示例#1
0
        public void ConfigStoreTestCreateFromConfigFileMissing()
        {
            ConfigStore store = ConfigStore.CreateFromFile("config.missing.ini", ENV_PREFIX);

            Assert.Null(store.Get <string>("CONFIG_WITH_NO_SECTION"));

            store = ConfigStore.CreateFromFile("config.missing.ini");

            Assert.Null(store.Get <string>("CONFIG_WITH_NO_SECTION"));
        }
示例#2
0
        public void ConfigStoreTestCreateFromConfigFile()
        {
            ConfigStore store = ConfigStore.CreateFromFile("config.ini", ENV_PREFIX);

            Assert.Equal("VALUE_01", store.Get <string>("CONFIG_WITH_NO_SECTION"));

            store = ConfigStore.CreateFromFile("config.ini");

            Assert.Equal("VALUE_01", store.Get <string>("CONFIG_WITH_NO_SECTION"));
        }
示例#3
0
        public void ConfigStoreTestGet()
        {
            ConfigStore store = ConfigStore.CreateFromFile("config.ini", ENV_PREFIX);

            Assert.Equal("VALUE_01", store.Get <string>("CONFIG_WITH_NO_SECTION"));
            Assert.Equal("VALUE_03", store.Get <string>("SECTION1", "CONFIG_INSIDE_SECTION1"));
            Assert.Equal("VALUE_01", store.GetWithDefaultValue("CONFIG_WITH_NO_SECTION", "WRONG_VALUE"));
            Assert.Equal("VALUE_03", store.GetWithDefaultValue("SECTION1", "CONFIG_INSIDE_SECTION1", "WRONG_VALUE"));
            Assert.Equal("DEFAULT_VALUE", store.GetWithDefaultValue("WRONG_KEY", "DEFAULT_VALUE"));
            Assert.Equal("DEFAULT_VALUE", store.GetWithDefaultValue("WRONG_SECTION", "WRONG_KEY", "DEFAULT_VALUE"));
        }
示例#4
0
        /// <summary>
        /// Initialize, or re-initialize the mod database.
        /// </summary>
        public static void Initialize()
        {
            Log.ModDatabase.Info("Initializing mod database");

            sModById    = new Dictionary <Guid, Mod>();
            sModsByGame = new Dictionary <Game, List <Mod> >();
            foreach (Game value in Enum.GetValues(typeof(Game)))
            {
                sModsByGame[value] = new List <Mod>();
            }

            var config = ConfigStore.Get <ModDatabaseConfig>();

            ModDirectory = config.ModsDirectoryPath;

            if (!Directory.Exists(ModDirectory))
            {
                Log.ModDatabase.Error("Mods directory doesn't exist; creating new directory...");
                Directory.CreateDirectory(ModDirectory);
            }
            else
            {
                // Todo: Different mod types?
                var modLoader = new XmlModLoader();

                foreach (var directory in Directory.EnumerateDirectories(ModDirectory))
                {
                    TryLoadModDirectory(modLoader, directory);
                }
            }
        }
示例#5
0
 protected void OnGameChange(object sender, EventArgs e)
 {
     SelectedGame = (Game)(GameSelect.Active + 1);
     GameConfig   = ConfigStore.Get(SelectedGame);
     RefreshMods();
     Console.WriteLine("Now Modding:" + SelectedGame);
 }
示例#6
0
 private void GameComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
 {
     SelectedGame = ( Game )(GameComboBox.SelectedIndex + 1);
     GameConfig   = ConfigStore.Get(SelectedGame);
     RefreshMods();
     InitializeFolderComboBox();
 }
        public Initializer()
        {
            Console.WriteLine("Yo you wanna learn how to do a f****n infinite?");
            var version = Assembly.GetExecutingAssembly().GetName().Version;

            Console.WriteLine($"Mod Compendium {version.Major}.{version.Minor}.{version.Revision}");
            Config = ConfigStore.Get <MainWindowConfig>();
            Console.WriteLine("Currently modding: " + Config.SelectedGame);
        }
