Пример #1
0
def patch_images(selected_images, cfg):
    backup_directory = pathjoin(exe_dir, 'backup')
    bin_dir = pathjoin(exe_dir, 'bin')

    for i, disk_path in enumerate(selected_images):
        image = cfg.images[i]
        disk_directory = pathsplit(disk_path)[0]
        DiskImage = Disk(disk_path,
                         backup_folder=backup_directory,
                         ndc_dir=bin_dir)

        if not access(disk_path, W_OK):
            message_wait_close(
                'Can\'t access the file "%s". Make sure the file is not read-only.'
                % disk_path)

        print("Backing up %s to %s now..." % (disk_path, backup_directory))
        if stat(disk_path).st_size > 100000000:  # 100 MB+ disk images
            print(
                "This is a large disk image, so it may take a few moments...")
        try:
            DiskImage.backup()
        except PermissionError:
            message_wait_close(
                'Can\'t access the file "%s". Make sure the file is not in use.'
                % disk_path)

        if DiskImage.extension in HARD_DISK_FORMATS:
            files = image['hdd']['files']
        else:
            files = image['floppy']['files']

        # Find the right directory to look for the files in.
        disk_filenames = [f['name'] for f in files]

        #path_in_disk = DiskImage.find_file_dir(disk_filenames)
        #if path_in_disk is None:
        #    message_wait_close("Can\'t access the file '%s' now, but could before. Make sure it is not in use, and try again." % disk_path)

        for f in files:
            # Ignore files that lack a patch
            try:
                _ = f['patch']
            except KeyError:
                continue

            print('Extracting %s...' % f['name'])
            paths_in_disk = [
                p.decode('shift_jis') for p in DiskImage.find_file(f['name'])
            ]
            #print(paths_in_disk)
            #print(path_in_disk)
            patch_worked = False
            for j, path_in_disk in enumerate(paths_in_disk):
                #print(path_in_disk)
                if patch_worked:
                    break

                try:
                    DiskImage.extract(f['name'], path_in_disk)
                except FileNotFoundError:
                    print("Error. Restoring from backup...")
                    DiskImage.restore_from_backup()
                    message_wait_close(
                        "Couldn't access the disk. Make sure it is not open in EditDisk/ND, and try again."
                    )
                extracted_file_path = pathjoin(disk_directory, f['name'])
                copyfile(extracted_file_path, extracted_file_path + '_edited')

                # Failsafe list. Patches to try in order.
                patch_list = []
                if 'type' in f['patch']:
                    if f['patch']['type'] == 'failsafelist':
                        patch_list = f['patch']['list']
                    elif f['patch']['type'] == 'boolean':
                        if options[f['patch']['id']]:
                            patch_list = [
                                f['patch']['true'],
                            ]
                        else:
                            patch_list = [
                                f['patch']['false'],
                            ]
                else:
                    patch_list = [
                        f['patch'],
                    ]

                #patch_worked = False
                for i, patch in enumerate(patch_list):
                    patch_filepath = pathjoin(exe_dir, 'patch', patch)
                    patchfile = Patch(extracted_file_path,
                                      patch_filepath,
                                      edited=extracted_file_path + '_edited',
                                      xdelta_dir=bin_dir)
                    try:
                        print("Patching %s..." % f['name'])
                        patchfile.apply()
                        patch_worked = True
                    except PatchChecksumError:
                        if i < len(patch_list) - 1:
                            print("Trying backup patch for %s..." % f['name'])
                if not patch_worked and j < len(paths_in_disk) - 1:
                    print("Trying another file with the name %s..." %
                          f['name'])

            if not patch_worked:
                print("Error. Restoring from backup...")
                DiskImage.restore_from_backup()
                remove(extracted_file_path)
                remove(extracted_file_path + '_edited')
                message_wait_close(
                    "Patch checksum error. This disk is not compatible with this patch, or is already patched."
                )

            copyfile(extracted_file_path + '_edited', extracted_file_path)
            if not options['delete_all_first']:
                print("Inserting %s..." % f['name'])
                try:
                    DiskImage.insert(extracted_file_path, path_in_disk)
                except ReadOnlyDiskError:
                    print("Error. Restoring from backup...")
                    DiskImage.restore_from_backup()
                    message_wait_close(
                        "Error inserting %s. Make sure the disk is not read-only or open in EditDisk/ND, and try again."
                        % f['name'])
                remove(extracted_file_path)
                remove(extracted_file_path + '_edited')

        if options['delete_all_first']:
            for f in files:
                try:
                    print("Deleting %s..." % f['name'])
                    DiskImage.delete(f['name'], path_in_disk)
                except ReadOnlyDiskError:
                    print("Error. Restoring from backup...")
                    DiskImage.restore_from_backup()
                    message_wait_close(
                        "Error deleting %s. Make sure the disk is not read-only, and try again."
                    )
            for f in files:
                extracted_file_path = pathjoin(disk_directory, f['name'])
                print("Inserting %s..." % f['name'])
                try:
                    DiskImage.insert(extracted_file_path,
                                     path_in_disk,
                                     delete_original=False)
                except ReadOnlyDiskError:
                    print("Error. Restoring from backup...")
                    DiskImage.restore_from_backup()
                    message_wait_close(
                        "Error inserting", f,
                        ". Make sure the disk is not read-only or open in EditDisk/ND, and try again."
                    )
                remove(extracted_file_path)
                remove(extracted_file_path + '_edited')

        for f in cfg.new_files:
            new_file_path = pathjoin(exe_dir, 'patch', f['name'])
            print("Inserting new file %s..." % f['name'])
            DiskImage.insert(new_file_path,
                             path_in_disk,
                             delete_original=False)