예제 #1
0
        /// <summary>
        /// This method will rip the image to the given directory
        /// </summary>
        /// <param name="destinationFolder"></param>
        public void Rip(string destinationFolder)
        {
            //RipNew(destinationFolder);
            RippedDirectory = destinationFolder;
            RippedCatPath   = Path.GetDirectoryName(ImageBinPath) + "\\" + Path.GetFileNameWithoutExtension(ImageBinPath) + ".cat";
            if (Path.GetExtension(ImageBinPath).ToLower() != ".bin")
            {
                return;
            }
            if (!File.Exists(ImageBinPath))
            {
                return;
            }

            ProcessStartInfo info = new ProcessStartInfo
            {
                FileName  = PSXRipExecutable,
                Arguments = String.Format("\"{0}\" \"{1}\"", ImageBinPath, RippedDirectory)
            };
            Process psxrip = new Process {
                StartInfo = info
            };

            psxrip.Start();
            psxrip.WaitForExit();

            FileDictionary = new FileDictionary();
            LoadExecutable(RippedDirectory + "\\SLPS_016.90");
            InitPKNs();

            foreach (PKNFile pknFile in PKNFiles)
            {
                pknFile.Unpack();
            }
        }
예제 #2
0
        ///  <summary>
        ///  Reads the file indexes of the PSX executable
        ///  </summary>
        ///  <param name="executablePath">Path of the PSX executable</param>
        ///  <param name="offset">Offset in the PSX executable where the file listing starts in bytes</param>
        ///  <param name="length">Length of the file listing in bytes</param>
        public void LoadExecutable(string executablePath)
        {
            RippedExecutablePath  = executablePath;
            FileDictionary.Offset = DictionaryOffset;
            FileDictionary.Length = DictionaryLength;

            byte[] listing = new byte[DictionaryLength];
            using (BinaryReader reader = new BinaryReader(new FileStream(RippedExecutablePath, FileMode.Open)))
            {
                reader.BaseStream.Seek(DictionaryOffset, SeekOrigin.Begin);
                reader.Read(listing, 0, DictionaryLength);
            }

            for (int i = 0; i < DictionaryLength; i += 0x24)
            {
                byte[] entryData = new byte[0x24];
                Array.Copy(listing, i, entryData, 0, 0x24);
                FileDictionary.Files.Add(new FileDictionaryFile(entryData));
            }
            FileDictionary.SortFiles();
        }
