Esempio n. 1
0
class SpriteGroupModule(EbModule.EbModule):
    _name = "Sprite Groups"
    def __init__(self):
        self._grPtrTbl = EbTable(0xef133f)
        self._grPalTbl = EbTable(0xc30000)
        self._groups = None
    def freeRanges(self):
        return [(0x2f1a7f, 0x2f4a3f),
                (0x110000, 0x11ffff),
                (0x120000, 0x12ffff),
                (0x130000, 0x13ffff),
                (0x140000, 0x14ffff),
                (0x150000, 0x154fff)]
    def free(self):
        del(self._grPtrTbl)
        del(self._grPalTbl)
    def readFromRom(self, rom):
        self._grPtrTbl.readFromRom(rom)
        updateProgress(5)
        self._grPalTbl.readFromRom(rom)
        updateProgress(5)

        # Load the sprite groups
        self._groups = []
        pct = 40.0/self._grPtrTbl.height()
        for i in range(self._grPtrTbl.height()):
            # Note: this assumes that the SPT is written contiguously
            numSprites = 8
            # Assume that the last group only has 8 sprites
            if i < self._grPtrTbl.height()-1:
                numSprites = (self._grPtrTbl[i+1,0].val() -
                        self._grPtrTbl[i,0].val() - 9) / 2

            g = SpriteGroup(numSprites)
            g.readFromRom(rom, EbModule.toRegAddr(self._grPtrTbl[i,0].val()))
            self._groups.append(g)
            updateProgress(pct)
    def writeToProject(self, resourceOpener):
        # Write the palettes
        self._grPalTbl.writeToProject(resourceOpener)
        updateProgress(5)
        out = { }
        i = 0
        pct = 40.0/len(self._groups)
        for g in self._groups:
            out[i] = g.dump()
            img = g.toImage(self._grPalTbl[g.palette(),0].val())
            imgFile = resourceOpener("SpriteGroups/" + str(i).zfill(3), 'png')
            img.save(imgFile, 'png', transparency=0)
            imgFile.close()
            del(img)
            i += 1
            updateProgress(pct)
        yaml.dump(out, resourceOpener("sprite_groups", "yml"),
                Dumper=yaml.CSafeDumper)
        updateProgress(5)
    def readFromProject(self, resourceOpener):
        self._grPalTbl.readFromProject(resourceOpener)
        updateProgress(5)
        input = yaml.load(resourceOpener("sprite_groups", "yml"),
                Loader=yaml.CSafeLoader)
        numGroups = len(input)
        self._groups = []
        pct = 45.0/numGroups
        for i in range(numGroups):
            g = SpriteGroup(16)
            g.load(input[i])
            img = Image.open(
                    resourceOpener("SpriteGroups/" + str(i).zfill(3), "png"))
            g.fromImage(img)
            palData = img.getpalette()
            del(img)
            self._groups.append(g)
            pal = [ ]

            # Read the palette from the image
            for i in range(1, 16):
                pal.append((palData[i*3], palData[i*3+1], palData[i*3+2]))
            # Assign the palette number to the sprite
            for i in range(8):
                if pal == self._grPalTbl[i,0].val()[1:]:
                    g.setPalette(i)
                    break
            else:
                # Error, this image uses an invalid palette
                raise RuntimeException("Sprite Group #" + i
                        + "uses an invalid palette.")
            updateProgress(pct)
            
    def writeToRom(self, rom):
        numGroups = len(self._groups)
        self._grPtrTbl.clear(numGroups)
        with DataBlock(sum(map(
            lambda x: x.blockSize(), self._groups))) as block:
            loc = 0
            i = 0
            # Write all the groups to the block, and sprites to rom
            pct = 40.0 / numGroups
            for g in self._groups:
                g.writeSpritesToFree(rom)
                g.writeToBlock(block, loc)
                self._grPtrTbl[i,0].setVal(loc)
                loc += g.blockSize()
                i += 1
                updateProgress(pct)
            # Write the block to rom and correct the group pointers
            addr = EbModule.toSnesAddr(block.writeToFree(rom))
            for i in range(self._grPtrTbl.height()):
                self._grPtrTbl[i,0].setVal(
                        self._grPtrTbl[i,0].val() + addr)
        # Write the pointer table
        self._grPtrTbl.writeToRom(rom)
        updateProgress(5)
        # Write the palettes
        self._grPalTbl.writeToRom(rom)
        updateProgress(5)
Esempio n. 2
0
class DoorModule(EbModule.EbModule):
    _name = "Doors"
    def __init__(self):
        self._ptrTbl = EbTable("DOOR_POINTER_TABLE")
        self._entries = [ ]
    def readFromRom(self, rom):
        self._ptrTbl.readFromRom(rom)
        updateProgress(5)
        pct = 45.0/(40*32)
        for i in range(self._ptrTbl.height()):
            loc = EbModule.toRegAddr(self._ptrTbl[i,0].val())
            entry = [ ]
            numDoors = rom.readMulti(loc, 2)
            loc += 2
            for j in range(numDoors):
                d = Door()
                try:
                    d.readFromRom(rom, loc)
                except ValueError:
                    # Invalid door entry. Some entries in EB are invalid.
                    # When we encounter one, just assume we've reached the end
                    # of this entry.
                    break
                entry.append(d)
                loc += 5
            self._entries.append(entry)
            i += 1
            updateProgress(pct)
    def writeToProject(self, resourceOpener):
        out = dict()
        x = y = 0
        rowOut = dict()
        pct = 45.0/(40*32)
        for entry in self._entries:
            if not entry:
                rowOut[x%32] = None
            else:
                rowOut[x%32] = map(lambda z: z.dump(), entry)
            if (x % 32) == 31:
                # Start new row
                out[y] = rowOut
                x = 0
                y += 1
                rowOut = dict()
            else:
                x += 1
            updateProgress(pct)
        with resourceOpener("map_doors", "yml") as f:
            s = yaml.dump(out, default_flow_style=False, Dumper=yaml.CSafeDumper)
            s = sub("Event Flag: (\d+)",
                    lambda i: "Event Flag: " + hex(int(i.group(0)[12:])), s)
            f.write(s)
        updateProgress(5)
    def readFromProject(self, resourceOpener):
        self._entries = []
        pct = 45.0/(40*32)
        with resourceOpener("map_doors", "yml") as f:
            updateProgress(5)
            input = yaml.load(f, Loader=yaml.CSafeLoader)
            for y in input:
                row = input[y]
                for x in row:
                    if row[x] == None:
                        self._entries.append(None)
                    else:
                        entry = []
                        for door in row[x]:
                            d = Door()
                            d.load(door)
                            entry.append(d)
                        self._entries.append(entry)
                    updateProgress(pct)
    def writeToRom(self, rom):
        self._ptrTbl.clear(32*40)
        destWriteLoc = 0xF0000
        destRangeEnd = 0xF58EE # TODO Is this correct? Can we go more?
        destLocs = dict()
        emptyEntryPtr = EbModule.toSnesAddr(rom.writeToFree([0, 0]))
        pct = 45.0/(40*32)
        i=0
        for entry in self._entries:
            if (entry == None) or (not entry):
                self._ptrTbl[i,0].setVal(emptyEntryPtr)
            else:
                entryLen = len(entry)
                writeLoc = rom.getFreeLoc(2 + entryLen*5)
                self._ptrTbl[i,0].setVal(EbModule.toSnesAddr(writeLoc))
                rom[writeLoc] = entryLen & 0xff
                rom[writeLoc+1] = entryLen >> 8
                writeLoc += 2
                for door in entry:
                    destWriteLoc += door.writeToRom(rom, writeLoc, destWriteLoc,
                            destRangeEnd, destLocs)
                    writeLoc += 5
            i += 1
            updateProgress(pct)
        self._ptrTbl.writeToRom(rom)
        # Mark any remaining space as free
        if destWriteLoc < destRangeEnd:
            rom.addFreeRanges([(destWriteLoc, destRangeEnd)])
        updateProgress(5)
