Skip to content

Instantly share code, notes, and snippets.

@einsteinx2
Last active June 26, 2023 19:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save einsteinx2/ccdd6522ec08cc74f2e16beb0e95f7c6 to your computer and use it in GitHub Desktop.
Save einsteinx2/ccdd6522ec08cc74f2e16beb0e95f7c6 to your computer and use it in GitHub Desktop.
Small python script to convert a folder full of *.nkit.iso files into the folder structure needed for use on a modded Wii
#!/usr/bin/env python3
# Requires: Python 3.7 (might work on 3.6, but I haven't tested)
# Purpose: Convert a folder full of *.nkit.iso (uncompressed) files into the folder structure needed for use on a modded Wii
# File names: Games must be named like "Game Name [GAMEID].nkit.iso"
# Multi-disc: Multi-disc games must be named like "Game Name (Disc 1) [GAMEID].nkit.iso" and "Game Name (Disc 2) [GAMEID].nkit.iso"
# Notes: Supports both copy and move, if you name your games differently you'll need to modify the script as it was made for my personal use
# TODO:
# - Better documentation
# - Support different naming schemes
# - Support Python 2.7 (maybe)
import os
import glob
import collections
import array
import shutil
import argparse
from pprint import pprint
from pathlib import Path
from operator import attrgetter
# Constants
NKIT_EXT = '.nkit.iso'
DISC1_STR = ' (Disc 1) '
DISC2_STR = ' (Disc 2) '
DISC1_FILENAME = 'game.iso'
DISC2_FILENAME = 'disc2.iso'
# Named tuple representing each disc
DiscImage = collections.namedtuple('DiscImage', 'in_path, in_filename, out_foldername, out_filename')
# Find all nkit isos and in the input path and calculate their output folder and file names
def process_discs(in_path):
# Array of processed discs so we can do all the processing first before modifying the filesystem
discs = []
# Process the list of discs
glob_str = os.path.join(in_path, F'*{NKIT_EXT}')
for in_path in glob.iglob(glob_str):
# Get the original nkit iso file name
in_filename = os.path.basename(in_path)
# Get the file name without the extension to use as the folder name
out_foldername = in_filename[:-len(NKIT_EXT)]
# Check if it's a multi-disc game and handle it properly
out_filename = DISC1_FILENAME
if DISC1_STR in in_filename:
# Build the correct folder name by removing the (Disc 1) string
split = out_foldername.split(DISC1_STR)
assert len(split) == 2, F"Could not split game disc 1 name, len(split) = {len(split)}"
out_foldername = F"{split[0]} {split[1]}"
elif DISC2_STR in in_filename:
# Build the correct folder name by removing the (Disc 2) string
split = out_foldername.split(DISC2_STR)
assert len(split) == 2, F"Could not split game disc 2 name, len(split) = {len(split)}"
out_foldername = F"{split[0]} {split[1]}"
# Second discs must be named disc2.iso
out_filename = DISC2_FILENAME
# Create the DiscImage named tuple and add it to the list of discs
discs.append(DiscImage(in_path = in_path, in_filename = in_filename, out_foldername = out_foldername, out_filename = out_filename))
# Sort by file name
discs.sort(key = attrgetter('in_filename'))
# Return the list of DiscImage named tuples
return discs
# Copy (or move) the files to their new locations
def copy_discs(discs, out_path, move = False, dry_run = False):
for disc in discs:
# Determine the output path
out_folder_path = os.path.join(out_path, disc.out_foldername)
out_file_path = os.path.join(out_folder_path, disc.out_filename)
# Create the output directory
Path(out_folder_path).mkdir(parents = True, exist_ok = True)
if move is True:
# Move the file
print(F'Moving "{disc.in_path}" to "{out_file_path}".....', end = '')
if dry_run is False:
shutil.move(disc.in_path, out_file_path)
print("Done!")
else:
# Copy the file
print(F'Copying "{disc.in_path}" to "{out_file_path}".....', end = '')
if dry_run is False:
shutil.copy2(disc.in_path, out_file_path)
print("Done")
def parse_args():
parser = argparse.ArgumentParser()
# Positional arguments
parser.add_argument('in_path', help = 'Path to the input directory that contains *.nkit.iso files that are in the format "Name Of Game [GAMEID].nkit.iso"')
parser.add_argument('out_path', help = 'Path to the output directory where the Wii / Nintendont file structure will be created (e.g. your "games" folder)')
# Optional arguments
parser.add_argument('-m', '--move', help='Move the disc images instead of copying them (WARNING! Make sure you have a backup copy first!)', action='store_true')
parser.add_argument('-d', '--dry-run', help='Just print out what would happen, but do not copy or move any files', action='store_true')
return parser.parse_args()
def main():
args = parse_args()
if args.dry_run is True:
print("Performing dry run...\n")
discs = process_discs(args.in_path)
copy_discs(discs, args.out_path, args.move, args.dry_run)
# Execute only if run as a script
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment