Exemple #1
0
 def load(self, input):
     self._x = input["X"]
     self._y = input["Y"]
     self.setTypeFromString(input["Type"])
     if (self._type == 3) or (self._type == 4): # Stairs/Escalator
         self._stairDir = ValuedIntTableEntry(None, None,
                 ["NW", "NE", "SW", "SE", "Nowhere"])
         self._stairDir.load(input["Direction"])
     elif self._type == 2: # Door
         self._destTextPtr = PointerTableEntry(None, 4)
         self._destTextPtr.load(input["Text Pointer"])
         self._destFlag = input["Event Flag"]
         self._destX = input["Destination X"]
         self._destY = input["Destination Y"]
         self._destDir = ValuedIntTableEntry(None, None,
                 ["Down", "Up", "Right", "Left"])
         self._destDir.load(input["Direction"])
         self._destStyle = input["Style"]
     elif self._type == 0: # Switch
         self._destTextPtr = PointerTableEntry(None, 4)
         self._destTextPtr.load(input["Text Pointer"])
         self._destFlag = input["Event Flag"]
     elif (self._type == 5) or (self._type == 6):
         self._destTextPtr = PointerTableEntry(None, 4)
         self._destTextPtr.load(input["Text Pointer"])
 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" ])
Exemple #3
0
 def readFromRom(self, rom, addr):
     self._y = rom[addr]
     self._x = rom[addr+1]
     self._type = rom[addr+2]
     ptr = rom.readMulti(addr+3, 2)
     if self._type == 1: # Rope/Ladder
         self._isRope = (ptr == 0x8000)
     elif (self._type == 3) or (self._type == 4): # Escalator and Stairs
         if ptr == 0x8000:
             stairDir = 4
         else:
             stairDir = ptr / 0x100
         self._stairDir = ValuedIntTableEntry(None, None,
                 ["NW", "NE", "SW", "SE", "Nowhere"])
         self._stairDir.setVal(stairDir)
     elif self._type == 2: # Door
         ptr |= 0xF0000
         #self._destTextPtr = rom.readMulti(ptr, 4)
         self._destTextPtr = PointerTableEntry(None, 4)
         self._destTextPtr.setVal(rom.readMulti(ptr, 4))
         if ((self._destTextPtr.val() != 0) and 
                 ((self._destTextPtr.val() < 0xc00000)
                     or (self._destTextPtr.val() > 0xffffff))):
             raise ValueError("Invalid Door")
         self._destFlag = rom.readMulti(ptr+4, 2)
         self._destY = rom[ptr+6]
         self._destY |= (rom[ptr+7] & 0x3f) << 8
         #self._destDir = (rom[ptr+7] & 0xc0) >> 6
         self._destDir = ValuedIntTableEntry(None, None,
                 ["Down", "Up", "Right", "Left"])
         self._destDir.setVal((rom[ptr+7] & 0xc0) >> 6)
         self._destX = rom.readMulti(ptr+8, 2)
         self._destStyle = rom[ptr+10]
     elif self._type == 0: # Switch
         ptr |= 0xF0000
         self._destFlag = rom.readMulti(ptr, 2)
         #self._destTextPtr = rom.readMulti(ptr+2, 4)
         self._destTextPtr = PointerTableEntry(None, 4)
         self._destTextPtr.setVal(rom.readMulti(ptr+2, 4))
         if ((self._destTextPtr.val() != 0) and 
                 ((self._destTextPtr.val() < 0xc00000)
                     or (self._destTextPtr.val() > 0xffffff))):
             raise ValueError("Invalid Switch")
     elif (self._type == 5) or (self._type == 6): # Object and Person
         ptr |= 0xF0000
         #self._destTextPtr = rom.readmulti(ptr, 4)
         self._destTextPtr = PointerTableEntry(None, 4)
         self._destTextPtr.setVal(rom.readMulti(ptr, 4))
     else:
         raise ValueError("Unknown type " + str(self._type))
Exemple #4
0
 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"])
Exemple #5
0
    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"])