Esempio n. 3
0
class MapModule(EbModule.EbModule):
    _name = "Map"
    _MAP_PTRS_PTR_ADDR = 0xa1db
    _LOCAL_TSET_ADDR = 0x175000
    _MAP_HEIGHT = 320
    _MAP_WIDTH = 256

    def __init__(self):
        self._tiles = []
        self._mapSecTsetPalsTbl = EbTable(0xD7A800)
        self._mapSecMusicTbl = EbTable(0xDCD637)
        self._mapSecMiscTbl = EbTable(0xD7B200)
        self._mapSecTownMapTbl = EbTable(0xEFA70F)

        self.teleport = ValuedIntTableEntry(None, None,
                ["Enabled", "Disabled"])
        self.townmap = ValuedIntTableEntry(None, None,
                ["None", "Onett", "Twoson", "Threed", "Fourside", "Scaraba",
                "Summers", "None 2"])
        self.setting = ValuedIntTableEntry(None, None,
                ["None", "Indoors", "Exit Mouse usable",
                "Lost Underworld sprites", "Magicant sprites", "Robot sprites",
                "Butterflies", "Indoors and Butterflies"])

        self.townmap_image = ValuedIntTableEntry(None, None,
                ["None", "Onett", "Twoson", "Threed", "Fourside", "Scaraba",
                "Summers" ])
        self.townmap_arrow = ValuedIntTableEntry(None, None,
                ["None", "Up", "Down", "Right", "Left"])
    def readFromRom(self, rom):
        # Read map tiles
        map_ptrs_addr = \
            EbModule.toRegAddr(rom.readMulti(self._MAP_PTRS_PTR_ADDR, 3))
        map_addrs = map(lambda x: \
            EbModule.toRegAddr(rom.readMulti(map_ptrs_addr+x*4,4)), \
            range(8))
        self._tiles = map(
                lambda y: rom.readList(map_addrs[y%8] + ((y>>3)<<8),
                    self._MAP_WIDTH).tolist(),
                range(self._MAP_HEIGHT))
        k = self._LOCAL_TSET_ADDR
        for i in range(self._MAP_HEIGHT>>3):
            for j in range(self._MAP_WIDTH):
                self._tiles[i<<3][j] |= (rom[k] & 3) << 8
                self._tiles[(i<<3)|1][j] |= ((rom[k] >> 2) & 3) << 8
                self._tiles[(i<<3)|2][j] |= ((rom[k] >> 4) & 3) << 8
                self._tiles[(i<<3)|3][j] |= ((rom[k] >> 6) & 3) << 8
                self._tiles[(i<<3)|4][j] |= (rom[k+0x3000] & 3) << 8
                self._tiles[(i<<3)|5][j] |= ((rom[k+0x3000] >> 2) & 3) << 8
                self._tiles[(i<<3)|6][j] |= ((rom[k+0x3000] >> 4) & 3) << 8
                self._tiles[(i<<3)|7][j] |= ((rom[k+0x3000] >> 6) & 3) << 8
                k += 1
        updateProgress(25)
        # Read sector data
        self._mapSecTsetPalsTbl.readFromRom(rom)
        updateProgress(25.0/4)
        self._mapSecMusicTbl.readFromRom(rom)
        updateProgress(25.0/4)
        self._mapSecMiscTbl.readFromRom(rom)
        updateProgress(25.0/4)
        self._mapSecTownMapTbl.readFromRom(rom)
        updateProgress(25.0/4)
    def writeToRom(self, rom):
        map_ptrs_addr = \
            EbModule.toRegAddr(rom.readMulti(self._MAP_PTRS_PTR_ADDR, 3))
        map_addrs = map(lambda x: \
            EbModule.toRegAddr(rom.readMulti(map_ptrs_addr+x*4,4)), \
            range(8))
        for i in range(self._MAP_HEIGHT):
            rom.write(map_addrs[i%8] + ((i>>3)<<8), map(lambda x: x & 0xff,
                self._tiles[i]))
        k = self._LOCAL_TSET_ADDR
        for i in range(self._MAP_HEIGHT>>3):
            for j in range(self._MAP_WIDTH):
                c = ((self._tiles[i<<3][j] >> 8)
                        | ((self._tiles[(i<<3)|1][j] >> 8) << 2)
                        | ((self._tiles[(i<<3)|2][j] >> 8) << 4)
                        | ((self._tiles[(i<<3)|3][j] >> 8) << 6))
                rom.write(k, c)
                c = ((self._tiles[(i<<3)|4][j] >> 8)
                        | ((self._tiles[(i<<3)|5][j] >> 8) << 2)
                        | ((self._tiles[(i<<3)|6][j] >> 8) << 4)
                        | ((self._tiles[(i<<3)|7][j] >> 8) << 6))
                rom.write(k+0x3000, c)
                k += 1
        updateProgress(25)
        # Write sector data
        self._mapSecTsetPalsTbl.writeToRom(rom)
        updateProgress(25.0/4)
        self._mapSecMusicTbl.writeToRom(rom)
        updateProgress(25.0/4)
        self._mapSecMiscTbl.writeToRom(rom)
        updateProgress(25.0/4)
        self._mapSecTownMapTbl.writeToRom(rom)
        updateProgress(25.0/4)
    def writeToProject(self, resourceOpener):
        # Write map tiles
        with resourceOpener("map_tiles", "map") as f:
            for row in self._tiles:
                f.write(hex(row[0])[2:].zfill(3))
                for tile in row[1:]:
                    f.write(" ")
                    f.write(hex(tile)[2:].zfill(3))
                f.write("\n")
        updateProgress(25.0)
        # Write sector data
        out = dict()
        for i in range(self._mapSecTsetPalsTbl.height()):
            self.teleport.setVal(self._mapSecMiscTbl[i,0].val() >> 7)
            self.townmap.setVal((self._mapSecMiscTbl[i,0].val() >> 3) & 7)
            self.setting.setVal(self._mapSecMiscTbl[i,0].val() & 3)
            self.townmap_image.setVal(self._mapSecTownMapTbl[i,0].val() & 0xf)
            self.townmap_arrow.setVal(self._mapSecTownMapTbl[i,0].val() >> 4)
            out[i] = {
                    "Tileset": self._mapSecTsetPalsTbl[i,0].val() >> 3,
                    "Palette": self._mapSecTsetPalsTbl[i,0].val() & 7,
                    "Music": self._mapSecMusicTbl[i,0].dump(),
                    "Teleport": self.teleport.dump(),
                    "Town Map": self.townmap.dump(),
                    "Setting": self.setting.dump(),
                    "Item": self._mapSecMiscTbl[i,1].dump(),
                    "Town Map Image": self.townmap_image.dump(),
                    "Town Map Arrow": self.townmap_arrow.dump(),
                    "Town Map X": self._mapSecTownMapTbl[i,1].dump(),
                    "Town Map Y": self._mapSecTownMapTbl[i,2].dump() }
        updateProgress(12.5)
        with resourceOpener("map_sectors", "yml") as f:
            yaml.dump(out, f, Dumper=yaml.CSafeDumper, default_flow_style=False)
        updateProgress(12.5)
    def readFromProject(self, resourceOpener):
        # Read map data
        with resourceOpener("map_tiles", "map") as f:
            self._tiles = map(lambda y:
                    map(lambda x: int(x, 16), y.split(" ")),
                    f.readlines())
        updateProgress(25)
        # Read sector data
        self._mapSecTsetPalsTbl.clear(2560)
        self._mapSecMusicTbl.clear(2560)
        self._mapSecMiscTbl.clear(2560)
        self._mapSecTownMapTbl.clear(2560)
        pct = (25.0/2560)
        with resourceOpener("map_sectors", "yml") as f:
            input = yaml.load(f, Loader=yaml.CSafeLoader)
            for i in input:
                entry = input[i]
                self._mapSecTsetPalsTbl[i,0].setVal(
                        (entry["Tileset"] << 3) | entry["Palette"])
                self._mapSecMusicTbl[i,0].load(entry["Music"])
                self._mapSecMiscTbl[i,1].load(entry["Item"])
                self.teleport.load(entry["Teleport"])
                self.townmap.load(entry["Town Map"])
                self.setting.load(entry["Setting"])
                self._mapSecMiscTbl[i,0].setVal((self.teleport.val() << 7)
                        | (self.townmap.val() << 3) | self.setting.val())
                self.townmap_image.load(entry["Town Map Image"])
                self.townmap_arrow.load(entry["Town Map Arrow"])
                self._mapSecTownMapTbl[i,0].setVal(
                        (self.townmap_arrow.val() << 4) |
                        (self.townmap_image.val() & 0xf))
                self._mapSecTownMapTbl[i,1].load(entry["Town Map X"])
                self._mapSecTownMapTbl[i,2].load(entry["Town Map Y"])
                updateProgress(pct)
    def upgradeProject(self, oldVersion, newVersion, rom, resourceOpenerR,
            resourceOpenerW):
        global updateProgress
        def replaceField(fname, oldField, newField, valueMap):
            if newField == None:
                newField = oldField
            valueMap = dict((k, v) for k,v in valueMap.iteritems())
            with resourceOpenerR(fname, 'yml') as f:
                data = yaml.load(f, Loader=yaml.CSafeLoader)
                for i in data:
                    if data[i][oldField] in valueMap:
                        data[i][newField] = valueMap[data[i][oldField]].lower()
                    else:
                        data[i][newField] = data[i][oldField]
                    if newField != oldField:
                        del data[i][oldField]
            with resourceOpenerW(fname, 'yml') as f:
                yaml.dump(data, f, Dumper=yaml.CSafeDumper,
                        default_flow_style=False)

        if oldVersion == newVersion:
            updateProgress(100)
            return
        elif oldVersion <= 2:
            replaceField("map_sectors", "Town Map", None,
                    { "scummers": "summers" })

            # Need to add the Town Map Image/Arrow/X/Y fields
            tmp = updateProgress
            updateProgress = lambda x: None
            self.readFromRom(rom)
            updateProgress = tmp

            with resourceOpenerR("map_sectors", 'yml') as f:
                data = yaml.load(f, Loader=yaml.CSafeLoader)
                for i in data:
                    self.townmap_image.setVal(self._mapSecTownMapTbl[i,0].val() & 0xf)
                    self.townmap_arrow.setVal(self._mapSecTownMapTbl[i,0].val() >> 4)
                    data[i]["Town Map Image"] = self.townmap_image.dump()
                    data[i]["Town Map Arrow"] = self.townmap_arrow.dump()
                    data[i]["Town Map X"] = self._mapSecTownMapTbl[i,1].dump()
                    data[i]["Town Map Y"] = self._mapSecTownMapTbl[i,2].dump()
            with resourceOpenerW("map_sectors", 'yml') as f:
                yaml.dump(data, f, Dumper=yaml.CSafeDumper,
                        default_flow_style=False)

            self.upgradeProject(3, newVersion, rom, resourceOpenerR,
                    resourceOpenerW)
        else:
            self.upgradeProject(oldVersion+1, newVersion, rom, resourceOpenerR,
                                                            resourceOpenerW)
