예제 #1
0
        private IList <Argument> ParseArguments(BinaryReaderX br, Xq32Header header)
        {
            var argumentStream = Decompress(br.BaseStream, header.table3Offset << 2);
            var arguments      = new BinaryReaderX(argumentStream).ReadMultiple <Xq32Argument>(header.table3EntryCount);

            return(arguments.Select(x => new Argument(x.type, x.value)).ToArray());
        }
예제 #2
0
        private IList <Function> ParseFunctions(BinaryReaderX br, Xq32Header header, IList <Jump> jumps, IList <Instruction> instructions)
        {
            var functionStream = Decompress(br.BaseStream, header.table0Offset << 2);
            var functions      = new BinaryReaderX(functionStream).ReadMultiple <Xq32Function>(header.table0EntryCount);

            var result = new List <Function>();

            foreach (var function in functions.OrderBy(x => x.instructionOffset))
            {
                var functionName         = _stringReader.Read(function.nameOffset);
                var functionInstructions = instructions
                                           .Skip(function.instructionOffset)
                                           .Take(function.instructionEndOffset - function.instructionOffset)
                                           .ToArray();

                var functionJumps = jumps
                                    .Skip(function.jumpOffset)
                                    .Take(function.jumpCount)
                                    .ToArray();

                var functionUnknowns = new int[] { function.unk1, function.unk2 };

                result.Add(new Function(functionName, function.parameterCount, functionJumps, functionInstructions, functionUnknowns));
            }

            return(result);
        }
예제 #3
0
        public override void Compile(Stream input, Stream output)
        {
            var stringStream = new MemoryStream();
            var stringWriter = new Xq32StringWriter(stringStream);

            var content = new StreamReader(input).ReadToEnd();

            var unkRegex = new Regex("^{(\\d+)}");

            if (!unkRegex.IsMatch(content))
            {
                throw new InvalidOperationException("Unknown header value is not prefixed to the script.");
            }

            var headerUnk    = short.Parse(unkRegex.Match(content).Groups[1].Value);
            var functions    = Function.ParseMultiple(string.Join(Environment.NewLine, content.Split(Environment.NewLine).Skip(1)), stringWriter);
            var jumps        = functions.SelectMany(x => x.Jumps.OrderBy(y => stringWriter.GetHash(y.Label))).ToArray();
            var instructions = functions.SelectMany(x => x.Instructions).ToArray();
            var arguments    = functions.SelectMany(x => x.Instructions.SelectMany(y => y.Arguments)).ToArray();

            var functionStream    = WriteFunctions(functions, jumps, instructions, stringWriter);
            var jumpStream        = WriteJumps(jumps, functions, instructions, stringWriter);
            var instructionStream = WriteInstructions(instructions);
            var argumentStream    = WriteArguments(arguments);

            var header = new Xq32Header
            {
                table0EntryCount = (short)functions.Count,
                table1EntryCount = (short)jumps.Length,
                table2EntryCount = (short)instructions.Length,
                table3EntryCount = (short)arguments.Length,
                unk3             = headerUnk
            };

            output.Position = header.table0Offset << 2;
            Compress(functionStream).CopyTo(output);

            header.table1Offset = (short)((output.Position + 3) >> 2);
            output.Position     = header.table1Offset << 2;
            Compress(jumpStream).CopyTo(output);

            header.table2Offset = (short)((output.Position + 3) >> 2);
            output.Position     = header.table2Offset << 2;
            Compress(instructionStream).CopyTo(output);

            header.table3Offset = (short)((output.Position + 3) >> 2);
            output.Position     = header.table3Offset << 2;
            Compress(argumentStream).CopyTo(output);

            header.table4Offset = (short)((output.Position + 3) >> 2);
            output.Position     = header.table4Offset << 2;
            Compress(stringStream).CopyTo(output);

            output.Position = 0;
            using var bw    = new BinaryWriterX(output, true);
            bw.WriteType(header);
        }
예제 #4
0
        private IList <Jump> ParseJumps(BinaryReaderX br, Xq32Header header, IList <Instruction> instructions)
        {
            var jumpStream = Decompress(br.BaseStream, header.table1Offset << 2);
            var jumps      = new BinaryReaderX(jumpStream).ReadMultiple <Xq32Jump>(header.table1EntryCount);

            var result = new List <Jump>();

            foreach (var jump in jumps)
            {
                var jumpInstruction = jump.instructionIndex < instructions.Count ? instructions[jump.instructionIndex] : null;
                result.Add(new Jump(_stringReader.Read(jump.nameOffset), jumpInstruction));
            }

            return(result);
        }
예제 #5
0
        private IList <Instruction> ParseInstructions(BinaryReaderX br, Xq32Header header, IList <Argument> arguments)
        {
            var instructionStream = Decompress(br.BaseStream, header.table2Offset << 2);
            var instructions      = new BinaryReaderX(instructionStream).ReadMultiple <Xq32Instruction>(header.table2EntryCount);

            var result = new List <Instruction>();

            foreach (var instruction in instructions)
            {
                var instructionArguments = arguments
                                           .Skip(instruction.argOffset)
                                           .Take(instruction.argCount)
                                           .ToArray();

                result.Add(new Instruction(instruction.subType, instructionArguments, instruction.returnParameter));
            }

            return(result);
        }
예제 #6
0
        private IStringReader CreateStringReader(BinaryReaderX br, Xq32Header header)
        {
            var stringStream = Decompress(br.BaseStream, header.table4Offset << 2);

            return(new StringReader(stringStream));
        }