示例#1
0
    def handleIps(self, plandoName, romDataJson):
        romDataJson = self.vars.romData
        romDataRaw = json.loads(romDataJson)
        # everything is string in json, cast to int
        romData = {}
        for addr in romDataRaw:
            romData[int(addr)] = int(romDataRaw[addr])

        # dict: address -> value, transform it dict: address -> [values]
        ipsData = {}
        prevAddr = -0xff
        curRecord = []
        curRecordAddr = -1
        for addr in sorted(romData):
            if addr == prevAddr + 1:
                curRecord.append(romData[addr])
            else:
                if len(curRecord) > 0:
                    # save current record
                    ipsData[curRecordAddr] = bytearray(curRecord)
                # start a new one
                curRecordAddr = addr
                curRecord = [romData[addr]]
            prevAddr = addr
        # save last record
        ipsData[curRecordAddr] = bytearray(curRecord)

        # generate ips using the records
        ipsPatch = IPS_Patch(ipsData)
        maxSize = ipsPatch.max_size

        # store ips in the repository
        ipsPatch.save(os.path.join(ipsBasePath, "{}.ips".format(plandoName)))

        return maxSize
示例#2
0
 def applyIPSPatch(self, patchName, patchDict=None, ipsDir=None):
     if patchDict is None:
         patchDict = self.patchAccess.getDictPatches()
     print("Apply patch {}".format(patchName))
     if patchName in patchDict:
         patch = IPS_Patch(patchDict[patchName])
     else:
         # look for ips file
         if ipsDir is None:
             patch = IPS_Patch.load(self.patchAccess.getPatchPath(patchName))
         else:
             patch = IPS_Patch.load(os.path.join(appDir, ipsDir, patchName))
     self.ipsPatches.append(patch)
示例#3
0
 def applyIPSPatch(self, patchName, patchDict=None, ipsDir="rando/patches"):
     if patchDict is None:
         patchDict = patches
     print("Apply patch {}".format(patchName))
     if patchName in patchDict:
         patch = IPS_Patch(patchDict[patchName])
     else:
         # look for ips file
         if os.path.exists(patchName):
             patch = IPS_Patch.load(patchName)
         else:
             patch = IPS_Patch.load(os.path.join(appDir, ipsDir, patchName))
     self.ipsPatches.append(patch)
示例#4
0
    def ipsPatch(self, ipsPatches):
        mergedIPS = IPS_Patch()
        for ips in ipsPatches:
            mergedIPS.append(ips)

        # generate records for ips from self data
        groupedData = {}
        startAddress = -1
        prevAddress = -1
        curData = []
        for address in sorted(self.data):
            if address == prevAddress + 1:
                curData.append(self.data[address])
                prevAddress = address
            else:
                if len(curData) > 0:
                    groupedData[startAddress] = curData
                startAddress = address
                prevAddress = address
                curData = [self.data[startAddress]]
        if startAddress != -1:
            groupedData[startAddress] = curData

        patch = IPS_Patch(groupedData)
        mergedIPS.append(patch)
        patchData = mergedIPS.encode()
        self.data = {}
        self.data["ips"] = base64.b64encode(patchData).decode()
        if mergedIPS.truncate_length is not None:
            self.data["truncate_length"] = mergedIPS.truncate_length
        self.data["max_size"] = mergedIPS.max_size
def writeAsm(patch, outAsm):
    print("Writing " + outAsm + "...")
    p = IPS_Patch.load(patch).toDict()
    with open(outAsm, 'w') as f:
        f.write("lorom\narch snes.cpu\n\n")
        for addr, bytez in p.items():
            f.write("org $%06x\nprint pc\n" % pc_to_snes(addr))
            for i in range(0, len(bytez), 8):
                blist = ["$%02x" % b for b in bytez[i:min(len(bytez), i + 8)]]
                f.write("\tdb %s\n" % ','.join(blist))
            f.write('print pc\n')