Esempio n. 4
0
class MapSpriteModule(EbModule.EbModule):
    _name = "Map Sprites"
    _PTR_LOC = 0x2261
    def __init__(self):
        self._ptrTbl = EbTable("SPRITE_PLACEMENT_PTR_TABLE")
        self._entries = [ ]
    def readFromRom(self, rom):
        ptr = EbModule.toRegAddr(rom.readMulti(self._PTR_LOC, 3))
        updateProgress(5)
        self._ptrTbl.readFromRom(rom, ptr)
        pct = 45.0/(40*32)
        for i in range(self._ptrTbl.height()):
            loc = self._ptrTbl[i,0].val()
            # Format: AA AA [BB BB YY XX]
            # AA = # of entries. BB = TPT. YY = y pos. XX = x pos.
            if loc != 0:
                loc |= 0x0F0000
                entry = [ ]
                size = rom.readMulti(loc, 2)
                loc += 2
                for i in range(size):
                    entry.append(SpritePlacement(
                        rom.readMulti(loc, 2),
                        rom[loc+3], rom[loc+2]))
                    loc += 4
                self._entries.append(entry)
            else:
                self._entries.append(None)
            updateProgress(pct)
    def writeToProject(self, resourceOpener):
        out = dict()
        x = y = 0
        rowOut = dict()
        pct = 45.0/(40*32)
        for entry in self._entries:
            if entry != None:
                rowOut[x%32] = map(
                        lambda sp: {
                            "NPC ID": sp.npcID,
                            "X": sp.x,
                            "Y": sp.y },
                        entry)
            else:
                rowOut[x%32] = None
            if (x % 32) == 31:
                # Start next row
                out[y] = rowOut
                x = 0
                y += 1
                rowOut = dict()
            else:
                x += 1
            updateProgress(pct)
        with resourceOpener("map_sprites", "yml") as f:
            yaml.dump(out, f, Dumper=yaml.CSafeDumper)
        updateProgress(5)
    def readFromProject(self, resourceOpener):
        self._entries = []
        pct = 45.0/(40*32)
        with resourceOpener("map_sprites", "yml") as f:
            input = yaml.load(f, Loader=yaml.CSafeLoader)
            updateProgress(5)
            for y in input:
                row = input[y]
                for x in row:
                    if row[x] == None:
                        self._entries.append(None)
                    else:
                        self._entries.append(map(lambda x: SpritePlacement(
                            x["NPC ID"], x["X"], x["Y"]),
                            row[x]))
                    updateProgress(pct)
    def writeToRom(self, rom):
        self._ptrTbl.clear(32*40)
        writeLoc = 0xf61e7
        writeRangeEnd = 0xf8984
        i = 0
        pct = 45.0/(40*32)
        for entry in self._entries:
            if (entry == None) or (not entry):
                self._ptrTbl[i,0].setVal(0)
            else:
                entryLen = len(entry)
                with DataBlock(2 + entryLen*4) as block:
                    block[0] = entryLen & 0xff
                    block[1] = entryLen >> 8
                    j = 2
                    for sprite in entry:
                        block[j] = sprite.npcID & 0xff
                        block[j+1] = sprite.npcID >> 8
                        block[j+2] = sprite.y
                        block[j+3] = sprite.x
                        j += 4
                    if writeLoc + len(block) > writeRangeEnd:
                        # TODO Error, not enough space
                        raise RuntimeError("Not enough map sprite space")
                    else:
                        block.writeToRom(rom, writeLoc)
                        self._ptrTbl[i,0].setVal(writeLoc & 0xffff)
                        writeLoc += len(block)
            updateProgress(pct)
            i += 1
        loc = self._ptrTbl.writeToFree(rom)
        rom.writeMulti(self._PTR_LOC, EbModule.toSnesAddr(loc), 3)
        # Mark any remaining space as free
        if writeLoc < writeRangeEnd:
            rom.addFreeRanges([(writeLoc, writeRangeEnd)])
        updateProgress(5)
Esempio n. 5
0
class EnemyModule(EbModule.EbModule):
    _name = "Enemies"
    _ASMPTR_GFX = 0x2ee0b
    _REGPTR_GFX = [ 0x2ebe0, 0x2f014, 0x2f065 ]
    _ASMPTR_PAL = 0x2ef74
    def __init__(self):
        self._enemyCfgTable = EbTable(0xd59589)
        self._bsPtrTbl = EbTable(0xce62ee)
        self._bsPalsTable = EbTable(0xce6514)
        self._enemyGroupTbl = EbTable(0xD0C60D)
        self._enemyGroupBgTbl = EbTable(0xCBD89A)

        self._bsprites = [ ]
        self._bsPals = [ ]
        self._enemyGroups = [ ]
    def readFromRom(self, rom):
        self._bsPtrTbl.readFromRom(rom,
                EbModule.toRegAddr(EbModule.readAsmPointer(rom,
                    self._ASMPTR_GFX)))
        self._bsPalsTable.readFromRom(rom,
                EbModule.toRegAddr(EbModule.readAsmPointer(rom,
                    self._ASMPTR_PAL)))
        pct = 45.0/(self._bsPtrTbl.height()
                + self._bsPalsTable.height() + 1)
        self._enemyCfgTable.readFromRom(rom)
        updateProgress(pct)
        # Read the palettes
        for i in range(self._bsPalsTable.height()):
            pal = EbPalettes(1,16)
            pal.set(0, self._bsPalsTable[i,0].val())
            self._bsPals.append(pal)
            updateProgress(pct)
        # Read the sprites
        for i in range(self._bsPtrTbl.height()):
            with EbCompressedData() as bsb:
                bsb.readFromRom(rom,
                        EbModule.toRegAddr(self._bsPtrTbl[i,0].val()))
                bs = EbBattleSprite()
                bs.readFromBlock(bsb, self._bsPtrTbl[i,1].val())
                self._bsprites.append(bs)
            updateProgress(pct)

        # Read the group data
        self._enemyGroupTbl.readFromRom(rom)
        self._enemyGroupBgTbl.readFromRom(rom)
        self._enemyGroups = [ ]
        pct = 5.0/self._enemyGroupTbl.height()
        for i in range(self._enemyGroupTbl.height()):
            group = [ ]
            ptr = EbModule.toRegAddr(self._enemyGroupTbl[i,0].val())
            while(rom[ptr] != 0xff):
                group.append((rom.readMulti(ptr+1,2), rom[ptr]))
                ptr += 3
            self._enemyGroups.append(group)
            updateProgress(pct)
    def freeRanges(self):
        return [(0x0d0000, 0x0dffff), # Battle Sprites
                (0x0e0000, 0x0e6913), # Battle Sprites Cont'd & Btl Spr. Pals
                (0x10d52d, 0x10dfb3)] # Enemy Group Data
    def writeToRom(self, rom):
        pct = 40.0/(len(self._bsprites) + len(self._bsPals) + 3)
        # Write the main table
        self._enemyCfgTable.writeToRom(rom)
        updateProgress(pct)
        # Write the gfx ptr table
        self._bsPtrTbl.clear(len(self._bsprites))
        i = 0
        for bs in self._bsprites:
            with EbCompressedData(bs.sizeBlock()) as bsb:
                bs.writeToBlock(bsb)
                self._bsPtrTbl[i,0].setVal(EbModule.toSnesAddr(
                    bsb.writeToFree(rom)))
            self._bsPtrTbl[i,1].setVal(bs.size())
            i += 1
            updateProgress(pct)
        gfxAddr = EbModule.toSnesAddr(self._bsPtrTbl.writeToFree(rom))
        EbModule.writeAsmPointer(rom, self._ASMPTR_GFX, gfxAddr)
        updateProgress(pct)
        for p in self._REGPTR_GFX:
            rom.writeMulti(p, gfxAddr, 3)
        # Write the pal table
        self._bsPalsTable.clear(len(self._bsPals))
        i = 0
        for p in self._bsPals:
            self._bsPalsTable[i,0].setVal(p.getSubpal(0))
            i += 1
            updateProgress(pct)
        EbModule.writeAsmPointer(rom, self._ASMPTR_PAL,
                EbModule.toSnesAddr(self._bsPalsTable.writeToFree(rom)))
        updateProgress(pct)
        # Write the groups
        self._enemyGroupBgTbl.writeToRom(rom)
        updateProgress(5)
        i=0
        for group in self._enemyGroups:
            loc = rom.getFreeLoc(len(group)*3 + 1)
            self._enemyGroupTbl[i,0].setVal(EbModule.toSnesAddr(loc))
            i += 1
            for enemyID, amount in group:
                rom[loc] = amount
                rom[loc+1] = enemyID & 0xff
                rom[loc+2] = enemyID >> 8
                loc += 3
            rom[loc] = 0xff
        self._enemyGroupTbl.writeToRom(rom)
        updateProgress(5)
    def writeToProject(self, resourceOpener):
        pct = 40.0/(self._enemyCfgTable.height() + 1)
        # First, write the Enemy Configuration Table
        self._enemyCfgTable.writeToProject(resourceOpener, [4,14])
        updateProgress(pct)

        # Next, write the battle sprite images
        for i in range(self._enemyCfgTable.height()):
            if self._enemyCfgTable[i,4].val() > 0:
                self._bsprites[self._enemyCfgTable[i,4].val()-1].writeToProject(
                        resourceOpener, i,
                        self._bsPals[self._enemyCfgTable[i,14].val()].getSubpal(0))
            updateProgress(pct)

        # Now write the groups
        out = dict()
        i = 0
        pct = 5.0/len(self._enemyGroups)
        for group in self._enemyGroups:
            entry = dict()
            for j in range(1,4):
                field = self._enemyGroupTbl[i,j]
                entry[field.name] = field.dump()
            for j in range(2):
                field = self._enemyGroupBgTbl[i,j]
                entry[field.name] = field.dump()
            enemyList = dict()
            j = 0
            for enemyID, amount in group:
                enemyEntry = dict()
                enemyEntry["Enemy"] = enemyID
                enemyEntry["Amount"] = amount
                enemyList[j] = enemyEntry
                j += 1
            entry["Enemies"] = enemyList
            out[i] = entry
            i += 1
            updateProgress(pct)
        with resourceOpener("enemy_groups", "yml") as f:
            yaml.dump(out, f, Dumper=yaml.CSafeDumper)
        updateProgress(5)
    def readFromProject(self, resourceOpener):
        # First, read the Enemy Configuration Table
        self._enemyCfgTable.readFromProject(resourceOpener)
        pct = 40.0/(self._enemyCfgTable.height())

        # Second, read the Battle Sprites
        bsHashes = dict()
        bsNextNum = 1
        palNextNum = 0
        for i in range(self._enemyCfgTable.height()):
            bs = EbBattleSprite()
            pal = EbPalettes(1,16)
            try:
                bs.readFromProject(resourceOpener, i, pal)
                # Add the battle sprite
                try:
                    #self._enemyCfgTable[i,4].set(self._bsprites.index(bs))
                    bsNum = bsHashes[bs._sprite._spriteHash]
                    self._enemyCfgTable[i,4].setVal(bsNum)
                except KeyError:
                    self._bsprites.append(bs)
                    self._enemyCfgTable[i,4].setVal(bsNextNum)
                    bsHashes[bs._sprite._spriteHash] = bsNextNum
                    bsNextNum += 1
                # Add the palette
                # TODO should probably use hash table here too?
                #      then again, I don't think it's actually a bottleneck
                try:
                    self._enemyCfgTable[i,14].setVal(self._bsPals.index(pal))
                except ValueError:
                    self._bsPals.append(pal)
                    self._enemyCfgTable[i,14].setVal(palNextNum)
                    palNextNum += 1
            except IOError:
                # No battle sprite PNG
                self._enemyCfgTable[i,4].setVal(0)
                self._enemyCfgTable[i,14].setVal(0)
            updateProgress(pct)

        # Third, read the groups
        self._enemyGroupTbl.readFromProject(resourceOpener, "enemy_groups")
        updateProgress(2)
        self._enemyGroupBgTbl.readFromProject(resourceOpener, "enemy_groups")
        updateProgress(2)
        self._enemyGroups = [ ]
        pct = 4.0/484
        with resourceOpener("enemy_groups", "yml") as f:
            input = yaml.load(f, Loader=yaml.CSafeLoader)
            updateProgress(2)
            for group in input:
                tmp1 = input[group]["Enemies"]
                enemyList = [ ]
                i = 0
                for enemy in tmp1:
                    tmp2 = tmp1[i]
                    enemyList.append((tmp2["Enemy"], tmp2["Amount"]))
                    i += 1
                self._enemyGroups.append(enemyList)
                updateProgress(pct)