示例#8
0
        public void ConfigStoreTestCreateFromConfigFileOverridedByEnvVar()
        {
            Environment.SetEnvironmentVariable(CONF_FILE_VAR, "config.ini");

            ConfigStore store = ConfigStore.CreateFromFile("config.missing.ini", ENV_PREFIX);

            Assert.Equal("VALUE_01", store.Get <string>("CONFIG_WITH_NO_SECTION"));

            Environment.SetEnvironmentVariable(CONF_FILE_VAR, null);
        }
示例#9
0
        public MainWindow()
        {
            InitializeComponent();
            InitializeLog();

            var version = Assembly.GetExecutingAssembly().GetName().Version;

            Title  = $"Mod Compendium {version.Major}.{version.Minor}.{version.Revision}";
            Config = ConfigStore.Get <MainWindowConfig>();
            InitializeGameComboBox();
        }
        //Window startup
        public MainWindow()
        {
            //starts the window I guess
            InitializeComponent();
            InitializeLog();
            //gets the Assembly version
            var version = Assembly.GetExecutingAssembly().GetName().Version;

            //appends it to mod compendium in the window title.
            Title = $"Mod Compendium {version.Major}.{version.Minor}.{version.Revision}";
            //retrieves the the main window configuration through the dark arts.
            Config = ConfigStore.Get <MainWindowConfig>();
            InitializeGameComboBox();
        }
示例#11
0
    /// <summary>
    /// Runs when the Main Window Initializes.
    /// </summary>
    public MainWindow() : base(Gtk.WindowType.Toplevel)
    {
        Build();
        this.Deleted.Sensitive = false;
        InitializeLog();
        //gets the Assembly version
        var version = Assembly.GetExecutingAssembly().GetName().Version;

        //appends it to mod compendium in the window title.
        Title = $"Mod Compendium {version.Major}.{version.Minor}.{version.Revision}";
        //retrieves the the main window configuration from the config store.
        Config = ConfigStore.Get <MainWindowConfig>();
        //retrieves the gameconfig previously in use from the combo box
        //which is set from the Main Window (somehow)
        SelectedGame = (Game)(GameSelect.Active + 1);
        //retrieves the gameconfig previously in use.
        GameConfig = ConfigStore.Get(SelectedGame);
        //starts the ModGrid.
        InitializeModGrid();
        //Refreshes the mod database to collect the correct mods
        RefreshModDatabase();
        //starts the combobox (shouldn't it be already be initialized?)
        InitializeGameComboBox();
    }