示例#6
0
 def close(self):
     mergedIPS = IPS_Patch()
     for ips in self.ipsPatches:
         mergedIPS.append(ips)
     mergedIPS.append(self.ips())
     patchData = mergedIPS.encode()
     self.data = {}
     self.data["ips"] = base64.b64encode(patchData).decode()
     if mergedIPS.truncate_length is not None:
         self.data["truncate_length"] = mergedIPS.truncate_length
     self.data["max_size"] = mergedIPS.max_size
示例#7
0
    def ips(self):
        groupedData = {}
        startAddress = -1
        prevAddress = -1
        curData = []
        for address in sorted(self.data):
            if address == prevAddress + 1:
                curData.append(self.data[address])
                prevAddress = address
            else:
                if len(curData) > 0:
                    groupedData[startAddress] = curData
                startAddress = address
                prevAddress = address
                curData = [self.data[startAddress]]
        if startAddress != -1:
            groupedData[startAddress] = curData

        return IPS_Patch(groupedData)
示例#8
0
    for r in patch.getRanges():
        ips_ranges.append({'name': name, 'range': r})


def loadPatchPy():
    from rando.patches import patches as patches_py
    for name, patch in patches_py.items():
        addRanges(name, IPS_Patch(patch))


for patch in sys.argv[2:]:
    baseName = os.path.basename(patch)
    if baseName == "patches.py":
        loadPatchPy()
    else:
        addRanges(baseName, IPS_Patch.load(patch))

overlaps = {}
last, lstop = None, -1
for rg in sorted(ips_ranges, key=lambda r: r['range'].start):
    thisStart = rg['range'].start
    if last and lstop > thisStart and lstop != 0x7fe0:  # overlap, skip checksum
        k = (last['name'], rg['name'])
        if k not in overlaps:
            overlaps[k] = []
        overlaps[k].append((lstop, thisStart))
    last = rg
    lstop = last['range'].stop

for k, v in overlaps.items():
    addresses = ["(0x%x, 0x%x)" % a for a in v]
sys.path.append(os.path.dirname(sys.path[0]))

from rom.ips import IPS_Patch
from rom.rom import RealROM
from patches.common import patches as common_patches

vanilla = sys.argv[1]
ipsToReverse = sys.argv[2:]

rom = RealROM(vanilla)

for ips in ipsToReverse:
    if ips not in common_patches.patches:
        ipsPath = os.path.abspath(ips)
        destDir, destFile = os.path.split(ipsPath)
        patch = IPS_Patch.load(ips)
        patchDict = patch.toDict()
    else:
        patchDict = common_patches.patches[ips]
        destDir = sys.path[0] + "/../patches/common/ips"
        destFile = ips + ".ips"
    destFile = "remove_" + destFile
    destPath = os.path.join(destDir, destFile)
    reversePatchDict = {}
    for addr, bytez in patchDict.items():
        sz = len(bytez)
        origBytes = []
        rom.seek(addr)
        for i in range(sz):
            origBytes.append(rom.readByte())
        assert len(origBytes) == sz
    # the output is a dict
    data = eval(response.text)

    # generate randomized rom
    romFileName = args.rom
    outFileName = data["fileName"]
    shutil.copyfile(romFileName, outFileName)
    romFile = RealROM(outFileName)

    ipsData = data["ips"]
    ipsData = base64.b64decode(ipsData.encode('ascii'))

    # our ips patcher need a file (or a dict), not the content of the ips file
    (fd, ipsFileName) = tempfile.mkstemp()
    os.close(fd)

    with open(ipsFileName, 'wb+') as ipsFile:
        ipsFile.write(ipsData)

    romFile.ipsPatch([IPS_Patch.load(ipsFileName)])

    os.remove(ipsFileName)
        
    # write dest rom
    romFile.close()

    print("permalink: {}/customizer/{}".format(baseUrl, data["seedKey"]))

    print("additional message: {}".format(data["errorMsg"]))
    print("{} generated succesfully".format(outFileName))
示例#11
0
    for name, diff in needCopy.items():
        if not diff:
            continue
        print("copy {} from hack".format(name))
        tmpBytes = []
        addrs = addresses[name]
        for addr in range(addrs["hack"][0], addrs["hack"][1]):
            tmpBytes.append(hackRom.readByte(addr))
        vanillaRom.seek(addrs["vanilla"][0])
        for byte in tmpBytes:
            vanillaRom.writeByte(byte)