Esempio n. 6
0
class BattleBgModule(EbModule.EbModule):
    _name = "Battle Backgrounds"
    _ASMPTRS_GFX = [0x2d1ba, 0x2d4dc, 0x2d8c3, 0x4a3ba]
    _ASMPTRS_ARR = [0x2d2c1, 0x2d537, 0x2d91f, 0x4a416]
    _ASMPTRS_PAL = [0x2d3bb, 0x2d61b, 0x2d7e8, 0x2d9e8, 0x4a4d0]
    def __init__(self):
        self._bbgGfxPtrTbl = EbTable("BATTLEBG_GFX_POINTERS")
        self._bbgArrPtrTbl = EbTable("BATTLEBG_ARR_POINTERS")
        self._bbgPalPtrTbl = EbTable("BATTLEBG_PALETTE_POINTERS")
        self._bbgScrollTbl = EbTable("BG_SCROLLING_TABLE")
        self._bbgDistorTbl = EbTable("BG_DISTORTION_TABLE")
        self._bbgTbl = EbTable("BG_DATA_TABLE")
    def free(self):
        del(self._bbgGfxPtrTbl)
        del(self._bbgArrPtrTbl)
        del(self._bbgPalPtrTbl)
        del(self._bbgTbl)

        del(self._bbgGfxArrs)
        del(self._bbgPals)
    def readFromRom(self, rom):
        self._bbgTbl.readFromRom(rom)
        pct = 50.0/(6+self._bbgTbl.height())
        self._bbgGfxPtrTbl.readFromRom(rom,
                EbModule.toRegAddr(EbModule.readAsmPointer(rom,
                    self._ASMPTRS_GFX[0])))
        updateProgress(pct)
        self._bbgArrPtrTbl.readFromRom(rom,
                EbModule.toRegAddr(EbModule.readAsmPointer(rom, 
                    self._ASMPTRS_ARR[0])))
        updateProgress(pct)
        self._bbgPalPtrTbl.readFromRom(rom,
                EbModule.toRegAddr(EbModule.readAsmPointer(rom, 
                    self._ASMPTRS_PAL[0])))
        updateProgress(pct)

        self._bbgGfxArrs = [ None for i in range(self._bbgGfxPtrTbl.height()) ]
        self._bbgPals = [ None for i in range(self._bbgPalPtrTbl.height()) ]
        updateProgress(pct)
        self._bbgScrollTbl.readFromRom(rom)
        updateProgress(pct)
        self._bbgDistorTbl.readFromRom(rom)
        updateProgress(pct)
        for i in range(self._bbgTbl.height()):
            gfxNum = self._bbgTbl[i,0].val()
            colorDepth = self._bbgTbl[i,2].val()
            if (self._bbgGfxArrs[gfxNum] == None):
                # Max size used in rom: 421 (2bpp) 442 (4bpp)
                tg = EbTileGraphics(512, 8, colorDepth)
                with EbCompressedData() as tgb:
                    tgb.readFromRom(rom, EbModule.toRegAddr(
                        self._bbgGfxPtrTbl[gfxNum,0].val()))
                    tg.readFromBlock(tgb)
                a = EbArrangement(32, 32)
                with EbCompressedData() as ab:
                    ab.readFromRom(rom, EbModule.toRegAddr(
                        self._bbgArrPtrTbl[gfxNum,0].val()))
                    a.readFromBlock(ab)
                
                self._bbgGfxArrs[gfxNum] = (tg, a)
            palNum = self._bbgTbl[i,1].val()
            if (self._bbgPals[palNum] == None):
                with DataBlock(32) as pb:
                    pb.readFromRom(rom,
                            EbModule.toRegAddr(self._bbgPalPtrTbl[palNum,0].val()))
                    p = EbPalettes(1, 16)
                    p.readFromBlock(pb)
                    self._bbgPals[palNum] = p
            updateProgress(pct)
    def writeToProject(self, resourceOpener):
        pct = 50.0/(3+self._bbgTbl.height())
        self._bbgTbl.writeToProject(resourceOpener, hiddenColumns=[0,1])
        updateProgress(pct)
        self._bbgScrollTbl.writeToProject(resourceOpener)
        updateProgress(pct)
        self._bbgDistorTbl.writeToProject(resourceOpener)
        updateProgress(pct)
        # Export BGs by table entry
        for i in range(self._bbgTbl.height()):
            (tg, a) = self._bbgGfxArrs[self._bbgTbl[i,0].val()]
            pal = self._bbgTbl[i,1].val()
            img = a.toImage(tg, self._bbgPals[pal])
            imgFile = resourceOpener('BattleBGs/' + str(i).zfill(3), 'png')
            img.save(imgFile, 'png')
            imgFile.close()
            del(img)
            updateProgress(pct)
    def readFromProject(self, resourceOpener):
        self._bbgTbl.readFromProject(resourceOpener)
        pct = 50.0/(2+self._bbgTbl.height())
        self._bbgScrollTbl.readFromProject(resourceOpener)
        updateProgress(pct)
        self._bbgDistorTbl.readFromProject(resourceOpener)
        updateProgress(pct)
        self._bbgGfxArrs = []
        self._bbgPals = []
        for i in range(self._bbgTbl.height()):
            img = Image.open(
                    resourceOpener('BattleBGs/' + str(i).zfill(3), 'png'))

            np = EbPalettes(1, 16)
            colorDepth = self._bbgTbl[i,2].val()
            # Max size used in rom: 421 (2bpp) 442 (4bpp)
            ntg = EbTileGraphics(512, 8, colorDepth)
            na = EbArrangement(32, 32)
            na.readFromImage(img, np, ntg)
            j=0
            for (tg, a) in self._bbgGfxArrs:
                if (tg == ntg) and (a == na):
                    self._bbgTbl[i,0].setVal(j)
                    break
                j += 1
            else:
                self._bbgGfxArrs.append((ntg, na))
                self._bbgTbl[i,0].setVal(j)
            j=0
            for p in self._bbgPals:
                if (p == np):
                    self._bbgTbl[i,1].setVal(j)
                    break
                j += 1
            else:
                self._bbgPals.append((np))
                self._bbgTbl[i,1].setVal(j)
            updateProgress(pct)
    def freeRanges(self):
        return [(0xa0000,0xadca0), (0xb0000, 0xbd899)]
    def writeToRom(self, rom):
        self._bbgGfxPtrTbl.clear(len(self._bbgGfxArrs))
        self._bbgArrPtrTbl.clear(len(self._bbgGfxArrs))
        self._bbgPalPtrTbl.clear(len(self._bbgPals))

        # Write gfx+arrs
        i = 0
        pct = (50.0/3)/len(self._bbgGfxArrs)
        for (tg, a) in self._bbgGfxArrs:
            with EbCompressedData(tg.sizeBlock()) as tgb:
                tg.writeToBlock(tgb)
                self._bbgGfxPtrTbl[i,0].setVal(EbModule.toSnesAddr(
                    tgb.writeToFree(rom)))
            with EbCompressedData(a.sizeBlock()) as ab:
                a.writeToBlock(ab)
                self._bbgArrPtrTbl[i,0].setVal(EbModule.toSnesAddr(
                    ab.writeToFree(rom)))
            i += 1
            updateProgress(pct)
        EbModule.writeAsmPointers(rom, self._ASMPTRS_GFX,
                EbModule.toSnesAddr(self._bbgGfxPtrTbl.writeToFree(rom)))
        EbModule.writeAsmPointers(rom, self._ASMPTRS_ARR,
                EbModule.toSnesAddr(self._bbgArrPtrTbl.writeToFree(rom)))

        # Write pals
        i = 0
        pct = (50.0/3)/len(self._bbgPals)
        for p in self._bbgPals:
            with DataBlock(32) as pb:
                p.writeToBlock(pb)
                self._bbgPalPtrTbl[i,0].setVal(EbModule.toSnesAddr(
                    pb.writeToFree(rom)))
            i += 1
            updateProgress(pct)
        EbModule.writeAsmPointers(rom, self._ASMPTRS_PAL,
                EbModule.toSnesAddr(self._bbgPalPtrTbl.writeToFree(rom)))

        # Write the data table
        pct = (50.0/3)/3
        self._bbgTbl.writeToRom(rom)
        updateProgress(pct)
        self._bbgScrollTbl.writeToRom(rom)
        updateProgress(pct)
        self._bbgDistorTbl.writeToRom(rom)
        updateProgress(pct)