示例#12
0
        /// <inheritdoc />
        public VirtualFileSystemEntry Build(VirtualDirectory root, string hostOutputPath = null, string gameName = null, bool useCompression = false, bool useExtracted = false)
        {
            gameName = Game.ToString();

            if (root == null)
            {
                throw new ArgumentNullException(nameof(root));
            }

            //Get game config
            var config = ConfigStore.Get(Game) as ModCpkGameConfig ?? throw new InvalidOperationException("Game config is missing.");

            Log.Builder.Info($"Building {gameName} Mod");
            Log.Builder.Info("Processing mod files");

            var modFilesDirectory = new VirtualDirectory(null, "mod");

            foreach (var entry in root)
            {
                if (entry.EntryType == VirtualFileSystemEntryType.Directory)
                {
                    var directory = (VirtualDirectory)entry;
                    var name      = directory.Name.ToLowerInvariant();

                    switch (name)
                    {
                    case "mod":
                    case "data":
                    {
                        // Move files in 'cpk' directory to 'mod' directory
                        LogModFilesInDirectory(directory);

                        foreach (var modFileEntry in directory)
                        {
                            modFileEntry.CopyTo(modFilesDirectory);
                        }
                    }
                    break;

                    default:
                        // Move directory to 'mod' directory
                        Log.Builder.Trace($"Adding directory {entry.FullName} to mod.cpk");
                        entry.CopyTo(modFilesDirectory);
                        break;
                    }
                }
                else
                {
                    // Move file to 'mod' directory
                    Log.Builder.Trace($"Adding file {entry.FullName} to mod.cpk");
                    entry.CopyTo(modFilesDirectory);
                }
            }

            bool.TryParse(config.Compression, out useCompression);

            // Build mod cpk
            Log.Builder.Info("Building mod.cpk");
            var cpkModCompiler = new CpkModBuilder();

            if (hostOutputPath != null)
            {
                Directory.CreateDirectory(hostOutputPath);
            }

            var cpkFilePath = hostOutputPath != null?Path.Combine(hostOutputPath, "mod.cpk") : null;

            var cpkNotWritable   = File.Exists(cpkFilePath) && FileHelper.IsFileInUse(cpkFilePath);
            var cpkFileBuildPath = hostOutputPath != null?cpkNotWritable?Path.Combine(Path.GetTempPath(), "mod.cpk") : cpkFilePath : null;

            var cpkFile = cpkModCompiler.Build(modFilesDirectory, cpkFileBuildPath, gameName, useCompression);

            if (cpkFileBuildPath != cpkFilePath)
            {
                File.Copy(cpkFileBuildPath, cpkFilePath, true);
                File.Delete(cpkFileBuildPath);
                cpkFile = VirtualFile.FromHostFile(cpkFilePath);
            }

            Log.Builder.Info("Done!");

            return(cpkFile);
        }
示例#13
0
 protected override Persona34GameConfig GetConfig() => ConfigStore.Get <Persona4GameConfig>();
示例#14
0
        /// <inheritdoc />
        public VirtualFileSystemEntry Build(VirtualDirectory root, List <Mod> enabledMods, string hostOutputPath = null, string gameName = null, bool useCompression = false, bool useExtracted = false)
        {
            gameName = Game.ToString();

            if (root == null)
            {
                throw new ArgumentNullException(nameof(root));
            }

            //Get game config
            var config = ConfigStore.Get(Game) as ModCpkGameConfig ?? throw new InvalidOperationException("Game config is missing.");

            Log.Builder.Info($"Building {gameName} Mod");
            Log.Builder.Info("Processing mod files");

            bool pc = Convert.ToBoolean(config.PC);
            var  modFilesDirectory = new VirtualDirectory();

            if (!pc)
            {
                modFilesDirectory = new VirtualDirectory(null, "mod");
            }
            else
            {
                modFilesDirectory = new VirtualDirectory(null, "");
            }

            foreach (var entry in root)
            {
                if (entry.EntryType == VirtualFileSystemEntryType.Directory)
                {
                    var directory = (VirtualDirectory)entry;
                    var name      = directory.Name.ToLowerInvariant();

                    switch (name)
                    {
                    case "mod":
                    case "data":
                    {
                        // Move files in 'cpk' directory to 'mod' directory
                        LogModFilesInDirectory(directory);

                        foreach (var modFileEntry in directory)
                        {
                            modFileEntry.CopyTo(modFilesDirectory);
                        }
                    }
                    break;

                    default:
                        // Move directory to 'mod' directory
                        Log.Builder.Trace($"Adding directory {entry.FullName} to mod.cpk");
                        entry.CopyTo(modFilesDirectory);
                        break;
                    }
                }
                else
                {
                    // Move file to 'mod' directory
                    Log.Builder.Trace($"Adding file {entry.FullName} to mod.cpk");
                    entry.CopyTo(modFilesDirectory);
                }
            }

            bool.TryParse(config.Compression, out useCompression);

            // If PC Mode is enabled, clear and replace contents
            if (pc)
            {
                if (Directory.Exists(hostOutputPath))
                {
                    foreach (var directory in Directory.GetDirectories(hostOutputPath))
                    {
                        Log.Builder.Info($"Replacing Output Path contents");
                        string[] stringArray = { "data00000", "data00001", "data00002", "data00003", "data00004", "data00005", "data00006", "movie00000", "movie00001", "movie00002", "snd", "data_e" };
                        if (stringArray.Any(Path.GetFileName(directory).ToLower().Equals))
                        {
                            Directory.Delete(directory, true);
                        }
                    }
                }

                Directory.CreateDirectory(Path.GetFullPath(hostOutputPath));
                modFilesDirectory.SaveToHost(hostOutputPath);
                Log.Builder.Info("Done!");
                return(modFilesDirectory);
            }
            else
            {
                // Build mod cpk
                Log.Builder.Info($"Building mod.cpk");
                var cpkModCompiler = new CpkModBuilder();

                if (hostOutputPath != null)
                {
                    Directory.CreateDirectory(hostOutputPath);
                }

                var cpkFilePath = hostOutputPath != null?Path.Combine(hostOutputPath, "mod.cpk") : null;

                var cpkNotWritable   = File.Exists(cpkFilePath) && FileHelper.IsFileInUse(cpkFilePath);
                var cpkFileBuildPath = hostOutputPath != null?cpkNotWritable?Path.Combine(Path.GetTempPath(), "mod.cpk") : cpkFilePath : null;

                var cpkFile = cpkModCompiler.Build(modFilesDirectory, enabledMods, cpkFileBuildPath, gameName, useCompression);

                if (cpkFileBuildPath != cpkFilePath)
                {
                    File.Copy(cpkFileBuildPath, cpkFilePath, true);
                    File.Delete(cpkFileBuildPath);
                    cpkFile = VirtualFile.FromHostFile(cpkFilePath);
                }
                Log.Builder.Info("Done!");
                return(cpkFile);
            }
        }
