def dry_transfer(sourcefname, targetfname):
    with open(sourcefname, 'rb') as f:
        sourcerawdata = f.read()
    with open(targetfname, 'rb') as f:
        targetrawdata = f.read()
    sourcegame, sourcedata = extract.parse_savedata(sourcerawdata)
    targetgame, targetdata = extract.parse_savedata(targetrawdata)
    # Get the player data from the source save
    sourcecfdata = extract.parse_changeforms(sourcedata['changeforms'])
    sourceplayer = extract.parse_player(sourcecfdata['playerdata'],
                                        sourcecfdata['playerchangeflags'],
                                        sourcegame)
    # Get the data from target save
    targetcfdata = extract.parse_changeforms(targetdata['changeforms'])
    targetplayer = extract.parse_player(targetcfdata['playerdata'],
                                        targetcfdata['playerchangeflags'],
                                        targetgame)
    # Merge players, return target player with source's face
    newplayer, newflags = extract.merge_player(
        sourceplayer, sourcecfdata['playerchangeflags'],
        targetplayer, targetcfdata['playerchangeflags'],
        sourcegame
    )
    pp = pprint.PrettyPrinter(indent=4)
    pp.pprint(newplayer)
Example #2
0
 def merge_player_and_revert(self, fnames):
     """
     Apply the source's face onto the target file and then revert.
     The target should be identical before and after.
     """
     for fname1, fname2 in fnames:
         with open(fname1, 'rb') as f:
             rawsourcedata = f.read()
         with open(fname2, 'rb') as f:
             rawtargetdata = f.read()
         # First get the source for the face
         sourcegame, sourcedata = extract.parse_savedata(rawsourcedata)
         sourcecf = extract.parse_changeforms(sourcedata['changeforms'])
         rawsourceplayer = sourcecf['playerdata']
         sourceplayer = extract.parse_player(rawsourceplayer,
                                             sourcecf['playerchangeflags'],
                                             sourcegame)
         # Then get the target data
         targetgame, targetdata = extract.parse_savedata(rawtargetdata)
         targetcf = extract.parse_changeforms(targetdata['changeforms'])
         rawtargetplayer = targetcf['playerdata']
         targetplayer = extract.parse_player(rawtargetplayer,
                                             targetcf['playerchangeflags'],
                                             targetgame)
         # Merge the source and target
         mergedplayer, mergedflags = extract.merge_player(
             sourceplayer, sourcecf['playerchangeflags'],
             targetplayer, targetcf['playerchangeflags'],
             targetgame
         )
         # Make sure the mergedplayer is valid
         rawmergedplayer = extract.encode_player(mergedplayer, targetgame)
         extract.parse_player(rawmergedplayer, mergedflags, targetgame)
         # Then get a new copy of the target, just to be sure
         target2game, target2data = extract.parse_savedata(rawtargetdata)
         rawtarget2cf = target2data['changeforms']
         target2cf = extract.parse_changeforms(rawtarget2cf)
         rawtarget2player = target2cf['playerdata']
         target2player = extract.parse_player(rawtarget2player,
                                             target2cf['playerchangeflags'],
                                             target2game)
         # Revert the face, aka put the newly read target face
         # onto the old target's data (which atm has source's face)
         revertedplayer, revertedflags = extract.merge_player(
             target2player, target2cf['playerchangeflags'],
             targetplayer, targetcf['playerchangeflags'],
             targetgame
         )
         # Encode the target again and compare
         rawrevertedplayer = extract.encode_player(revertedplayer, targetgame)
         self.assertEqual(rawtargetplayer, rawrevertedplayer)
         # Encode the changeforms and compare
         targetcf['playerdata'] = rawrevertedplayer
         targetcf['playerchangeflags'] = revertedflags
         rawrevertedcf = extract.encode_changeforms(targetcf)
         self.assertEqual(rawtarget2cf, rawrevertedcf)
         # Encode the whole file and compare
         targetdata['changeforms'] = rawrevertedcf
         rawreverteddata = extract.encode_savedata(targetdata)
         self.assertEqual(rawtargetdata, rawreverteddata)
def transfer_face(sourcefname: str, targetfname: str):
    """
    Copy facial data from one save file to another. This function should be
    the main entry point for the UI.
    """
    with open(sourcefname, 'rb') as f:
        sourcerawdata = f.read()
    with open(targetfname, 'rb') as f:
        targetrawdata = f.read()
    sourcegame, sourcedata = extract.parse_savedata(sourcerawdata)
    targetgame, targetdata = extract.parse_savedata(targetrawdata)
    if sourcegame != targetgame:
        raise Exception('Saves are not from the same game!')
    if sourcedata['playersex'] != targetdata['playersex']:
        raise Exception('Characters must have the same gender!')
    if sourcedata['playerraceeditorid'] != targetdata['playerraceeditorid']:
        raise Exception('Characters must be the same race!')
    # Get the player data from the source save
    sourcecfdata = extract.parse_changeforms(sourcedata['changeforms'])
    sourceplayer = extract.parse_player(sourcecfdata['playerdata'],
                                        sourcecfdata['playerchangeflags'],
                                        sourcegame)
    # Get the data from target save
    targetcfdata = extract.parse_changeforms(targetdata['changeforms'])
    targetplayer = extract.parse_player(targetcfdata['playerdata'],
                                        targetcfdata['playerchangeflags'],
                                        targetgame)
    # Merge players, return target player with source's face
    newplayer, newflags = extract.merge_player(
        sourceplayer, sourcecfdata['playerchangeflags'],
        targetplayer, targetcfdata['playerchangeflags'],
        sourcegame
    )
    # Encode and put the new face and flags in the target changeform data
    targetcfdata['playerdata'] = extract.encode_player(newplayer, sourcegame)
    targetcfdata['playerchangeflags'] = newflags
    # Encode the changeform data and put it in the target main data
    targetdata['changeforms'] = extract.encode_changeforms(targetcfdata)
    # Then encode the whole file
    newrawdata = extract.encode_savedata(targetdata)
    # Write to disk
    i = 0
    while os.path.isfile(targetfname+'.facebak'+str(i)):
        i += 1
    rename(targetfname, targetfname+'.facebak'+str(i))
    with open(targetfname, 'wb') as f:
        f.write(newrawdata)
    return True
def dump_file(fname, rawplayer, npc, achr):
    with open(fname, 'rb') as f:
        rawdata = f.read()
    game, data = extract.parse_savedata(rawdata)
    cfdata = extract.parse_changeforms(data['changeforms'])
    if rawplayer:
        with open(join('savedumps', basename(fname) + '.rawsavedump'), 'w') as f:
            f.write('{}\n\n{}'.format(cfdata['playerchangeflags'],
                                      readable_bytes(cfdata['playerdata'])))
        return

    player = extract.parse_player(cfdata['playerdata'],
                                  cfdata['playerchangeflags'],
                                  game)
    if npc:
        out = ''
        if game == 'fallout4':
            keys = defaultdict(str)
            keys['fname'] = fname
            keys['flags'] = cfdata['playerchangeflags']
            keys.update({k:(readable_bytes(v) if isinstance(v, bytes) else v)
                         for k,v in player.items()})
            out = falloutformat.format_map(keys)
        with open(join('savedumps', basename(fname) + '.savedump'), 'w') as f:
            f.write(out)
    if achr:
        cfdata2 = extract.parse_changeforms(data['changeforms'], refidnr=0x14)
        with open(join('savedumps', basename(fname) + '.ACHRsavedump'), 'w') as f:
            flags = cfdata2['playerchangeflags']
            f.write('{}\n\n{}'.format(flags, readable_bytes(cfdata2['playerdata'])))
Example #5
0
def dump_file(fname, rawplayer, npc, achr):
    with open(fname, 'rb') as f:
        rawdata = f.read()
    game, data = extract.parse_savedata(rawdata)
    cfdata = extract.parse_changeforms(data['changeforms'])
    if rawplayer:
        with open(join('savedumps',
                       basename(fname) + '.rawsavedump'), 'w') as f:
            f.write('{}\n\n{}'.format(cfdata['playerchangeflags'],
                                      readable_bytes(cfdata['playerdata'])))
        return

    player = extract.parse_player(cfdata['playerdata'],
                                  cfdata['playerchangeflags'], game)
    if npc:
        out = ''
        if game == 'fallout4':
            keys = defaultdict(str)
            keys['fname'] = fname
            keys['flags'] = cfdata['playerchangeflags']
            keys.update({
                k: (readable_bytes(v) if isinstance(v, bytes) else v)
                for k, v in player.items()
            })
            out = falloutformat.format_map(keys)
        with open(join('savedumps', basename(fname) + '.savedump'), 'w') as f:
            f.write(out)
    if achr:
        cfdata2 = extract.parse_changeforms(data['changeforms'], refidnr=0x14)
        with open(join('savedumps',
                       basename(fname) + '.ACHRsavedump'), 'w') as f:
            flags = cfdata2['playerchangeflags']
            f.write('{}\n\n{}'.format(flags,
                                      readable_bytes(cfdata2['playerdata'])))
Example #6
0
 def decode_and_encode(self, root):
     for path, _, fnames in os.walk(root):
         for fname in fnames:
             with open(os.path.join(path, fname), 'rb') as f:
                 rawdata = f.read()
             _, data = extract.parse_savedata(rawdata)
             rawdata2 = extract.encode_savedata(data)
             self.assertEqual(rawdata, rawdata2)