Esempio n. 7
0
class TilesetModule(EbModule.EbModule):
    _name = "Tilesets"
    def __init__(self):
        self._gfxPtrTbl = EbTable("MAP_DATA_TILESET_PTR_TABLE")
        self._arrPtrTbl = EbTable("MAP_DATA_TILE_ARRANGEMENT_PTR_TABLE")
        self._colPtrTbl = EbTable("MAP_DATA_TILE_COLLISION_PTR_TABLE")
        self._mapTsetTbl = EbTable("TILESET_TABLE")
        self._palPtrTbl = EbTable("MAP_PALETTE_PTR_TABLE")
        self._tsets = [ Tileset() for i in range(20) ]
    def freeRanges(self):
        return [(0x17c600, 0x17fbe7),
                (0x190000, 0x19fc17),
                (0x1b0000, 0x1bf2ea),
                (0x1c0000, 0x1cd636),
                (0x1d0000, 0x1dfecd),
                (0x1e0000, 0x1ef0e6),
                (0x1f0000, 0x1fc242)]
    def readFromRom(self, rom):
        self._gfxPtrTbl.readFromRom(rom)
        updateProgress(2)
        self._arrPtrTbl.readFromRom(rom)
        updateProgress(2)
        self._colPtrTbl.readFromRom(rom)
        updateProgress(2)
        self._mapTsetTbl.readFromRom(rom)
        updateProgress(2)
        self._palPtrTbl.readFromRom(rom)
        updateProgress(2)

        # Read tilesets
        pct = 30.0/len(self._tsets)
        i=0
        for tset in self._tsets:
            # Read data
            tset.readMinitilesFromRom(rom,
                    EbModule.toRegAddr(self._gfxPtrTbl[i,0].val()))
            tset.readArrangementsFromRom(rom,
                    EbModule.toRegAddr(self._arrPtrTbl[i,0].val()))
            tset.readCollisionsFromRom(rom,
                    EbModule.toRegAddr(self._colPtrTbl[i,0].val()))
            i += 1
            updateProgress(pct)

        # Read palettes
        pct = 10.0/self._mapTsetTbl.height()
        for i in range(self._mapTsetTbl.height()):
            drawTset = self._mapTsetTbl[i,0].val()
            # Each map tset has 8 maximum palettes
            # We'll just assume they all use 8 and read the garbage
            #romLoc = self._palPtrTbl[i,0].val()
            #for j in xrange(8):
            #    # Read the palette
            #    self._tsets[drawTset].readPaletteFromRom(rom, i, j,
            #            EbModule.toRegAddr(romLoc))
            #    romLoc += 0xc0

            # OK, as it turns out, all palettes need to be in the 1A bank
            # So we actually need to conserve space and not read garbage
            # Estimate the number of palettes for this map tileset
            if i == 31:
                #k = 0xDAFAA7 - self._palPtrTbl[i,0].val()
                k = 7
            else:
                k = self._palPtrTbl[i+1,0].val() - self._palPtrTbl[i,0].val()
                k /= 0xc0
            # Add the palettes
            romLoc = EbModule.toRegAddr(self._palPtrTbl[i,0].val())
            for j in range(k):
                # Read the palette
                self._tsets[drawTset].readPaletteFromRom(rom, i, j, romLoc)
                romLoc += 0xc0
            updateProgress(pct)

    def writeToRom(self, rom):
        numTsets = len(self._tsets)
        self._gfxPtrTbl.clear(numTsets)
        self._arrPtrTbl.clear(numTsets)
        self._colPtrTbl.clear(numTsets)
        self._mapTsetTbl.clear(32)
        self._palPtrTbl.clear(32)

        # Write gfx & arrs
        pct = 30.0/numTsets
        i=0
        for tset in self._tsets:
            self._gfxPtrTbl[i,0].setVal(EbModule.toSnesAddr(
                tset.writeMinitilesToFree(rom)))
            self._arrPtrTbl[i,0].setVal(EbModule.toSnesAddr(
               tset.writeArrangementsToFree(rom)))
            i += 1
            updateProgress(pct)
        self._gfxPtrTbl.writeToRom(rom)
        updateProgress(2)
        self._arrPtrTbl.writeToRom(rom)
        updateProgress(2)

        # Write collissions
        pct = 6.0/numTsets
        colLocs = dict()
        colWriteLoc = 0x180000
        colRangeEnd = 0x18f05d
        i=0
        for tset in self._tsets:
            with DataBlock(len(tset.col)*2) as colTable:
                j=0
                for c in tset.col:
                    hash = crc32(c)
                    try:
                        addr = colLocs[hash]
                    except KeyError:
                        if (colWriteLoc + 16) > colRangeEnd:
                            # TODO Error, not enough space for collisions
                            print "Ran out of collision space"
                            raise Exception
                            addr = 0
                        else:
                            colLocs[hash] = colWriteLoc
                            addr = colWriteLoc
                            rom.write(colWriteLoc, c)
                            colWriteLoc += 16
                    colTable[j] = addr & 0xff
                    colTable[j+1] = (addr >> 8) & 0xff
                    j += 2
                self._colPtrTbl[i,0].setVal(EbModule.toSnesAddr(
                    colTable.writeToFree(rom)))
                i += 1
            updateProgress(pct)
        self._colPtrTbl.writeToRom(rom)
        updateProgress(1)

        # Write the palettes, they need to be in the DA bank
        pct = 7.0/32
        palWriteLoc = 0x1a0000
        palRangeEnd = 0x1afaa6 # can we go more?
        # Write maps/drawing tilesets associations and map tset pals
        for i in range(32): # For each map tileset
            # Find the drawing tileset number for this map tileset
            drawTset = -1
            j = 0
            for tset in self._tsets:
                for (mt,mp,pal) in tset.pals:
                    if mt == i:
                        drawTset = j
                        break
                if drawTset != -1:
                    break
                j += 1
            else:
                # TODO Error, this drawing tileset isn't associated
                drawTset = 0
            self._mapTsetTbl[i,0].setVal(drawTset)
            # Write the palette data for this map tileset
            mtset_pals = [(mp,pal) for (mt,mp,pal)
                    in self._tsets[drawTset].pals if mt == i]
            mtset_pals.sort()
            # Let's take the easy way out and just write redundant flag pals
            # This will waste space but oh well
            # First, write the flag pals
            for (mp,pal) in mtset_pals:
                if pal.flag != 0:
                    if palWriteLoc + 0xc0 > palRangeEnd:
                        # TODO Error, not enough space for all these palettes
                        raise RuntimeError("Too many palettes")
                    pal.flagPal.writeToBlock(rom, palWriteLoc)
                    pal.flagPalPtr = palWriteLoc & 0xffff
                    palWriteLoc += 0xc0
            self._palPtrTbl[i,0].setVal(EbModule.toSnesAddr(palWriteLoc))
            # Now write the regular pals
            for (mp,pal) in mtset_pals:
                if palWriteLoc + 0xc0 > palRangeEnd:
                    # TODO Error, not enough space for all these palettes
                    raise RuntimeException("Too many palettes")
                pal.writeToBlock(rom, palWriteLoc)
                palWriteLoc += 0xc0
            updateProgress(pct)
        self._mapTsetTbl.writeToRom(rom)
        updateProgress(1)
        self._palPtrTbl.writeToRom(rom)
        updateProgress(1)

        # Might as well use any extra leftover space
        ranges = [(colWriteLoc, colRangeEnd), (palWriteLoc, palRangeEnd)]
        ranges = [(a,b) for (a,b) in ranges if a < b]
        rom.addFreeRanges(ranges)

    def writeToProject(self, resourceOpener):
        # Dump an additional YML with color0 data
        out = dict()
        for i in range(0,32): # For each map tset
            entry = dict()
            tset = None
            for ts in self._tsets:
                if ts.hasMapTileset(i):
                    tset = ts
                    break
            for (pN,p) in [(mp,p) for (mt,mp,p) in tset.pals if mt == i]:
                entry[pN] = p.dump()
            out[i] = entry
        with resourceOpener('map_palette_settings', 'yml') as f:
            s = yaml.dump(out, default_flow_style=False,
                    Dumper=yaml.CSafeDumper)
            s = sub("Event Flag: (\d+)",
                    lambda i: "Event Flag: " + hex(int(i.group(0)[12:])), s)
            f.write(s)
        updateProgress(5)

        # Dump the FTS files
        pct=45.0/len(self._tsets)
        i=0
        for tset in self._tsets:
            with resourceOpener('Tilesets/' + str(i).zfill(2), 'fts') as f:
                tset.writeToFTS(f)
            i += 1
            updateProgress(pct)
    def readFromProject(self, resourceOpener):
        i=0
        pct = 45.0/len(self._tsets)
        for tset in self._tsets:
            with resourceOpener('Tilesets/' + str(i).zfill(2), 'fts') as f:
                tset.readFromFTS(f)
            i += 1
            updateProgress(pct)
        with resourceOpener('map_palette_settings', 'yml') as f:
            input = yaml.load(f, Loader=yaml.CSafeLoader)
            for mtset in input: # For each map tileset
                # Get the draw (normal) tileset
                tset = None
                for ts in self._tsets:
                    if ts.hasMapTileset(mtset):
                        tset = ts
                        break
                # For each map palette
                mtset_pals = [(mp,p) for (mt,mp,p) in tset.pals if mt == mtset]
                for (pN,mtset_pal) in mtset_pals:
                    entry = input[mtset][pN]
                    mtset_pal.flag = entry["Event Flag"]
                    mtset_pal.flashEffect = entry["Flash Effect"]
                    mtset_pal.spritePalNum = entry["Sprite Palette"]
                    if mtset_pal.flag != 0:
                        mtset_pal.flagPal = MapPalette()
                        mtset_pal.flagPal.setFromString(entry["Event Palette"])
                        mtset_pal.flagPal.spritePalNum = entry["Sprite Palette"]
                updateProgress(5.0/32)