示例#15
0
        /// <inheritdoc />
        public VirtualFileSystemEntry Build(VirtualDirectory root, string hostOutputPath = null, string gameName = null, bool useCompression = false, bool useExtracted = false)
        {
            gameName = Game.ToString();

            if (root == null)
            {
                throw new ArgumentNullException(nameof(root));
            }

            // Get game config
            var config = ConfigStore.Get(Game) as CatherineFullBodyGameConfig;

            if (config == null)
            {
                // Unlikely
                throw new InvalidOperationException("Game config is missing.");
            }

            if (string.IsNullOrWhiteSpace(config.CpkRootOrPath))
            {
                throw new InvalidConfigException("CPK path is not specified.");
            }

            // Create temp folder
            var cpkRootDirectoryPath = Path.Combine(Path.GetTempPath(), $"{Game}ModCompilerTemp_" + Path.GetRandomFileName());

            Log.Builder.Trace($"Creating temp output directory: {cpkRootDirectoryPath}");
            Directory.CreateDirectory(cpkRootDirectoryPath);

            // Get files from CPK
            VirtualDirectory cpkRootDirectory;

            Log.Builder.Trace($"{nameof(config.CpkRootOrPath)} = {config.CpkRootOrPath}");

            if (config.CpkRootOrPath.EndsWith(".cpk"))
            {
                // If extraction is enabled, use files from CPK path
                useExtracted = Convert.ToBoolean(config.Extract);
                if (useExtracted)
                {
                    Log.Builder.Info($"Extracting CPK: {config.CpkRootOrPath}");

                    if (!File.Exists(config.CpkRootOrPath))
                    {
                        throw new InvalidConfigException($"CPK root path references a CPK file that does not exist: {config.CpkRootOrPath}.");
                    }

                    string[] args = { "-x", "-i", config.CpkRootOrPath, "-d", cpkRootDirectoryPath };
                    CriPakTools.Program.Main(args);
                }
                // Cpk file found & extracted, convert it to our virtual file system
                cpkRootDirectory      = VirtualDirectory.FromHostDirectory(cpkRootDirectoryPath);
                cpkRootDirectory.Name = Path.GetFileNameWithoutExtension(config.CpkRootOrPath);
            }
            else
            {
                Log.Builder.Info($"Mounting directory: {config.CpkRootOrPath}");

                if (!Directory.Exists(config.CpkRootOrPath))
                {
                    throw new InvalidConfigException($"CPK root path references a directory that does not exist: {config.CpkRootOrPath}.");
                }

                // No CPK file found, assume files are extracted
                cpkRootDirectory      = VirtualDirectory.FromHostDirectory(config.CpkRootOrPath);
                cpkRootDirectory.Name = Path.GetDirectoryName(config.CpkRootOrPath);
            }

            Log.Builder.Info("Processing mod files");
            foreach (var entry in root)
            {
                if (entry.EntryType == VirtualFileSystemEntryType.Directory)
                {
                    var directory = (VirtualDirectory)entry;
                    var name      = directory.Name.ToLowerInvariant();

                    switch (name)
                    {
                    case "mod":
                    case "cache":
                    case "umd0":
                    case "umd1":
                    case "vita":
                    case "patch":
                    case "memst":
                    {
                        // Move files in 'cpk' directory to 'mod' directory
                        LogModFilesInDirectory(directory);

                        foreach (var modFileEntry in directory)
                        {
                            modFileEntry.CopyTo(cpkRootDirectory);
                        }
                    }
                    break;

                    default:
                        // Move directory to 'mod' directory
                        Log.Builder.Trace($"Adding directory {entry.FullName} to {cpkRootDirectory.Name}.cpk");
                        entry.CopyTo(cpkRootDirectory);
                        break;
                    }
                }
                else
                {
                    // Move file to 'mod' directory
                    Log.Builder.Trace($"Adding file {entry.FullName} to {cpkRootDirectory.Name}.cpk");
                    entry.CopyTo(cpkRootDirectory);
                }
            }

            useCompression = Convert.ToBoolean(config.Compression);

            // Build mod cpk
            var cpkModCompiler = new CpkModBuilder();
            var cpkFilePath    = hostOutputPath != null?Path.Combine(hostOutputPath, $"{cpkRootDirectory.Name}.cpk") : null;

            var cpkFile = cpkModCompiler.Build(cpkRootDirectory, cpkFilePath, gameName, useCompression);

            Log.Builder.Info("Done!");
            return(cpkFile);
        }