예제 #3
0
        /// <summary>
        /// Saves the PSX executable with modified indexes to match the current game files
        /// </summary>
        public void SaveExecutable()
        {
            if (FileDictionary == null)
            {
                return;
            }

            uint   counter    = 24;
            string lastFolder = "BG";

            foreach (FileDictionaryFile file in FileDictionary.Files)
            {
                if (lastFolder != file.Folder)
                {
                    counter++;
                }
                lastFolder = file.Folder;

                if (file.IsInsidePkn)
                {
                    string   fileName = RippedDirectory + "\\" + file.Folder + "\\" + file.FullPath;
                    FileInfo fileInfo = new FileInfo(fileName);

                    file.Offset = counter;
                    file.Length = (uint)fileInfo.Length / 2048;
                    uint modLength = (uint)fileInfo.Length % 2048;
                    if (modLength != 0)
                    {
                        file.Length++;
                    }
                    if (!IgnoreMemoryOptimization)
                    {
                        file.SectorOverhead = DisableMemoryOptimization ? 0 : modLength / 4;
                    }

                    counter += file.Length;
                }
                else
                {
                    string   fileName = RippedDirectory + file.FullPath;
                    FileInfo fileInfo = new FileInfo(fileName);
                    if (fileInfo.Length % 2336 != 0)
                    {
                        if (MessageBox.Show(String.Format("The file \"{0}\" does not have the correct size.\n Do you want to add zero padding?", fileInfo.FullName), "Incorrect Size!", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes)
                        {
                            long rest = 2336 - fileInfo.Length % 2336;
                            using (BinaryWriter writer = new BinaryWriter(new FileStream(fileName, FileMode.Append, FileAccess.Write)))
                            {
                                for (int i = 0; i < rest; i++)
                                {
                                    writer.Write('\0');
                                }
                            }
                            fileInfo = new FileInfo(fileName);
                        }
                        else
                        {
                            MessageBox.Show("The build process was cancelled!", "Build process cancelled!");
                            return;
                        }
                        //MessageBox.Show(String.Format("The file \"{0}\" does not have the correct size.", fileInfo.FullName));
                        //return;
                    }

                    file.Offset = counter;
                    file.Length = (uint)fileInfo.Length / 2336;
                    counter    += file.Length;
                }
            }

            FileDictionary.SortFiles();

            using (BinaryWriter writer = new BinaryWriter(new FileStream(RippedExecutablePath, FileMode.Open)))
            {
                writer.BaseStream.Seek(FileDictionary.Offset, SeekOrigin.Begin);
                foreach (FileDictionaryFile file in FileDictionary.Files)
                {
                    writer.Write(file.GetBytes());
                }

                int CodeCaveSegment = 585512;

                //Apply Assembler patches (write as single hex because of endianess)
                //Patch 01 - Allow sjis 2+1 more char in GMAP "school" string
                writer.BaseStream.Seek(0x03D5CB, SeekOrigin.Begin);
                writer.Write((byte)0x24);
                writer.Write((byte)0x03);
                writer.BaseStream.Seek(0x03D5D0, SeekOrigin.Begin);
                writer.Write((byte)0xA8);
                writer.Write((byte)0x03);

                //Patch 02 - Mod save string to way longer (Speichern)
                //Move pointer a code cave ("old seq data" printf strings 1/2)
                writer.BaseStream.Seek(0x0375F8, SeekOrigin.Begin);
                writer.Write(new byte[] { 0x01, 0x80, 0x04, 0x3C, 0xC4, 0x69, 0x84, 0x24 });
                //nop out the lib printf part
                writer.BaseStream.Seek(0x6BCB4, SeekOrigin.Begin);
                writer.Write(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });

                //Patch 03 - Move pointer (gmap wohnheim) to a code cave ("old seq data" printf string 2/2)
                writer.BaseStream.Seek(0x03D630, SeekOrigin.Begin);
                writer.Write(new byte[] { 0x01, 0x80, 0x04, 0x3C, 0xD0, 0x69, 0x84, 0x24 });

                //Patch 03.1
                writer.BaseStream.Seek(685204, SeekOrigin.Begin);
                writer.Write(new byte[] {
                    0x44, 0x45, 0x52, 0x50, 0x4c, 0x41, 0x59, 0x45,
                    0x52, 0x20, 0x57, 0x41, 0x53, 0x20, 0x48, 0x45,
                    0x52, 0x45
                });

                //Patch 04 - Resize the GMAP Draw area for text (0x70 is the hardware limit for width)
                //We increase the draw rectangle with for one more char
                writer.BaseStream.Seek(0xF944, SeekOrigin.Begin);
                writer.Write((byte)0x30); //0x40->0x30
                //We overwrite (8001F288 move $a3, $zero) to change the width register back for the other rectangles
                //Should not crash or cause the game to be unstable, but never say never (should be tested on real hardware later)
                //alternative for this is the usage of the t2 register (but value is over 0x70, so not tested)
                writer.BaseStream.Seek(0xF988, SeekOrigin.Begin);
                writer.Write(new byte[] { 0x40, 0x00, 0x14, 0x24 }); //0x30->0x40

                //Patch 05 - Increase the chars in buffer for GMAP draw area (CPU)
                writer.BaseStream.Seek(0x03D638, SeekOrigin.Begin);
                writer.Write((byte)0x05); //0x03->0x05

                byte libsegptr = 0x28;
                //dehnen    - 584152 - orginal hex: A4 6C 0B 80
                //wasser    - 584156 - orginal hex: C4 3F 01 80
                //stein     - 584188 - orginal hex: 3C 3F 01 80
                //aufricht  - 584208 - orginal hex: 9C 6C 0B 80
                //binden    - 584212 - orginal hex: 94 6C 0B 80

                //Patch 06.1 - Move minigame label pointer (dehnen) to a code cave (sony lib header text)
                writer.BaseStream.Seek(584152, SeekOrigin.Begin);
                writer.Write(new byte[] { libsegptr, 0xE7, 0x09, 0x80 });
                libsegptr += 12;

                //Patch 06.2 - Move minigame label pointer (wasser) to a code cave (sony lib header text)
                writer.BaseStream.Seek(584156, SeekOrigin.Begin);
                writer.Write(new byte[] { libsegptr, 0xE7, 0x09, 0x80 });
                libsegptr += 22;

                //Patch 06.3 - Move minigame label pointer (stein) to a code cave (sony lib header text)
                writer.BaseStream.Seek(584188, SeekOrigin.Begin);
                writer.Write(new byte[] { libsegptr, 0xE7, 0x09, 0x80 });
                libsegptr += 22;

                //Patch 06.4 - Move minigame label pointer (aufricht) to a code cave (sony lib header text)
                writer.BaseStream.Seek(584208, SeekOrigin.Begin);
                writer.Write(new byte[] { libsegptr, 0xE7, 0x09, 0x80 });
                libsegptr += 12;

                //Patch 06.5 - Move minigame label pointer (aufricht) to a code cave (sony lib header text)
                writer.BaseStream.Seek(584212, SeekOrigin.Begin);
                writer.Write(new byte[] { libsegptr, 0xE7, 0x09, 0x80 });
                libsegptr += 16;

                //----------

                //Patch 0x - dialog color for minigame 3 (totally useless ;)
                //writer.BaseStream.Seek(0x057AFC, SeekOrigin.Begin);
                //writer.Write((byte)0xA); //Blue 0x02, Red 0x04, Yellow 0x06
            }
        }