Ejemplo n.º 1
0
        /// <summary>
        /// Takes a file and breaks it down into IElements then returns it in a structured format
        /// </summary>
        /// <param name="br">The file to process</param>
        /// <param name="fileName">The name of the file to be processed (used only for displaying error messages)</param>
        /// <param name="jumpLabelManager">The jump label manager to use when processing file (pass null to disable jump tracking)</param>
        /// <returns>A class containing the processed file data</returns>
        public KCFile ParseFile(BinaryReader br, string fileName, JumpLabelManager jumpLabelManager)
        {
            KCFile workingFile = new KCFile();
            List <IInstruction> instructions = new List <IInstruction>();

            workingFile.footer = ReadFooter(br);
            workingFile.header = ReadHeader(br);

            StCpNumber fileNumber = (workingFile.header as StCp_Header).GetFileNumber(); // more than anything else this basically cements that this function reads only StCp files which should really be clarified at some point

            long streamEnd = br.BaseStream.Length - ElementHelper.GetElementSize(workingFile.footer);

            while (br.BaseStream.Position != streamEnd) // will need to check this for accuracy as it has been unreliable in some cases in the past
            {
                Opcode opcode = FileIOHelper.ReadOpcode(br);
                br.BaseStream.Position -= OpcodeInfo.OPCODE_SIZE; // set the position back by 2, the size of the opcodes, as the instruction parsers will expect to given a position starting with an opcode

                if (opcode == Opcode.INVALID)
                {
                    string errorMessage = string.Format("There was an unexpected opcode when reading file {0} at position {1} after reading {2} instructions", fileName, br.BaseStream.Position.ToString("X"), instructions.Count.ToString());
                    MessageBox.Show(errorMessage, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Environment.Exit(1);
                }

                if (jumpLabelManager != null) // we want to support running this without a jumplabelmanager just in case
                {
                    long currentAddress = br.BaseStream.Position;

                    if (jumpLabelManager.IsJumpTarget(fileNumber, (int)currentAddress))
                    {
                        var virtualLabel = jumpLabelManager.CreateVirtualLabel(fileNumber, (int)currentAddress);
                        instructions.Add(virtualLabel);
                    }
                }

                IInstruction newInstruction;
                Type         instructionParserType = OpcodeInfo.GetInstructionParserType(opcode);

                if (instructionParserType == typeof(InstructionBox))
                {
                    newInstruction = ElementHelper.MakeInstructionBox(opcode);
                    newInstruction.Read(br);
                }
                else
                {
                    newInstruction = (IInstruction)Activator.CreateInstance(instructionParserType);
                    newInstruction.Read(br);
                }

                instructions.Add(newInstruction);
            }

            //string finishMessage = string.Format("Parsed file {0} with {1} instructions", fileName, instructions.Count.ToString());
            //MessageBox.Show(finishMessage);

            workingFile.instructions = instructions;
            return(workingFile);
        }
Ejemplo n.º 2
0
        // under ideal circumstances a large portion of DumpStrings and LoadStrings code would be seperated out into ProcessStrings - but that's more of goal for future refactoring
        // yeah this is just getting done to provide a quick beta and will have to be refactored later
        public static void LoadStrings(object sender, EventArgs e)
        {
            BackgroundWorker worker    = null;
            DoWorkEventArgs  eventArgs = null;

            if (sender is BackgroundWorker)
            {
                worker    = sender as BackgroundWorker;
                eventArgs = e as DoWorkEventArgs;
            }
            else
            {
                worker = null;
            }

            string dialogueFileDir = Path.Combine(rootDir, unpackedGameFilesDir, @"PSP_GAME\USRDIR\St000"); // at the moment there's only one directory with files that have strings and only files with strings in that directory, so this is a quick way of processing. if any non-string files are added to this directory or any string files are found in other directories more advanced filtering will be necessary.

            string[]         fileList          = Directory.GetFiles(dialogueFileDir);
            StringCollection translatedStrings = LoadCSVStrings(Path.Combine(rootDir, editableGameFiesDir, @"PSP_GAME\USRDIR\St000"));

            if (!Directory.Exists(dialogueFileDir))
            {
                string errorMessage = string.Format("Could not find directory {0}.", dialogueFileDir);
                MessageBox.Show(errorMessage, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                eventArgs.Result = false;
            }

            var nameCollection = new StringCollection();
            Dictionary <string, StringCollection> stringFiles = new Dictionary <string, StringCollection>();

            FontHandler fontHandler = new FontHandler(); // we will sneak fixing the font size in here

            fontHandler.ChangeSpaceSize(FontHandler.DEFAULT_SPACE_SIZE);

            var textWrapper = new DynamicTextBoxes();
            var jumpTable   = new KPT.Parser.Jump_Label_Manager.JumpTableInterface();

            jumpTable.LoadJumpTable(); // changing the size of instructions with new dialogue will mess up file offsets so we will need to load the jump table and make sure it's updated as we go
            var jumpLabelManager = new JumpLabelManager(jumpTable.GetJumpTableEntries());

            int counter = 0;

            foreach (string file in fileList)
            {
                counter++;

                if (worker != null)
                {
                    double progress = ((double)counter / (double)fileList.Length) * 100;

                    worker.ReportProgress((int)progress);

                    Thread.Sleep(3); // these are aeshetic sleeps, there to make the progress bar grow steadily so the user doesn't think something might have went wrong
                }

                if (worker != null)
                {
                    if (worker.WorkerSupportsCancellation && worker.CancellationPending)
                    {
                        eventArgs.Result = false;
                        MessageBox.Show("Load strings cancelled");
                        return;
                    }
                }

                string fileName    = Path.Combine(dialogueFileDir, file);
                var    fileStrings = new StringCollection(GetSubPath(file, Path.Combine(rootDir, unpackedGameFilesDir)));

                FileStream   fs = new FileStream(fileName, FileMode.Open);
                BinaryReader br = new BinaryReader(fs);

                var parser     = new FileParser();
                var parsedFile = parser.ParseFile(br, Path.GetFileName(file), jumpLabelManager);

                foreach (IElement element in parsedFile.instructions)
                {
                    if (element is IHasName)
                    {
                        var name = (element as IHasName).GetName();
                        nameCollection.AddString(name, name); // using name as ID and value since we want a single entry for each name - saves messing with IDs
                    }
                    if (element is IHasStrings)
                    {
                        var temp = element as IHasStrings;
                        temp.AddStrings(fileStrings);
                        temp.GetStrings(translatedStrings);
                    }
                }

                textWrapper.CheckTextboxes(parsedFile);

                br.Close();
                fs.Close();

                if (fileStrings.NumberOfKeys > 0)
                {
                    string outputFileName = Path.Combine(rootDir, reassembledGameFilesDir, GetSubPath(file, Path.Combine(rootDir, unpackedGameFilesDir)));
                    parser.WriteFile(parsedFile, outputFileName);
                }
            }

            jumpTable.SaveJumpTable();

            Thread.Sleep(1000); // this is another aesthetic sleep, ensuring the the progress bar does not disappear before the user can see it completing
            eventArgs.Result = true;
        }