示例#16
0
        /// <inheritdoc />
        public VirtualFileSystemEntry Build(VirtualDirectory root, string hostOutputPath = null, string gameName = null, bool useCompression = false, bool useExtracted = false)
        {
            if (root == null)
            {
                throw new ArgumentNullException(nameof(root));
            }

            Log.Builder.Info($"Building {Game} Mod");
            if (hostOutputPath != null)
            {
                Log.Builder.Info($"Output directory: {hostOutputPath}");
            }

            // Get game config
            var config = ConfigStore.Get(Game) as Persona34GameConfig ?? throw new InvalidOperationException("Game config is missing.");

            if (string.IsNullOrWhiteSpace(config.DvdRootOrIsoPath))
            {
                throw new InvalidConfigException("Dvd root path/ISO path is not specified.");
            }

            // Get files
            Log.Builder.Trace($"DvdRootOrIsoPath = {config.DvdRootOrIsoPath}");
            var dvdRootDirectory = Persona34Common.GetRootDirectory(config, out var isoFileSystem);

            // Find system config
            var systemConfigFile = dvdRootDirectory["SYSTEM.CNF"] as VirtualFile ?? throw new MissingFileException("SYSTEM.CNF is missing from the file source.");

            string executablePath;

            using (var systemConfigStream = systemConfigFile.Open())
            {
                bool leaveOpen = isoFileSystem == null;
                executablePath = Ps2SystemConfig.GetExecutablePath(systemConfigStream, leaveOpen, true);
            }

            if (executablePath == null)
            {
                throw new MissingFileException("Executable file path is not specified in SYSTEM.CNF; Unable to locate executable file.");
            }

            Log.Builder.Info($"Executable path: {executablePath}");

            var executableFile = ( VirtualFile )dvdRootDirectory[executablePath] ?? throw new MissingFileException("The executable file is missing from the dvd root file source.");

            // Some basic checks have been done, let's start generating the cvms
            var dvdRootDirectoryPath = hostOutputPath ?? Path.Combine(Path.GetTempPath(), "Persona34ModCompilerTemp_" + Path.GetRandomFileName());

            Log.Builder.Trace($"Creating (temp?) output directory: {dvdRootDirectoryPath}");
            Directory.CreateDirectory(dvdRootDirectoryPath);

            var bgmCvmFile      = ( VirtualFile )dvdRootDirectory["BGM.CVM"];
            var bgmCvmModified  = false;
            var btlCvmFile      = ( VirtualFile )dvdRootDirectory["BTL.CVM"];
            var btlCvmModified  = false;
            var dataCvmFile     = ( VirtualFile )dvdRootDirectory["DATA.CVM"];
            var dataCvmModified = false;
            var envCvmFile      = ( VirtualFile )dvdRootDirectory["ENV.CVM"];
            var envCvmModified  = false;

            var newDvdRootDirectory = new VirtualDirectory();

            // Process mod files
            Log.Builder.Info("Processing mod files");
            foreach (var entry in root)
            {
                if (entry.EntryType == VirtualFileSystemEntryType.File)
                {
                    Log.Builder.Info($"Adding file {entry.Name} to root directory");
                    entry.MoveTo(newDvdRootDirectory, true);
                    continue;
                }

                var name      = entry.Name.ToLowerInvariant();
                var directory = ( VirtualDirectory )entry;

                switch (name)
                {
                case "bgm":
                    UpdateAndRecompileCvm(ref bgmCvmFile, directory, Path.Combine(dvdRootDirectoryPath, "bgm.cvm"), newDvdRootDirectory);
                    bgmCvmModified = true;
                    break;

                case "btl":
                    UpdateAndRecompileCvm(ref btlCvmFile, directory, Path.Combine(dvdRootDirectoryPath, "btl.cvm"), newDvdRootDirectory);
                    btlCvmModified = true;
                    break;

                case "data":
                    UpdateAndRecompileCvm(ref dataCvmFile, directory, Path.Combine(dvdRootDirectoryPath, "data.cvm"), newDvdRootDirectory);
                    dataCvmModified = true;
                    break;

                case "env":
                {
                    Log.Builder.Info("Replacing files in env.cvm");

                    if (envCvmFile == null)
                    {
                        throw new MissingFileException("Mod replaces files in env.cvm but env.cvm isn't present.");
                    }

                    UpdateAndRecompileCvm(ref envCvmFile, directory, Path.Combine(dvdRootDirectoryPath, "env.cvm"), newDvdRootDirectory);
                    envCvmModified = true;
                }
                break;

                default:
                    Log.Builder.Info($"Adding directory {entry.Name} to root directory");
                    entry.MoveTo(newDvdRootDirectory, true);
                    break;
                }
            }

            // Patch executable
            var executableFilePath = executableFile.SaveToHost(dvdRootDirectoryPath);

            Log.Builder.Info($"Patching executable");
            Log.Builder.Trace($"Executable file path: {executableFilePath}");
            if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows))
            {
                if (bgmCvmModified)
                {
                    PatchExecutable(executableFilePath, bgmCvmFile.HostPath);
                }

                if (btlCvmModified)
                {
                    PatchExecutable(executableFilePath, btlCvmFile.HostPath);
                }

                if (dataCvmModified)
                {
                    PatchExecutable(executableFilePath, dataCvmFile.HostPath);
                }

                if (envCvmModified)
                {
                    PatchExecutable(executableFilePath, envCvmFile.HostPath);
                }
            }
            else
            {
                if (bgmCvmModified)
                {
                    PatchExecutableLinux(executableFilePath, bgmCvmFile.HostPath);
                }

                if (btlCvmModified)
                {
                    PatchExecutableLinux(executableFilePath, btlCvmFile.HostPath);
                }

                if (dataCvmModified)
                {
                    PatchExecutableLinux(executableFilePath, dataCvmFile.HostPath);
                }

                if (envCvmModified)
                {
                    PatchExecutableLinux(executableFilePath, envCvmFile.HostPath);
                }
            }

            executableFile = VirtualFile.FromHostFile(executableFilePath);
            executableFile.MoveTo(newDvdRootDirectory, true);

            if (hostOutputPath != null)
            {
                Log.Builder.Info($"Copying files to output directory (might take a while): {hostOutputPath}");
                newDvdRootDirectory.SaveToHost(hostOutputPath);
            }

            if (hostOutputPath != null && isoFileSystem != null)
            {
                isoFileSystem.Dispose();
            }

            Log.Builder.Info("Done");

            return(newDvdRootDirectory);
        }