# also copy last line of ship tiles in escape sequence
rowSize = 1024
hAddr = addresses["tilesAddr"]["hack"][0] + rowSize * 3
vAddr = snes_to_pc(0x94C800)
hackRom.seek(hAddr)
vanillaRom.seek(vAddr)
for i in range(rowSize):
    vanillaRom.writeByte(hackRom.readByte())

vanillaRom.close()

# generate ips between vanilla & tempfile
patch = IPS_Patch.create(
    open(vanilla, 'rb').read(),
    open(tmpfile, 'rb').read())
out = hack + '.ips'
patch.save(out)
print("ips generated: {}".format(out))
示例#12
0
#!/usr/bin/python3

import sys, os

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

from rom.ips import IPS_Patch

original=sys.argv[1]
patched=sys.argv[2]
target=sys.argv[3]

patch = IPS_Patch.create(open(original, 'rb').read(), open(patched, 'rb').read())

patch.save(target)

}
meta["dynamic_patches"] = {
    "track_id": [snes_to_pc(0xA497DE)]
}

meta = getBossMeta("Spore Spawn")
meta["pc_addresses"] = [499165]

meta = getBossMeta("Botwoon")
meta["pc_addresses"] = [514420]

# Add patches to silence song-specific sfx that don't work anymore when changed,
# and can generate horrible sounds or crashes
patchDir = os.path.abspath(sys.path[0])+"/../patches/common/ips/custom_music_specific"
assert os.path.exists(patchDir)

for trackName, trackData in metadata.items():
    patchName = re.sub('[^a-zA-Z0-9\._]', '_', trackName)
    patchPath = os.path.join(patchDir, patchName+".ips")
    if os.path.exists(patchPath):
        print("Adding SFX patch for track "+trackName)
        patch = IPS_Patch.load(patchPath)
        if "static_patches" not in trackData:
            trackData["static_patches"] = {}
        trackData["static_patches"].update(patch.toDict())


print("Writing %s ..." % json_path)
with open(json_path, 'w') as fp:
    json.dump(metadata, fp, indent=4)
示例#14
0
 def applyIPSPatchDict(self, patchDict):
     for patchName in patchDict.keys():
         # print("Apply patch {}".format(patchName))
         patch = IPS_Patch(patchDict[patchName])
         self.ipsPatches.append(patch)
示例#15
0
def loadPatchPy():
    from rando.patches import patches as patches_py
    for name, patch in patches_py.items():
        addRanges(name, IPS_Patch(patch))
#!/usr/bin/python3

import sys, os, json

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

from rom.ips import IPS_Patch
elev = IPS_Patch.load("patches/common/ips/elevators_speed.ips")
doors = IPS_Patch.load("patches/common/ips/fast_doors.ips")
merged = IPS_Patch()
merged.append(elev)
merged.append(doors)
merged.save("patches/common/ips/elevators_doors_speed.ips")
from rom.ips import IPS_Patch
from rom.rom import snes_to_pc, pc_to_snes

ips=sys.argv[1]
low=snes_to_pc(int(sys.argv[2], 16))
high=snes_to_pc(int(sys.argv[3], 16))

ext = os.path.splitext(ips)[-1].lower()

if ext != ".ips":
    sys.stderr.write("Wrong ips extension")
    sys.exit(1)

# load ips
patch = IPS_Patch.load(ips)
patch_dict = patch.toDict()

# remove overlapping data
filtered_dict = {}
for keyLow, data in patch_dict.items():
    dataLength = len(data)
    keyHigh = keyLow + dataLength
    if keyHigh < low or keyLow > high:
        print("[{}, {}] we have {} bytes of data".format(hex(pc_to_snes(keyLow)),
                                                         hex(pc_to_snes(keyHigh)),
                                                         dataLength))
        filtered_dict[keyLow] = data
    else:
        print("[{}, {}] we have {} bytes of data overlaping with [{}, {}]".format(hex(pc_to_snes(keyLow)),
                                                                                  hex(pc_to_snes(keyHigh)),