Esempio n. 8
0
class TownMapIconModule(EbModule.EbModule):
    _name = "Town Map Icon Positions"
    _ASMPTR_PTR_TBL = 0x4d464
    def __init__(self):
        self._ptrTbl = EbTable(0xE1F491)
        self._entries = [ ]
        self._entryIdField = ValuedIntTableEntry(None, None,
                ["Onett", "Twoson", "Threed", "Fourside", "Scaraba", "Summers"])
        self._iconField = ValuedIntTableEntry(None, None,
                ["0", "Hamburger Shop", "Bakery", "Hotel",
                "Restaurant", "Hospital", "Shop", "Dept Store", "Bus Stop",
                "South to Twoson", "North to Onett", "South to Threed",
                "West to Twoson", "East to Desert", "West to Desert",
                "East to Toto", "Hint", "Ness", "Small Ness",
                "North", "South", "West", "East" ])
    def freeRanges(self):
        return [(0x21f491, 0x21f580)] # Pointer Table and Data
    def readFromRom(self, rom):
        self._ptrTbl.readFromRom(rom,
                EbModule.toRegAddr(EbModule.readAsmPointer(rom,
                    self._ASMPTR_PTR_TBL)))
        updateProgress(5)
        for i in range(self._ptrTbl.height()):
            loc = EbModule.toRegAddr(self._ptrTbl[i,0].val())
            entry = []
            while True:
                x = rom[loc]
                if x == 0xff:
                    break
                y = rom[loc+1]
                icon = rom[loc+2]
                flag = rom.readMulti(loc+3, 2)
                entry.append((x, y, icon, flag))
                loc += 5
            self._entries.append(entry)
            i += 1
        updateProgress(45)
    def writeToRom(self, rom):
        self._ptrTbl.clear(6)
        i = 0
        for entry in self._entries:
            writeLoc = rom.getFreeLoc(len(entry)*5 + 1)
            self._ptrTbl[i,0].setVal(
                    EbModule.toSnesAddr(writeLoc))
            for (x, y, icon, flag) in entry:
                rom[writeLoc] = x
                rom[writeLoc+1] = y
                rom[writeLoc+2] = icon
                rom.writeMulti(writeLoc+3, flag, 2)
                writeLoc += 5
            rom[writeLoc] = 0xff
            i += 1
        updateProgress(45)
        EbModule.writeAsmPointer(rom, self._ASMPTR_PTR_TBL,
                EbModule.toSnesAddr(
                    self._ptrTbl.writeToFree(rom)))
        updateProgress(5)
    def readFromProject(self, resourceOpener):
        self._entries = [None] * 6
        with resourceOpener("TownMaps/icon_positions", "yml") as f:
            data = yaml.load(f, Loader=yaml.CSafeLoader)
            for name in data:
                entry = []
                for subEntry in data[name]:
                    self._iconField.load(subEntry["Icon"])
                    entry.append((
                        subEntry["X"],
                        subEntry["Y"],
                        self._iconField.val(),
                        subEntry["Event Flag"]))
                self._entryIdField.load(name)
                self._entries[self._entryIdField.val()] = entry
        updateProgress(50)
    def writeToProject(self, resourceOpener):
        out = dict()
        i = 0
        for entry in self._entries:
            outEntry = []
            for (x, y, icon, flag) in entry:
                self._iconField.setVal(icon)
                outEntry.append({
                    "X": x,
                    "Y": y,
                    "Icon": self._iconField.dump(),
                    "Event Flag": flag })
            self._entryIdField.setVal(i)
            out[self._entryIdField.dump()] = outEntry
            i += 1
        updateProgress(25)
        with resourceOpener("TownMaps/icon_positions", "yml") as f:
            s = yaml.dump(out, default_flow_style=False,
                    Dumper=yaml.CSafeDumper)
            s = sub("Event Flag: (\d+)",
                    lambda i: "Event Flag: " + hex(int(i.group(0)[12:])), s)
            f.write(s)
        updateProgress(25)
    def upgradeProject(self, oldVersion, newVersion, rom, resourceOpenerR,
            resourceOpenerW):
        global updateProgress
        if oldVersion == newVersion:
            updateProgress(100)
            return
        elif oldVersion <= 2:
            tmp = updateProgress
            updateProgress = lambda x: None
            self.readFromRom(rom)
            self.writeToProject(resourceOpenerW)
            updateProgress = tmp
            self.upgradeProject(3, newVersion, rom, resourceOpenerR,
                    resourceOpenerW)
        else:
            self.upgradeProject(oldVersion+1, newVersion, rom, resourceOpenerR,
                    resourceOpenerW)
Esempio n. 9
0
class MapEnemyModule(EbModule.EbModule):
    _name = "Map Enemies"

    def __init__(self):
        self._mapGroupPtrTbl = EbTable("ENEMY_PLACEMENT_GROUPS_PTR_TABLE")
        self._mapEnemyTbl = EbTable("ENEMY_PLACEMENT_DATA")

    def freeRanges(self):
        return [(0x10BBAC, 0x10C6AC)]  # Groups data

    def readFromRom(self, rom):
        self._mapEnemyTbl.readFromRom(rom)
        updateProgress(2.5)
        self._mapGroupPtrTbl.readFromRom(rom)
        updateProgress(2.5)

        # Read the groups
        pct = 45.0 / (self._mapGroupPtrTbl.height())
        self._mapGroups = []
        for i in range(self._mapGroupPtrTbl.height()):
            loc = EbModule.toRegAddr(self._mapGroupPtrTbl[i, 0].val())
            flag = rom.readMulti(loc, 2)
            rate1 = rom[loc + 2]
            rate2 = rom[loc + 3]
            loc += 4

            # Read the enemies/probabilities
            group1 = []
            if rate1 > 0:
                sum = 0
                while sum < 8:
                    prob = rom[loc]
                    enemy = rom.readMulti(loc + 1, 2)
                    sum += prob
                    loc += 3
                    group1.append((prob, enemy))
            group2 = []
            if rate2 > 0:
                sum = 0
                while sum < 8:
                    prob = rom[loc]
                    enemy = rom.readMulti(loc + 1, 2)
                    sum += prob
                    loc += 3
                    group2.append((prob, enemy))

            # Add to the list
            self._mapGroups.append((flag, rate1, rate2, group1, group2))
            updateProgress(pct)

    def writeToRom(self, rom):
        self._mapEnemyTbl.writeToRom(rom)
        updateProgress(2.5)
        self._mapGroupPtrTbl.clear(len(self._mapGroups))
        updateProgress(2.5)

        pct = 42.5 / len(self._mapGroups)
        i = 0
        for (flag, rate1, rate2, subg1, subg2) in self._mapGroups:
            size = 4
            if rate1 > 0:
                size += len(subg1) * 3
            if rate2 > 0:
                size += len(subg2) * 3
            loc = rom.getFreeLoc(size)
            self._mapGroupPtrTbl[i, 0].setVal(EbModule.toSnesAddr(loc))

            rom.writeMulti(loc, flag, 2)
            rom[loc + 2] = rate1
            rom[loc + 3] = rate2
            loc += 4
            for prob, egroup in subg1:
                rom[loc] = prob
                rom.writeMulti(loc + 1, egroup, 2)
                loc += 3
            for prob, egroup in subg2:
                rom[loc] = prob
                rom.writeMulti(loc + 1, egroup, 2)
                loc += 3
            i += 1
            updateProgress(pct)
        self._mapGroupPtrTbl.writeToRom(rom)
        updateProgress(2.5)

    def writeToProject(self, resourceOpener):
        self._mapEnemyTbl.writeToProject(resourceOpener)
        updateProgress(2.5)

        # Write the groups
        pct = 42.5 / len(self._mapGroups)
        out = dict()
        i = 0
        for (flag, rate1, rate2, group1, group2) in self._mapGroups:
            # Generate first enemy/prob list
            g1out = dict()
            j = 0
            for prob, enemy in group1:
                g1out[j] = {"Enemy Group": enemy, "Probability": prob}
                j += 1
            g2out = dict()
            j = 0
            for prob, enemy in group2:
                g2out[j] = {"Enemy Group": enemy, "Probability": prob}
                j += 1
            out[i] = {
                "Event Flag": flag,
                "Sub-Group 1 Rate": rate1,
                "Sub-Group 1": g1out,
                "Sub-Group 2 Rate": rate2,
                "Sub-Group 2": g2out,
            }
            i += 1
            updateProgress(pct)
        s = yaml.dump(out, Dumper=yaml.CSafeDumper)
        updateProgress(2.5)
        s = sub("Event Flag: (\d+)", lambda i: "Event Flag: " + hex(int(i.group(0)[12:])), s)
        with resourceOpener("map_enemy_groups", "yml") as f:
            f.write(s)
        updateProgress(2.5)

    def readFromProject(self, resourceOpener):
        self._mapEnemyTbl.readFromProject(resourceOpener)
        updateProgress(5)

        pct = 40.0 / 203
        self._mapGroups = []
        with resourceOpener("map_enemy_groups", "yml") as f:
            input = yaml.load(f, Loader=yaml.CSafeLoader)
            updateProgress(5)
            for gid in input:
                group = input[gid]
                flag = group["Event Flag"]
                rate1 = group["Sub-Group 1 Rate"]
                rate2 = group["Sub-Group 2 Rate"]

                subg1 = []
                if rate1 > 0:
                    for eid in group["Sub-Group 1"]:
                        entry = group["Sub-Group 1"][eid]
                        subg1.append((entry["Probability"], entry["Enemy Group"]))
                subg2 = []
                if rate2 > 0:
                    for eid in group["Sub-Group 2"]:
                        entry = group["Sub-Group 2"][eid]
                        subg2.append((entry["Probability"], entry["Enemy Group"]))
                self._mapGroups.append((flag, rate1, rate2, subg1, subg2))
                updateProgress(pct)