Example #7
0
def transfer_face(sourcefname: str, targetfname: str):
    """
    Copy facial data from one save file to another. This function should be
    the main entry point for the UI.
    """
    with open(sourcefname, 'rb') as f:
        sourcerawdata = f.read()
    with open(targetfname, 'rb') as f:
        targetrawdata = f.read()
    sourcegame, sourcedata = extract.parse_savedata(sourcerawdata)
    targetgame, targetdata = extract.parse_savedata(targetrawdata)
    if sourcegame != targetgame:
        raise Exception('Saves are not from the same game!')
    if sourcedata['playersex'] != targetdata['playersex']:
        raise Exception('Characters must have the same gender!')
    if sourcedata['playerraceeditorid'] != targetdata['playerraceeditorid']:
        raise Exception('Characters must be the same race!')
    # Get the player data from the source save
    sourcecfdata = extract.parse_changeforms(sourcedata['changeforms'])
    sourceplayer = extract.parse_player(sourcecfdata['playerdata'],
                                        sourcecfdata['playerchangeflags'],
                                        sourcegame)
    # Get the data from target save
    targetcfdata = extract.parse_changeforms(targetdata['changeforms'])
    targetplayer = extract.parse_player(targetcfdata['playerdata'],
                                        targetcfdata['playerchangeflags'],
                                        targetgame)
    # Merge players, return target player with source's face
    newplayer, newflags = extract.merge_player(
        sourceplayer, sourcecfdata['playerchangeflags'], targetplayer,
        targetcfdata['playerchangeflags'], sourcegame)
    # Encode and put the new face and flags in the target changeform data
    targetcfdata['playerdata'] = extract.encode_player(newplayer, sourcegame)
    targetcfdata['playerchangeflags'] = newflags
    # Encode the changeform data and put it in the target main data
    targetdata['changeforms'] = extract.encode_changeforms(targetcfdata)
    # Then encode the whole file
    newrawdata = extract.encode_savedata(targetdata)
    # Write to disk
    i = 0
    while os.path.isfile(targetfname + '.facebak' + str(i)):
        i += 1
    rename(targetfname, targetfname + '.facebak' + str(i))
    with open(targetfname, 'wb') as f:
        f.write(newrawdata)
    return True
Example #8
0
 def decode_and_encode_changeforms(self, root):
     for path, _, fnames in os.walk(root):
         for fname in fnames:
             with open(os.path.join(path, fname), 'rb') as f:
                 rawdata = f.read()
             _, data = extract.parse_savedata(rawdata)
             rawcf1 = data['changeforms']
             cf = extract.parse_changeforms(rawcf1)
             rawcf2 = extract.encode_changeforms(cf)
             self.assertEqual(rawcf1, rawcf2)
Example #9
0
 def decode_and_encode_player(self, root):
     for path, _, fnames in os.walk(root):
         for fname in fnames:
             with open(os.path.join(path, fname), 'rb') as f:
                 rawdata = f.read()
             game, data = extract.parse_savedata(rawdata)
             cf = extract.parse_changeforms(data['changeforms'])
             rawplayer1 = cf['playerdata']
             player = extract.parse_player(rawplayer1, cf['playerchangeflags'], game)
             rawplayer2 = extract.encode_player(player, game)
             self.assertEqual(rawplayer1, rawplayer2)
Example #10
0
def dry_transfer(sourcefname, targetfname):
    with open(sourcefname, 'rb') as f:
        sourcerawdata = f.read()
    with open(targetfname, 'rb') as f:
        targetrawdata = f.read()
    sourcegame, sourcedata = extract.parse_savedata(sourcerawdata)
    targetgame, targetdata = extract.parse_savedata(targetrawdata)
    # Get the player data from the source save
    sourcecfdata = extract.parse_changeforms(sourcedata['changeforms'])
    sourceplayer = extract.parse_player(sourcecfdata['playerdata'],
                                        sourcecfdata['playerchangeflags'],
                                        sourcegame)
    # Get the data from target save
    targetcfdata = extract.parse_changeforms(targetdata['changeforms'])
    targetplayer = extract.parse_player(targetcfdata['playerdata'],
                                        targetcfdata['playerchangeflags'],
                                        targetgame)
    # Merge players, return target player with source's face
    newplayer, newflags = extract.merge_player(
        sourceplayer, sourcecfdata['playerchangeflags'], targetplayer,
        targetcfdata['playerchangeflags'], sourcegame)
    pp = pprint.PrettyPrinter(indent=4)
    pp.pprint(newplayer)
def get_ui_data(fname):
    """
    Return data useful for the UI to display, such as name, file info etc.
    """
    with open(fname, 'rb') as f:
        rawdata = f.read()
    game, data = extract.parse_savedata(rawdata)
    out = {}
    out['save number'] = data['savenumber']
    out['name'] = data['playername']
    out['level'] = data['playerlevel']
    out['location'] = data['playerlocation']
    out['race'] = data['playerraceeditorid']
    out['gender'] = data['playersex']
    out['playing time'] = data['gamedate']
    out['screenshot'] = (data['shotwidth'], data['shotheight'], data['screenshotdata'])
    return out, game
Example #12
0
def get_ui_data(fname):
    """
    Return data useful for the UI to display, such as name, file info etc.
    """
    with open(fname, 'rb') as f:
        rawdata = f.read()
    game, data = extract.parse_savedata(rawdata)
    out = {}
    out['save number'] = data['savenumber']
    out['name'] = data['playername']
    out['level'] = data['playerlevel']
    out['location'] = data['playerlocation']
    out['race'] = data['playerraceeditorid']
    out['gender'] = data['playersex']
    out['playing time'] = data['gamedate']
    out['screenshot'] = (data['shotwidth'], data['shotheight'],
                         data['screenshotdata'])
    return out, game