示例#17
0
        public void ConfigStoreTestCreateFromEnvVarMissing()
        {
            ConfigStore store = ConfigStore.Create(ENV_PREFIX);

            Assert.Null(store.Get <string>("CONFIG_WITH_NO_SECTION"));
        }
        /// <inheritdoc />
        public VirtualFileSystemEntry Build(VirtualDirectory root, string hostOutputPath = null, string gameName = null, bool useCompression = false, bool useExtracted = false)
        {
            gameName = Game.Persona5.ToString();

            if (root == null)
            {
                throw new ArgumentNullException(nameof(root));
            }

            //Get game config
            var config = ConfigStore.Get <Persona5GameConfig>() ?? throw new InvalidOperationException("Game config is missing.");

            Log.Builder.Info("Building Persona 5 Mod");
            Log.Builder.Info("Processing mod files");

            var modFilesDirectory = new VirtualDirectory(null, "mod");

            foreach (var entry in root)
            {
                if (entry.EntryType == VirtualFileSystemEntryType.Directory)
                {
                    var directory = ( VirtualDirectory )entry;
                    var name      = directory.Name.ToLowerInvariant();

                    switch (name)
                    {
                    case "mod":
                    case "cache":
                    case "data":
                    case "ps3":
                    case "ps3sndjp":
                    case "patch1ps3":
                    case "patch3ps3":
                    case "ps4":
                    case "ps4sndjp":
                    {
                        // Move files in 'cpk' directory to 'mod' directory
                        LogModFilesInDirectory(directory);

                        foreach (var modFileEntry in directory)
                        {
                            modFileEntry.CopyTo(modFilesDirectory);
                        }
                    }
                    break;

                    default:
                        // Move directory to 'mod' directory
                        Log.Builder.Trace($"Adding directory {entry.FullName} to mod.cpk");
                        entry.CopyTo(modFilesDirectory);
                        break;
                    }
                }
                else
                {
                    // Move file to 'mod' directory
                    Log.Builder.Trace($"Adding file {entry.FullName} to mod.cpk");
                    entry.CopyTo(modFilesDirectory);
                }
            }

            useCompression = config.Compression == "true";

            // Build mod cpk
            Log.Builder.Info("Building mod.cpk");
            var cpkModCompiler = new CpkModBuilder();
            var cpkFilePath    = hostOutputPath != null?Path.Combine(hostOutputPath, "mod.cpk") : null;

            var cpkFile = cpkModCompiler.Build(modFilesDirectory, cpkFilePath, gameName, useCompression);

            Log.Builder.Info("Done!");

            return(cpkFile);
        }