Esempio n. 10
0
class MapModule(EbModule.EbModule):
    _name = "Map"
    _MAP_PTRS_PTR_ADDR = 0xa1db
    _LOCAL_TSET_ADDR = 0x175000
    _MAP_HEIGHT = 320
    _MAP_WIDTH = 256

    def __init__(self):
        self._tiles = []
        self._mapSecTsetPalsTbl = EbTable("GLOBAL_MAP_TILESETPALETTE_DATA")
        self._mapSecMusicTbl = EbTable("MAP_DATA_PER-SECTOR_MUSIC")
        self._mapSecMiscTbl = EbTable("MAP_DATA_PER-SECTOR_ATTRIBUTES_TABLE")
        self.teleport = ValuedIntTableEntry(None, None,
                ["Enabled", "Disabled"])
        self.townmap = ValuedIntTableEntry(None, None,
                ["None", "Onett", "Twoson", "Threed", "Fourside", "Scaraba",
                "Scummers", "None 2"])
        self.setting = ValuedIntTableEntry(None, None,
                ["None", "Indoors", "Exit Mouse usable",
                "Lost Underworld sprites", "Magicant sprites", "Robot sprites",
                "Butterflies", "Indoors and Butterflies"])
    def readFromRom(self, rom):
        # Read map tiles
        map_ptrs_addr = \
            EbModule.toRegAddr(rom.readMulti(self._MAP_PTRS_PTR_ADDR, 3))
        map_addrs = map(lambda x: \
            EbModule.toRegAddr(rom.readMulti(map_ptrs_addr+x*4,4)), \
            range(8))
        self._tiles = map(
                lambda y: rom.readList(map_addrs[y%8] + ((y>>3)<<8),
                    self._MAP_WIDTH).tolist(),
                range(self._MAP_HEIGHT))
        k = self._LOCAL_TSET_ADDR
        for i in range(self._MAP_HEIGHT>>3):
            for j in range(self._MAP_WIDTH):
                self._tiles[i<<3][j] |= (rom[k] & 3) << 8
                self._tiles[(i<<3)|1][j] |= ((rom[k] >> 2) & 3) << 8
                self._tiles[(i<<3)|2][j] |= ((rom[k] >> 4) & 3) << 8
                self._tiles[(i<<3)|3][j] |= ((rom[k] >> 6) & 3) << 8
                self._tiles[(i<<3)|4][j] |= (rom[k+0x3000] & 3) << 8
                self._tiles[(i<<3)|5][j] |= ((rom[k+0x3000] >> 2) & 3) << 8
                self._tiles[(i<<3)|6][j] |= ((rom[k+0x3000] >> 4) & 3) << 8
                self._tiles[(i<<3)|7][j] |= ((rom[k+0x3000] >> 6) & 3) << 8
                k += 1
        updateProgress(25)
        # Read sector data
        self._mapSecTsetPalsTbl.readFromRom(rom)
        updateProgress(25.0/3)
        self._mapSecMusicTbl.readFromRom(rom)
        updateProgress(25.0/3)
        self._mapSecMiscTbl.readFromRom(rom)
        updateProgress(25.0/3)
    def writeToRom(self, rom):
        map_ptrs_addr = \
            EbModule.toRegAddr(rom.readMulti(self._MAP_PTRS_PTR_ADDR, 3))
        map_addrs = map(lambda x: \
            EbModule.toRegAddr(rom.readMulti(map_ptrs_addr+x*4,4)), \
            range(8))
        for i in range(self._MAP_HEIGHT):
            rom.write(map_addrs[i%8] + ((i>>3)<<8), map(lambda x: x & 0xff,
                self._tiles[i]))
        k = self._LOCAL_TSET_ADDR
        for i in range(self._MAP_HEIGHT>>3):
            for j in range(self._MAP_WIDTH):
                c = ((self._tiles[i<<3][j] >> 8)
                        | ((self._tiles[(i<<3)|1][j] >> 8) << 2)
                        | ((self._tiles[(i<<3)|2][j] >> 8) << 4)
                        | ((self._tiles[(i<<3)|3][j] >> 8) << 6))
                rom.write(k, c)
                c = ((self._tiles[(i<<3)|4][j] >> 8)
                        | ((self._tiles[(i<<3)|5][j] >> 8) << 2)
                        | ((self._tiles[(i<<3)|6][j] >> 8) << 4)
                        | ((self._tiles[(i<<3)|7][j] >> 8) << 6))
                rom.write(k+0x3000, c)
                k += 1
        updateProgress(25)
        # Write sector data
        self._mapSecTsetPalsTbl.writeToRom(rom)
        updateProgress(25.0/3)
        self._mapSecMusicTbl.writeToRom(rom)
        updateProgress(25.0/3)
        self._mapSecMiscTbl.writeToRom(rom)
        updateProgress(25.0/3)
    def writeToProject(self, resourceOpener):
        # Write map tiles
        with resourceOpener("map_tiles", "map") as f:
            for row in self._tiles:
                f.write(hex(row[0])[2:].zfill(3))
                for tile in row[1:]:
                    f.write(" ")
                    f.write(hex(tile)[2:].zfill(3))
                f.write("\n")
        updateProgress(25.0)
        # Write sector data
        out = dict()
        for i in range(self._mapSecTsetPalsTbl.height()):
            self.teleport.setVal(self._mapSecMiscTbl[i,0].val() >> 7)
            self.townmap.setVal((self._mapSecMiscTbl[i,0].val() >> 3) & 7)
            self.setting.setVal(self._mapSecMiscTbl[i,0].val() & 3)
            out[i] = {
                    "Tileset": self._mapSecTsetPalsTbl[i,0].val() >> 3,
                    "Palette": self._mapSecTsetPalsTbl[i,0].val() & 7,
                    "Music": self._mapSecMusicTbl[i,0].dump(),
                    "Teleport": self.teleport.dump(),
                    "Town Map": self.townmap.dump(),
                    "Setting": self.setting.dump(),
                    "Item": self._mapSecMiscTbl[i,1].dump() }
        updateProgress(12.5)
        with resourceOpener("map_sectors", "yml") as f:
            yaml.dump(out, f, Dumper=yaml.CSafeDumper, default_flow_style=False)
        updateProgress(12.5)
    def readFromProject(self, resourceOpener):
        # Read map data
        with resourceOpener("map_tiles", "map") as f:
            self._tiles = map(lambda y:
                    map(lambda x: int(x, 16), y.split(" ")),
                    f.readlines())
        updateProgress(25)
        # Read sector data
        self._mapSecTsetPalsTbl.clear(2560)
        self._mapSecMusicTbl.clear(2560)
        self._mapSecMiscTbl.clear(2560)
        pct = (25.0/2560)
        with resourceOpener("map_sectors", "yml") as f:
            input = yaml.load(f, Loader=yaml.CSafeLoader)
            for i in input:
                entry = input[i]
                self._mapSecTsetPalsTbl[i,0].setVal(
                        (entry["Tileset"] << 3) | entry["Palette"])
                self._mapSecMusicTbl[i,0].load(entry["Music"])
                self._mapSecMiscTbl[i,1].load(entry["Item"])
                self.teleport.load(entry["Teleport"])
                self.townmap.load(entry["Town Map"])
                self.setting.load(entry["Setting"])
                self._mapSecMiscTbl[i,0].setVal((self.teleport.val() << 7)
                        | (self.townmap.val() << 3) | self.setting.val())
                updateProgress(pct)
Esempio n. 11
0
class MapMusicModule(EbModule.EbModule):
    _ASMPTR = 0x6939
    _name = "Map Music"
    def __init__(self):
        self._ptrTbl = EbTable(0xCF58EF)
        self._entries = []
    def readFromRom(self, rom):
        self._ptrTbl.readFromRom(rom,
                EbModule.toRegAddr(rom.readMulti(self._ASMPTR, 3)))
        updateProgress(25)
        for i in range(self._ptrTbl.height()):
            loc = 0xf0000 | self._ptrTbl[i,0].val()
            entry = [ ]
            flag = 1
            while flag != 0:
                flag = rom.readMulti(loc, 2)
                music = rom[loc+2]
                entry.append((flag, music))
                loc += 4
            self._entries.append(entry)
        updateProgress(25)
    def writeToRom(self, rom):
        self._ptrTbl.clear(165)
        writeLoc = 0xf58ef
        writeRangeEnd = 0xf61e5 # TODO Can re-use bank space from doors
        i=0
        for entry in self._entries:
            entryLen = len(entry)*4
            if writeLoc+entryLen > writeRangeEnd:
                raise RuntimeError("Not enough room for map music")
            self._ptrTbl[i,0].setVal(writeLoc & 0xffff)
            i += 1

            for (flag, music) in entry:
                rom.writeMulti(writeLoc, flag, 2)
                rom[writeLoc+2] = music
                rom[writeLoc+3] = 0
                writeLoc += 4
        updateProgress(25)
        rom.writeMulti(self._ASMPTR,
                EbModule.toSnesAddr(self._ptrTbl.writeToFree(rom)), 3)
        if writeLoc < writeRangeEnd:
            rom.addFreeRanges([(writeLoc, writeRangeEnd)])
        updateProgress(25)
    def writeToProject(self, resourceOpener):
        out = dict()
        i = 0
        for entry in self._entries:
            outEntry = []
            for (flag, music) in entry:
                outEntry.append({
                    "Event Flag": flag,
                    "Music": music })
            out[i] = outEntry
            i += 1
        updateProgress(25)
        with resourceOpener("map_music", "yml") as f:
            s = yaml.dump(out, default_flow_style=False,
                    Dumper=yaml.CSafeDumper)
            s = sub("Event Flag: (\d+)",
                    lambda i: "Event Flag: " + hex(int(i.group(0)[12:])), s)
            f.write(s)
        updateProgress(25)
    def readFromProject(self, resourceOpener):
        with resourceOpener("map_music", "yml") as f:
            input = yaml.load(f, Loader=yaml.CSafeLoader)
            for i in input:
                entry = []
                for subEntry in input[i]:
                    entry.append((subEntry["Event Flag"],
                        subEntry["Music"]))
                self._entries.append(entry)
        updateProgress(50)
