示例#1
0
        public VirtualFileSystemEntry Build(VirtualDirectory root, string hostOutputPath = null, string gameName = null, bool useCompression = false, bool useExtracted = false)
        {
            if (hostOutputPath == null)
            {
                // We need a path, so generate one.
                hostOutputPath = Path.Combine(Path.GetTempPath(), "Persona34IsoModBuilderTemp_" + Path.GetRandomFileName() + ".iso");
            }
            else if (Directory.Exists(hostOutputPath))
            {
                // Add file name if the path is a directory
                hostOutputPath = Path.Combine(hostOutputPath, "Amicitia.iso");
            }

            // Build mod files
            var fileModBuilder = CreateFileModBuilder();
            var tempDirectory  = Path.Combine(Path.GetTempPath(), "Persona34IsoModBuilderTemp_" + Path.GetRandomFileName());

            Directory.CreateDirectory(tempDirectory);
            var modFilesDirectory = (VirtualDirectory)fileModBuilder.Build(root, tempDirectory);

            var config = GetConfig();

            if (!config.DvdRootOrIsoPath.EndsWith(".iso"))
            {
                throw new NotImplementedException("This can only be done with an ISO source right now!");
            }

            // Modify & save new ISO
            Log.Builder.Info($"Modifying & saving ISO to {hostOutputPath} (this will take a while)");
            if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux))
            {
                Log.Builder.Info("Process will take longer as WINE must translate paths, please be patient.");
            }

            UltraISOUtility.ModifyIso(config.DvdRootOrIsoPath, hostOutputPath, modFilesDirectory.Select(x => x.HostPath));

            // Delete temp directory
            Directory.Delete(tempDirectory, true);

            // We're done
            return(VirtualFile.FromHostFile(hostOutputPath));
        }
        /// <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);
        }
示例#3
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);
        }
示例#4
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);
            }
        }
示例#5
0
        /// <summary>
        /// Build a PS2 bootable iso from the files in the root directory.
        /// If output path is specified, it is expected to be a path to the output ISO.
        /// Otherwise, if present, the root's name will be used as the base name for the ISO output.
        /// Requires SYSTEM.CNF and an executable file to be present in the root's file structure.
        /// </summary>
        /// <param name="root"></param>
        /// <param name="hostOutputPath"></param>
        /// <returns>PS2 bootable ISO file.</returns>
        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));
            }

            // Hack: get rid of root's name and restore it later
            // This is so we can use FullName with the builder without having to strip the root's name
            var rootName = root.Name;

            root.Name = string.Empty;

            // Find system.cnf first, as we need it to get the executable file path
            var systemCnfFile = root["SYSTEM.CNF"] as VirtualFile ?? throw new MissingFileException("SYSTEM.CNF is missing.");

            var executablePath = Ps2SystemConfig.GetExecutablePath(systemCnfFile.Open(), false, true) ??
                                 throw new MissingFileException(
                                           "Executable file path is not specified in SYSTEM.CNF; Unable to locate executable file.");

            var executableFile = root[executablePath] as VirtualFile ??
                                 throw new MissingFileException($"Executable file {executablePath} is missing.");

            var isoBuilder = new CDBuilder
            {
                UseJoliet = false,
                UpdateIsolinuxBootTable = false,
                VolumeIdentifier        = "AMICITIA"
            };

            // system.cnf first
            isoBuilder.AddFile(systemCnfFile.Name, systemCnfFile);

            // executable second
            isoBuilder.AddFile(executablePath, executableFile);

            // And then the rest
            AddToIsoBuilderRecursively(isoBuilder, root, executablePath);

            // HACK: Restore root name
            root.Name = rootName;

            if (hostOutputPath != null)
            {
                isoBuilder.Build(hostOutputPath);
                return(VirtualFile.FromHostFile(hostOutputPath));
            }
            else
            {
                string isoName;
                if (!string.IsNullOrWhiteSpace(root.Name))
                {
                    isoName = root.Name + ".iso";
                }
                else
                {
                    isoName = "PS2DVD.iso";
                }

                var stream = isoBuilder.Build();
                return(new VirtualFile(null, stream, isoName));
            }
        }