Exemple #6
0
class Door:
    # Types: Switch, Rope/Ladder, Door, Escalator, Stairway, Object, Person
    _TYPE_NAMES = ["switch", "rope/ladder", "door", "escalator", "stairway",
            "object", "person"]
    def readFromRom(self, rom, addr):
        self._y = rom[addr]
        self._x = rom[addr+1]
        self._type = rom[addr+2]
        ptr = rom.readMulti(addr+3, 2)
        if self._type == 1: # Rope/Ladder
            self._isRope = (ptr == 0x8000)
        elif (self._type == 3) or (self._type == 4): # Escalator and Stairs
            if ptr == 0x8000:
                stairDir = 4
            else:
                stairDir = ptr / 0x100
            self._stairDir = ValuedIntTableEntry(None, None,
                    ["NW", "NE", "SW", "SE", "Nowhere"])
            self._stairDir.setVal(stairDir)
        elif self._type == 2: # Door
            ptr |= 0xF0000
            #self._destTextPtr = rom.readMulti(ptr, 4)
            self._destTextPtr = PointerTableEntry(None, 4)
            self._destTextPtr.setVal(rom.readMulti(ptr, 4))
            if ((self._destTextPtr.val() != 0) and 
                    ((self._destTextPtr.val() < 0xc00000)
                        or (self._destTextPtr.val() > 0xffffff))):
                raise ValueError("Invalid Door")
            self._destFlag = rom.readMulti(ptr+4, 2)
            self._destY = rom[ptr+6]
            self._destY |= (rom[ptr+7] & 0x3f) << 8
            #self._destDir = (rom[ptr+7] & 0xc0) >> 6
            self._destDir = ValuedIntTableEntry(None, None,
                    ["Down", "Up", "Right", "Left"])
            self._destDir.setVal((rom[ptr+7] & 0xc0) >> 6)
            self._destX = rom.readMulti(ptr+8, 2)
            self._destStyle = rom[ptr+10]
        elif self._type == 0: # Switch
            ptr |= 0xF0000
            self._destFlag = rom.readMulti(ptr, 2)
            #self._destTextPtr = rom.readMulti(ptr+2, 4)
            self._destTextPtr = PointerTableEntry(None, 4)
            self._destTextPtr.setVal(rom.readMulti(ptr+2, 4))
            if ((self._destTextPtr.val() != 0) and 
                    ((self._destTextPtr.val() < 0xc00000)
                        or (self._destTextPtr.val() > 0xffffff))):
                raise ValueError("Invalid Switch")
        elif (self._type == 5) or (self._type == 6): # Object and Person
            ptr |= 0xF0000
            #self._destTextPtr = rom.readmulti(ptr, 4)
            self._destTextPtr = PointerTableEntry(None, 4)
            self._destTextPtr.setVal(rom.readMulti(ptr, 4))
        else:
            raise ValueError("Unknown type " + str(self._type))
    def getTypeAsString(self):
        if self._type == 1:
            if self._isRope:
                return "rope"
            else:
                return "ladder"
        else:
            return Door._TYPE_NAMES[self._type]
    def setTypeFromString(self, str):
        str = str.lower()
        if str == "rope":
            self._type = 1
            self._isRope = True
        elif str == "ladder":
            self._type = 1
            self._isRope = False
        else:
            self._type = Door._TYPE_NAMES.index(str)
    def dump(self):
        out = { "X": self._x,
                "Y": self._y,
                "Type": self.getTypeAsString() }
        if (self._type == 3) or (self._type == 4): # Stairs/Escalator
            out["Direction"] = self._stairDir.dump()
        elif self._type == 2: # Door
            out["Text Pointer"] = self._destTextPtr.dump()
            out["Event Flag"] = self._destFlag
            out["Destination X"] = self._destX
            out["Destination Y"] = self._destY
            out["Direction"] = self._destDir.dump()
            out["Style"] = self._destStyle
        elif self._type == 0: # Switch
            out["Text Pointer"] = self._destTextPtr.dump()
            out["Event Flag"] = self._destFlag
        elif (self._type == 5) or (self._type == 6):
            out["Text Pointer"] = self._destTextPtr.dump()
        return out
    def load(self, input):
        self._x = input["X"]
        self._y = input["Y"]
        self.setTypeFromString(input["Type"])
        if (self._type == 3) or (self._type == 4): # Stairs/Escalator
            self._stairDir = ValuedIntTableEntry(None, None,
                    ["NW", "NE", "SW", "SE", "Nowhere"])
            self._stairDir.load(input["Direction"])
        elif self._type == 2: # Door
            self._destTextPtr = PointerTableEntry(None, 4)
            self._destTextPtr.load(input["Text Pointer"])
            self._destFlag = input["Event Flag"]
            self._destX = input["Destination X"]
            self._destY = input["Destination Y"]
            self._destDir = ValuedIntTableEntry(None, None,
                    ["Down", "Up", "Right", "Left"])
            self._destDir.load(input["Direction"])
            self._destStyle = input["Style"]
        elif self._type == 0: # Switch
            self._destTextPtr = PointerTableEntry(None, 4)
            self._destTextPtr.load(input["Text Pointer"])
            self._destFlag = input["Event Flag"]
        elif (self._type == 5) or (self._type == 6):
            self._destTextPtr = PointerTableEntry(None, 4)
            self._destTextPtr.load(input["Text Pointer"])
    def writeToRom(self, rom, addr, destWriteLoc, destRangeEnd, destLocs):
        rom[addr] = self._y
        rom[addr+1] = self._x
        rom[addr+2] = self._type
        if self._type == 1: # Rope/Ladder
            rom[addr+3] = 0
            rom[addr+4] = (0x80 if self._isRope else 0)
            return 0
        elif (self._type == 3) or (self._type == 4): # Escalator and Stairs
            rom[addr+3] = 0
            rom[addr+4] = (0x80 if (self._stairDir.val() == 4) else
                    self._stairDir.val())
            return 0
        elif self._type == 2: # Door
            with DataBlock(11) as destBlock:
                # Write data to block
                destTextPtr = self._destTextPtr.val()
                destBlock[0] = destTextPtr & 0xff
                destBlock[1] = (destTextPtr>>8) & 0xff
                destBlock[2] = (destTextPtr>>16) & 0xff
                destBlock[3] = (destTextPtr>>24) & 0xff
                destBlock[4] = self._destFlag & 0xff
                destBlock[5] = (self._destFlag >> 8) & 0xff
                destBlock[6] = self._destY & 0xff
                destBlock[7] = (self._destY >> 8) | (self._destDir.val() << 6)
                destBlock[8] = self._destX & 0xff
                destBlock[9] = self._destX >> 8
                destBlock[10] = self._destStyle
                # Check for any pre-existing matching destinations
                destHash = destBlock.hash()
                try:
                    destAddr = destLocs[destHash]
                    rom[addr+3] = destAddr & 0xff
                    rom[addr+4] = destAddr >> 8
                    return 0
                except KeyError:
                    # Need to write a new destination
                    if (destWriteLoc + 11) > destRangeEnd:
                        # TODO Error, not enough space
                        raise RunetimeError("Not enough door destination space")
                    destBlock.writeToRom(rom, destWriteLoc)
                    destLocs[destHash] = destWriteLoc & 0xffff
                    rom[addr+3] = destWriteLoc & 0xff
                    rom[addr+4] = (destWriteLoc >> 8) & 0xff
                    return 11
        elif self._type == 0: # Switch
            with DataBlock(6) as destBlock:
                # Write the data to block
                destBlock[0] = self._destFlag & 0xff
                destBlock[1] = self._destFlag >> 8
                destTextPtr = self._destTextPtr.val()
                destBlock[2] = destTextPtr & 0xff
                destBlock[3] = (destTextPtr>>8) & 0xff
                destBlock[4] = (destTextPtr>>16) & 0xff
                destBlock[5] = (destTextPtr>>24) & 0xff
                # Check for any pre-existing matching destinations
                destHash = destBlock.hash()
                try:
                    destAddr = destLocs[destHash]
                    rom[addr+3] = destAddr & 0xff
                    rom[addr+4] = destAddr >> 8
                    return 0
                except KeyError:
                    # Need to write a new destination
                    if (destWriteLoc + 6) > destRangeEnd:
                        # TODO Error, not enough space
                        raise RunetimeError("Not enough door destination space")
                    destBlock.writeToRom(rom, destWriteLoc)
                    destLocs[destHash] = destWriteLoc & 0xffff
                    rom[addr+3] = destWriteLoc & 0xff
                    rom[addr+4] = (destWriteLoc >> 8) & 0xff
                    return 6
        elif (self._type == 5) or (self._type == 6): # Switch
            with DataBlock(4) as destBlock:
                # Write the data to block
                destTextPtr = self._destTextPtr.val()
                destBlock[0] = destTextPtr & 0xff
                destBlock[1] = (destTextPtr>>8) & 0xff
                destBlock[2] = (destTextPtr>>16) & 0xff
                destBlock[3] = (destTextPtr>>24) & 0xff
                # Check for any pre-existing matching destinations
                destHash = destBlock.hash()
                try:
                    destAddr = destLocs[destHash]
                    rom[addr+3] = destAddr & 0xff
                    rom[addr+4] = destAddr >> 8
                    return 0
                except KeyError:
                    # Need to write a new destination
                    if (destWriteLoc + 4) > destRangeEnd:
                        # TODO Error, not enough space
                        raise RunetimeError("Not enough door destination space")
                    destBlock.writeToRom(rom, destWriteLoc)
                    destLocs[destHash] = destWriteLoc & 0xffff
                    rom[addr+3] = destWriteLoc & 0xff
                    rom[addr+4] = (destWriteLoc >> 8) & 0xff
                    return 4
Exemple #7
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)
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)
Exemple #9
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)