Esempio n. 12
0
class SpriteGroupModule(EbModule.EbModule):
    _name = "Sprite Groups"
    def __init__(self):
        self._grPtrTbl = EbTable(0xef133f)
        self._grPalTbl = EbTable(0xc30000)
        self._groups = None
    def freeRanges(self):
        return [(0x2f1a7f, 0x2f4a3f),
                (0x110000, 0x11ffff),
                (0x120000, 0x12ffff),
                (0x130000, 0x13ffff),
                (0x140000, 0x14ffff),
                (0x150000, 0x154fff)]
    def free(self):
        del(self._grPtrTbl)
        del(self._grPalTbl)
    def readFromRom(self, rom):
        self._grPtrTbl.readFromRom(rom)
        updateProgress(5)
        self._grPalTbl.readFromRom(rom)
        updateProgress(5)

        # Load the sprite groups
        self._groups = []
        pct = 40.0/self._grPtrTbl.height()
        for i in range(self._grPtrTbl.height()):
            # Note: this assumes that the SPT is written contiguously
            numSprites = 8
            # Assume that the last group only has 8 sprites
            if i < self._grPtrTbl.height()-1:
                numSprites = (self._grPtrTbl[i+1,0].val() -
                        self._grPtrTbl[i,0].val() - 9) / 2

            g = SpriteGroup(numSprites)
            g.readFromRom(rom, EbModule.toRegAddr(self._grPtrTbl[i,0].val()))
            self._groups.append(g)
            updateProgress(pct)
    def writeToProject(self, resourceOpener):
        # Write the palettes
        self._grPalTbl.writeToProject(resourceOpener)
        updateProgress(5)
        out = { }
        i = 0
        pct = 40.0/len(self._groups)
        for g in self._groups:
            out[i] = g.dump()
            img = g.toImage(self._grPalTbl[g.palette(),0].val())
            imgFile = resourceOpener("SpriteGroups/" + str(i).zfill(3), 'png')
            img.save(imgFile, 'png', transparency=0)
            imgFile.close()
            del(img)
            i += 1
            updateProgress(pct)
        yaml.dump(out, resourceOpener("sprite_groups", "yml"),
                Dumper=yaml.CSafeDumper)
        updateProgress(5)
    def readFromProject(self, resourceOpener):
        self._grPalTbl.readFromProject(resourceOpener)
        updateProgress(5)
        input = yaml.load(resourceOpener("sprite_groups", "yml"),
                Loader=yaml.CSafeLoader)
        numGroups = len(input)
        self._groups = []
        pct = 45.0/numGroups
        for i in range(numGroups):
            g = SpriteGroup(16)
            g.load(input[i])
            try:
                img = Image.open(
                        resourceOpener("SpriteGroups/" + str(i).zfill(3), "png"))
            except IOError:
                print "Could not load Sprite Group #" + str(i)
                raise

            if img.mode != 'P':
                raise RuntimeError("SpriteGroups/" +
                        str(i).zfill(3) + " is not an indexed PNG.")

            g.fromImage(img)
            palData = img.getpalette()
            del(img)
            self._groups.append(g)
            pal = [ ]

            # Read the palette from the image
            for j in range(1, 16):
                pal.append((palData[j*3], palData[j*3+1], palData[j*3+2]))
            # Assign the palette number to the sprite
            for j in range(8):
                if pal == self._grPalTbl[j,0].val()[1:]:
                    g.setPalette(j)
                    break
            else:
                # Error, this image uses an invalid palette
                for j in range(8):
                    print j, ":", self._grPalTbl[j,0].val()[1:]
                raise RuntimeError("Sprite Group #" + str(i)
                        + " uses an invalid palette: " + str(pal))
            updateProgress(pct)
            
    def writeToRom(self, rom):
        numGroups = len(self._groups)
        self._grPtrTbl.clear(numGroups)
        with DataBlock(sum(map(
            lambda x: x.blockSize(), self._groups))) as block:
            loc = 0
            i = 0
            # Write all the groups to the block, and sprites to rom
            pct = 40.0 / numGroups
            for g in self._groups:
                g.writeSpritesToFree(rom)
                g.writeToBlock(block, loc)
                self._grPtrTbl[i,0].setVal(loc)
                loc += g.blockSize()
                i += 1
                updateProgress(pct)
            # Write the block to rom and correct the group pointers
            addr = EbModule.toSnesAddr(block.writeToFree(rom))
            for i in range(self._grPtrTbl.height()):
                self._grPtrTbl[i,0].setVal(
                        self._grPtrTbl[i,0].val() + addr)
        # Write the pointer table
        self._grPtrTbl.writeToRom(rom)
        updateProgress(5)
        # Write the palettes
        self._grPalTbl.writeToRom(rom)
        updateProgress(5)
    def upgradeProject(self, oldVersion, newVersion, rom, resourceOpenerR,
            resourceOpenerW):
        def replaceField(fname, oldField, newField, valueMap):
            if newField == None:
                newField = oldField
            valueMap = dict((k, v) for k,v in valueMap.iteritems())
            with resourceOpenerR(fname, 'yml') as f:
                data = yaml.load(f, Loader=yaml.CSafeLoader)
                for i in data:
                    if data[i][oldField] in valueMap:
                        data[i][newField] = valueMap[data[i][oldField]].lower()
                    else:
                        data[i][newField] = data[i][oldField]
                    if newField != oldField:
                        del data[i][oldField]
            with resourceOpenerW(fname, 'yml') as f:
                yaml.dump(data, f, Dumper=yaml.CSafeDumper)
        def replaceFieldName(fname, oldField, newField):
            if newField == None:
                newField = oldField
            with resourceOpenerR(fname, 'yml') as f:
                data = yaml.load(f, Loader=yaml.CSafeLoader)
                for i in data:
                    data[i][newField] = data[i][oldField]
                    del data[i][oldField]
            with resourceOpenerW(fname, 'yml') as f:
                yaml.dump(data, f, Dumper=yaml.CSafeDumper)

        if oldVersion == newVersion:
            updateProgress(100)
            return
        elif oldVersion == 2:
            replaceField("sprite_groups",
                    "Unknown A", "Size",
                    { 0: "16x16",
                        1: "16x16 2",
                        2: "24x16",
                        3: "32x16",
                        4: "48x16",
                        5: "16x24",
                        6: "24x24",
                        7: "16x32",
                        8: "32x32",
                        9: "48x32",
                        10: "24x40",
                        11: "16x48",
                        12: "32x48",
                        13: "48x48",
                        14: "64x48",
                        15: "64x64",
                        16: "64x80" })
            replaceFieldName("sprite_groups", "Unknown B", "Collision Settings")
            self.upgradeProject(oldVersion+1, newVersion, rom, resourceOpenerR,
                    resourceOpenerW)
        elif oldVersion == 1:
            self.upgradeProject(oldVersion+1, newVersion, rom, resourceOpenerR,
                    resourceOpenerW)
Esempio n. 13
0
class MapEventModule(EbModule.EbModule):
    _name = "Map Events"
    _PTR_LOC = 0x70d
    _PTR_BANK_LOC = 0x704
    def __init__(self):
        self._ptrTbl = EbTable(0xD01598)
        self._entries = [ ]
    def freeRanges(self):
        return [(0x101598, 0x10187f)]
    def readFromRom(self, rom):
        self._ptrTbl.readFromRom(rom,
                EbModule.toRegAddr(rom.readMulti(self._PTR_LOC, 3)))
        updateProgress(5)
        bank = (rom[self._PTR_BANK_LOC] - 0xc0) << 16
        pct = 45.0/20
        for i in range(20):
            addr = bank | self._ptrTbl[i,0].val()
            tsetEntry = []
            while (rom.readMulti(addr, 2) != 0):
                flag = rom.readMulti(addr, 2)
                num = rom.readMulti(addr+2, 2)
                addr += 4
                changes = []
                for j in range(num):
                    changes.append((rom.readMulti(addr, 2),
                            rom.readMulti(addr+2, 2)))
                    addr += 4
                tsetEntry.append((flag, changes))
            self._entries.append(tsetEntry)
            updateProgress(pct)
    def writeToProject(self, resourceOpener):
        out = dict()
        i = 0
        for entry in self._entries:
            entryOut = []
            for (flag, changes) in entry:
                changeOut = { "Event Flag": flag }
                changeOut["Changes"] = changes
                entryOut.append(changeOut)
            if entryOut == []:
                out[i] = None
            else:
                out[i] = entryOut
            i += 1
        updateProgress(25)
        with resourceOpener("map_changes", "yml") as f:
            s = yaml.dump(out, Dumper=yaml.CSafeDumper)
            s = sub("Event Flag: (\d+)",
                    lambda i: "Event Flag: " + hex(int(i.group(0)[12:])), s)
            f.write(s)
        updateProgress(25)
    def readFromProject(self, resourceOpener):
        with resourceOpener("map_changes", "yml") as f:
            input = yaml.load(f, Loader=yaml.CSafeLoader)
            for mtset in input:
                entry = []
                entryIn = input[mtset]
                if (entryIn != None):
                    for csetIn in entryIn:
                        entry.append((csetIn["Event Flag"],
                            csetIn["Changes"]))
                self._entries.append(entry)
                updateProgress(50.0/20)
    def writeToRom(self, rom):
        self._ptrTbl.clear(20)
        blockSize = 0
        for entry in self._entries:
            for (flag, set) in entry:
                blockSize += 4 + 4*len(set)
            blockSize += 2
        if blockSize > 0xffff:
            raise RuntimeError("Too many map changes")
        loc = rom.getFreeLoc(blockSize)
        rom[self._PTR_BANK_LOC] = (loc >> 16) + 0xc0
        i = 0
        for entry in self._entries:
            self._ptrTbl[i,0].setVal(loc & 0xffff)
            for (flag, set) in entry:
                rom.writeMulti(loc, flag, 2)
                rom.writeMulti(loc+2, len(set), 2)
                loc += 4
                for (before, after) in set:
                    rom.writeMulti(loc, before, 2)
                    rom.writeMulti(loc+2, after, 2)
                    loc += 4
            rom[loc] = 0
            rom[loc+1] = 0
            loc += 2
            i += 1
            updateProgress(45.0/20)
        ptrTblLoc = self._ptrTbl.writeToFree(rom)
        rom.writeMulti(self._PTR_LOC, EbModule.toSnesAddr(ptrTblLoc), 3)
        updateProgress(5)