} = new byte[16];                                        // more high entropy data

        public void Serialize(UndertaleWriter writer)
        {
            writer.Write(DisableDebugger ? (byte)1 : (byte)0);
            writer.Write(BytecodeVersion);
            writer.Write(Unknown);
            writer.WriteUndertaleString(Filename);
            writer.WriteUndertaleString(Config);
            writer.Write(LastObj);
            writer.Write(LastTile);
            writer.Write(GameID);
            writer.Write(DirectPlayGuid.ToByteArray());
            writer.WriteUndertaleString(Name);
            writer.Write(Major);
            writer.Write(Minor);
            writer.Write(Release);
            writer.Write(Build);
            writer.Write(DefaultWindowWidth);
            writer.Write(DefaultWindowHeight);
            writer.Write((uint)Info);
            if (LicenseMD5.Length != 16)
            {
                throw new IOException("LicenseMD5 has invalid length");
            }
            writer.Write(LicenseMD5);
            writer.Write(LicenseCRC32);
            writer.Write(Timestamp);
            writer.WriteUndertaleString(DisplayName);

            // Should always be zero.
            writer.Write(ActiveTargets);

            // Very weird value. Decides if Runner should initialize certain subsystems.
            writer.Write((ulong)FunctionClassifications);

            writer.Write(SteamAppID);
            if (BytecodeVersion >= 14)
            {
                writer.Write(DebuggerPort);
            }
            writer.WriteUndertaleObject(RoomOrder);
            if (Major >= 2)
            {
                // Write random UID
                Random random      = new Random((int)(Timestamp & 4294967295L));
                long   firstRandom = (long)random.Next() << 32 | (long)random.Next();
                long   infoNumber  = (long)(Timestamp - 1000);
                ulong  temp        = (ulong)infoNumber;
                temp = ((temp << 56 & 18374686479671623680UL) | (temp >> 8 & 71776119061217280UL) |
                        (temp << 32 & 280375465082880UL) | (temp >> 16 & 1095216660480UL) | (temp << 8 & 4278190080UL) |
                        (temp >> 24 & 16711680UL) | (temp >> 16 & 65280UL) | (temp >> 32 & 255UL));
                infoNumber  = (long)temp;
                infoNumber ^= firstRandom;
                infoNumber  = ~infoNumber;
                infoNumber ^= ((long)GameID << 32 | (long)GameID);
                infoNumber ^= ((long)(DefaultWindowWidth + (int)Info) << 48 |
                               (long)(DefaultWindowHeight + (int)Info) << 32 |
                               (long)(DefaultWindowHeight + (int)Info) << 16 |
                               (long)(DefaultWindowWidth + (int)Info));
                infoNumber ^= BytecodeVersion;
                int infoLocation = Math.Abs((int)((int)(Timestamp & 65535L) / 7 + (GameID - DefaultWindowWidth) + RoomOrder.Count)) % 4;
                GMS2RandomUID.Clear();
                writer.Write(firstRandom);
                GMS2RandomUID.Add(firstRandom);
                for (int i = 0; i < 4; i++)
                {
                    if (i == infoLocation)
                    {
                        writer.Write(infoNumber);
                        GMS2RandomUID.Add(infoNumber);
                    }
                    else
                    {
                        int first  = random.Next();
                        int second = random.Next();
                        writer.Write(first);
                        writer.Write(second);
                        GMS2RandomUID.Add(((long)first << 32) | (long)second);
                    }
                }
                writer.Write(GMS2FPS);
                if (GMS2GameGUID.Length != 16)
                {
                    throw new IOException("GMS2GameGUID has invalid length");
                }
                writer.Write(GMS2AllowStatistics);
                writer.Write(GMS2GameGUID);
            }
        }
 public void Serialize(UndertaleWriter writer)
 {
     writer.Write(ID);
     Tags.Serialize(writer);
 }
Beispiel #3
0
 internal override void SerializeChunk(UndertaleWriter writer)
 {
     List.Serialize(writer);
 }
Beispiel #4
0
 internal override void SerializeChunk(UndertaleWriter writer)
 {
     base.SerializeChunk(writer);
 }
        public void Serialize(UndertaleWriter writer)
        {
            switch (GetInstructionType(Kind))
            {
            case InstructionType.SingleTypeInstruction:
            case InstructionType.DoubleTypeInstruction:
            case InstructionType.ComparisonInstruction:
            {
                writer.Write(DupExtra);
                writer.Write((byte)ComparisonKind);
                byte TypePair = (byte)((byte)Type2 << 4 | (byte)Type1);
                writer.Write(TypePair);
                writer.Write((byte)Kind);
            }
            break;

            case InstructionType.GotoInstruction:
            {
                // TODO: see unserialize
                // TODO: why the hell is there exactly ONE number that was NOT encoded in a weird way? If you just rewrite the file with the 'fix' it differs one one byte
                uint JumpOffsetFixed = (uint)JumpOffset;
                JumpOffsetFixed &= ~0xFF800000;
                if (JumpOffsetIsWeird)
                {
                    JumpOffsetFixed |= 0x00800000;
                }
                writer.WriteInt24((int)JumpOffsetFixed);

                writer.Write((byte)Kind);
            }
            break;

            case InstructionType.PopInstruction:
            {
                writer.Write((short)TypeInst);
                byte TypePair = (byte)((byte)Type2 << 4 | (byte)Type1);
                writer.Write(TypePair);
                writer.Write((byte)Kind);
                writer.WriteUndertaleObject(Destination);
            }
            break;

            case InstructionType.PushInstruction:
            {
                if (Type1 == DataType.Int16)
                {
                    Debug.Assert(Value.GetType() == typeof(short));
                    writer.Write((short)Value);
                }
                else if (Type1 == DataType.Variable)
                {
                    writer.Write((short)TypeInst);
                }
                else
                {
                    writer.Write((short)0);
                }
                writer.Write((byte)Type1);
                writer.Write((byte)Kind);
                switch (Type1)
                {
                case DataType.Double:
                    Debug.Assert(Value.GetType() == typeof(double));
                    writer.Write((double)Value);
                    break;

                case DataType.Float:
                    Debug.Assert(Value.GetType() == typeof(float));
                    writer.Write((float)Value);
                    break;

                case DataType.Int32:
                    Debug.Assert(Value.GetType() == typeof(int));
                    writer.Write((int)Value);
                    break;

                case DataType.Int64:
                    Debug.Assert(Value.GetType() == typeof(long));
                    writer.Write((long)Value);
                    break;

                case DataType.Boolean:
                    Debug.Assert(Value.GetType() == typeof(bool));
                    writer.Write((bool)Value ? 1 : 0);
                    break;

                case DataType.Variable:
                    Debug.Assert(Value.GetType() == typeof(Reference <UndertaleVariable>));
                    writer.WriteUndertaleObject((Reference <UndertaleVariable>)Value);
                    break;

                case DataType.String:
                    Debug.Assert(Value.GetType() == typeof(UndertaleResourceById <UndertaleString>));
                    UndertaleResourceById <UndertaleString> str = (UndertaleResourceById <UndertaleString>)Value;
                    writer.Write(str.Serialize(writer));
                    break;

                case DataType.Int16:
                    break;
                }
            }
            break;

            case InstructionType.CallInstruction:
            {
                writer.Write(ArgumentsCount);
                writer.Write((byte)Type1);
                writer.Write((byte)Kind);
                writer.WriteUndertaleObject(Function);
            }
            break;

            case InstructionType.BreakInstruction:
            {
                Debug.Assert(Value.GetType() == typeof(short));
                writer.Write((short)Value);
                writer.Write((byte)Type1);
                writer.Write((byte)Kind);
            }
            break;

            default:
                throw new IOException("Unknown opcode " + Kind.ToString().ToUpper());
            }
        }
Beispiel #6
0
 internal override void SerializeChunk(UndertaleWriter writer)
 {
     writer.WriteUndertaleObject(Object);
 }
Beispiel #7
0
 public void Serialize(UndertaleWriter writer)
 {
     writer.Write((uint)Type);
 }
 public void Serialize(UndertaleWriter writer)
 {
     throw new NotImplementedException();
 }
        private async Task SaveFile(string filename)
        {
            if (Data == null)
            {
                return; // TODO: lock save button
            }
            if (IsGMS2 == Visibility.Visible)
            {
                MessageBox.Show("This is not yet tested and may break. You have been warned.", "GMS2 game", MessageBoxButton.YesNo, MessageBoxImage.Warning);
            }

            LoaderDialog dialog = new LoaderDialog("Saving", "Saving, please wait...");

            dialog.Owner = this;
            FilePath     = filename;

            DebugDataMode debugMode = DebugDataMode.NoDebug;

            if (!Data.GeneralInfo.DisableDebugger) // TODO: I think the game itself can also use the .yydebug file on crash reports
            {
                DebugDataDialog debugDialog = new DebugDataDialog();
                debugDialog.Owner = this;
                debugDialog.ShowDialog();
                debugMode = debugDialog.Result;
                // TODO: Add an option to generate debug data for just selected scripts (to make running faster / make the full assembly not take forever to load)
            }
            Task t = Task.Run(() =>
            {
                try
                {
                    using (var stream = new FileStream(filename, FileMode.Create))
                    {
                        UndertaleIO.Write(stream, Data);
                    }

                    if (debugMode != DebugDataMode.NoDebug)
                    {
                        Debug.WriteLine("Generating debugger data...");
                        UndertaleDebugData debugData = DebugDataGenerator.GenerateDebugData(Data, debugMode);
                        using (FileStream stream = new FileStream(System.IO.Path.ChangeExtension(FilePath, ".yydebug"), FileMode.Create))
                        {
                            using (UndertaleWriter writer = new UndertaleWriter(stream))
                            {
                                debugData.FORM.Serialize(writer);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show("An error occured while trying to save:\n" + e.Message, "Save error", MessageBoxButton.OK, MessageBoxImage.Error);
                }

                Dispatcher.Invoke(() =>
                {
                    dialog.Hide();
                });
            });

            dialog.ShowDialog();
            await t;
        }
Beispiel #10
0
 public void Serialize(UndertaleWriter writer)
 {
     Serialize(writer, true);
 }
Beispiel #11
0
 internal override void SerializeChunk(UndertaleWriter writer)
 {
     Alignment = 8;
     base.SerializeChunk(writer);
 }
 public void Serialize(UndertaleWriter writer)
 {
     writer.Write(Unknown1);
     writer.Write(Unknown2);
     writer.Write(Unknown3);
 }
Beispiel #13
0
 /// <inheritdoc />
 public void Serialize(UndertaleWriter writer)
 {
     writer.Write(X);
     writer.Write(Y);
     writer.Write(Speed);
 }
 public override void Serialize(UndertaleWriter writer)
 {
     writer.Write(Value);
     base.Serialize(writer);
 }
 public void Serialize(UndertaleWriter writer)
 {
     writer.Write((uint)Data.Length);
     writer.Write(Data);
 }
        public void Serialize(UndertaleWriter writer)
        {
            switch (GetInstructionType(Kind))
            {
            case InstructionType.SingleTypeInstruction:
            case InstructionType.DoubleTypeInstruction:
            case InstructionType.ComparisonInstruction:
            {
                writer.Write(DupExtra);
                writer.Write((byte)ComparisonKind);
                byte TypePair = (byte)((byte)Type2 << 4 | (byte)Type1);
                writer.Write(TypePair);
                writer.Write((byte)Kind);
            }
            break;

            case InstructionType.GotoInstruction:
            {
                // See unserialize
                if (JumpOffsetPopenvExitMagic)
                {
                    writer.WriteInt24(0xF00000);
                }
                else
                {
                    uint JumpOffsetFixed = (uint)JumpOffset;
                    JumpOffsetFixed &= ~0xFF800000;
                    writer.WriteInt24((int)JumpOffsetFixed);
                }

                writer.Write((byte)Kind);
            }
            break;

            case InstructionType.PopInstruction:
            {
                if (Type1 == DataType.Int16)
                {
                    // Special scenario - the swap instruction
                    // TODO: Figure out the proper syntax, see #129
                    writer.Write(SwapExtra);
                    byte TypePair = (byte)((byte)Type2 << 4 | (byte)Type1);
                    writer.Write(TypePair);
                    writer.Write((byte)Kind);
                }
                else
                {
                    writer.Write((short)TypeInst);
                    byte TypePair = (byte)((byte)Type2 << 4 | (byte)Type1);
                    writer.Write(TypePair);
                    writer.Write((byte)Kind);
                    writer.WriteUndertaleObject(Destination);
                }
            }
            break;

            case InstructionType.PushInstruction:
            {
                if (Type1 == DataType.Int16)
                {
                    Debug.Assert(Value.GetType() == typeof(short));
                    writer.Write((short)Value);
                }
                else if (Type1 == DataType.Variable)
                {
                    writer.Write((short)TypeInst);
                }
                else
                {
                    writer.Write((short)0);
                }
                writer.Write((byte)Type1);
                writer.Write((byte)Kind);
                switch (Type1)
                {
                case DataType.Double:
                    Debug.Assert(Value.GetType() == typeof(double));
                    writer.Write((double)Value);
                    break;

                case DataType.Float:
                    Debug.Assert(Value.GetType() == typeof(float));
                    writer.Write((float)Value);
                    break;

                case DataType.Int32:
                    Debug.Assert(Value.GetType() == typeof(int));
                    writer.Write((int)Value);
                    break;

                case DataType.Int64:
                    Debug.Assert(Value.GetType() == typeof(long));
                    writer.Write((long)Value);
                    break;

                case DataType.Boolean:
                    Debug.Assert(Value.GetType() == typeof(bool));
                    writer.Write((bool)Value ? 1 : 0);
                    break;

                case DataType.Variable:
                    Debug.Assert(Value.GetType() == typeof(Reference <UndertaleVariable>));
                    writer.WriteUndertaleObject((Reference <UndertaleVariable>)Value);
                    break;

                case DataType.String:
                    Debug.Assert(Value.GetType() == typeof(UndertaleResourceById <UndertaleString, UndertaleChunkSTRG>));
                    writer.WriteUndertaleObject((UndertaleResourceById <UndertaleString, UndertaleChunkSTRG>)Value);
                    break;

                case DataType.Int16:
                    break;
                }
            }
            break;

            case InstructionType.CallInstruction:
            {
                writer.Write(ArgumentsCount);
                writer.Write((byte)Type1);
                writer.Write((byte)Kind);
                writer.WriteUndertaleObject(Function);
            }
            break;

            case InstructionType.BreakInstruction:
            {
                Debug.Assert(Value.GetType() == typeof(short));
                writer.Write((short)Value);
                writer.Write((byte)Type1);
                writer.Write((byte)Kind);
            }
            break;

            default:
                throw new IOException("Unknown opcode " + Kind.ToString().ToUpper());
            }
        }
 public void Serialize(UndertaleWriter writer)
 {
     Messages.Serialize(writer);
 }
 public void Serialize(UndertaleWriter writer)
 {
     NextOccurrenceOffset = 0xdead;
     writer.WriteInt24(NextOccurrenceOffset);
     writer.Write((byte)Type);
 }
            public void Serialize(UndertaleWriter writer)
            {
                writer.WriteUndertaleString(ModelName);
                writer.WriteUndertaleString(Name);
                writer.Write(BuiltinName);
                writer.Write(Traits);
                writer.Write(IsCreationTrack);

                writer.Write(Tags.Count);
                writer.Write(OwnedResources.Count);
                writer.Write(Tracks.Count);

                foreach (int i in Tags)
                {
                    writer.Write(i);
                }

                foreach (UndertaleResource res in OwnedResources)
                {
                    if (res is UndertaleAnimationCurve)
                    {
                        writer.WriteUndertaleString(GMAnimCurveString);
                        res.Serialize(writer);
                    }
                    else
                    {
                        throw new IOException("Expected an animation curve");
                    }
                }

                foreach (Track t in Tracks)
                {
                    writer.WriteUndertaleObject(t);
                }

                // Now, handle specific keyframe/etc. data
                switch (ModelName.Content)
                {
                case "GMAudioTrack":
                    writer.WriteUndertaleObject(Keyframes as AudioKeyframes);
                    break;

                case "GMInstanceTrack":
                    writer.WriteUndertaleObject(Keyframes as InstanceKeyframes);
                    break;

                case "GMGraphicTrack":
                    writer.WriteUndertaleObject(Keyframes as GraphicKeyframes);
                    break;

                case "GMSequenceTrack":
                    writer.WriteUndertaleObject(Keyframes as SequenceKeyframes);
                    break;

                case "GMSpriteFramesTrack":
                    writer.WriteUndertaleObject(Keyframes as SpriteFramesKeyframes);
                    break;

                case "GMAssetTrack":     // TODO?
                    throw new NotImplementedException("GMAssetTrack not implemented, report this");

                case "GMBoolTrack":
                    writer.WriteUndertaleObject(Keyframes as BoolKeyframes);
                    break;

                case "GMStringTrack":
                    writer.WriteUndertaleObject(Keyframes as StringKeyframes);
                    break;

                // TODO?
                //case "GMIntTrack":
                //  writer.WriteUndertaleObject(Keyframes as IntKeyframes);
                //  break;
                case "GMRealTrack":
                    writer.WriteUndertaleObject(Keyframes as RealKeyframes);
                    break;
                }
            }
Beispiel #20
0
 public void Serialize(UndertaleWriter writer)
 {
     writer.WriteGMString(Content);
 }
 public virtual void Serialize(UndertaleWriter writer)
 {
     Resource.Serialize(writer);
 }
Beispiel #22
0
 internal abstract void SerializeChunk(UndertaleWriter writer);
 public override void Serialize(UndertaleWriter writer)
 {
     base.Serialize(writer);
     writer.Write((int)0);
     writer.Write(Mode);
 }
Beispiel #24
0
    public static void Main(string[] args)
    {
        UndertaleData data;

        Parser.Default.ParseArguments <Options>(args).WithParsed(opts =>
        {
            if (!new[] { 'P', 'D', 'C' }.Contains(opts.Mode))
            {
                Console.WriteLine("Invalid Patcher Mode: " + opts.Mode);
                return;
            }
            try
            {
                Process[] processes = Process.GetProcessesByName("MyRabbitsAreGone");
                if (processes.Length != 0)
                {
                    if (opts.CloseBeforeStarting)
                    {
                        Console.WriteLine("Closing all open instances of My Rabbits Are Gone");
                        foreach (var proc in processes)
                        {
                            proc.CloseMainWindow();
                        }
                    }
                    else
                    {
                        Console.WriteLine("Close My Rabbits Are Gone before continuing.");
                    }
                    while (processes.Length != 0)
                    {
                        Thread.Sleep(1000);
                        processes = Process.GetProcessesByName("MyRabbitsAreGone");
                    }

                    Console.WriteLine("Continuing!");
                }

                if (Path.GetFileName(opts.FileLocation) != "data.win")
                {
                    throw new Exception("File name is not data.win!");
                }
                if (File.Exists(opts.FileLocation + ".bak"))
                {
                    Console.WriteLine("Found a backup, overwriting current data.win with it.");
                    File.Delete(opts.FileLocation);
                    opts.FileLocation += ".bak";
                }
                else
                {
                    Console.WriteLine("Backup not found, doing that now.");
                    File.Copy(opts.FileLocation, opts.FileLocation + ".bak");
                }
                if (!File.Exists(opts.FileLocation))
                {
                    throw new Exception("File does not exist!");
                }

                var read = new UndertaleReader(File.OpenRead(opts.FileLocation));
                data     = read.ReadUndertaleData();
                read.Close();
                var md5       = MD5.Create();
                Engine engine = new Engine(cfg =>
                                           cfg.AllowClr(
                                               typeof(UndertaleData).Assembly,
                                               typeof(UndertaleGameObject).Assembly,
                                               typeof(DiffUtil).Assembly).DebugMode());
                engine = engine.SetValue("RoomGameObject",
                                         TypeReference.CreateTypeReference(engine, typeof(UndertaleRoom.GameObject))).SetValue(
                    "EventAction",
                    TypeReference.CreateTypeReference(engine, typeof(UndertaleGameObject.EventAction))).SetValue(
                    "UEvent", TypeReference.CreateTypeReference(engine, typeof(UndertaleGameObject.Event)));
                engine = engine.SetValue("log", new Action <object>(Console.WriteLine))
                         .SetValue("data", data)
                         .SetValue("emmdeefive", new Func <string, string>((s) =>
                {
                    var hash         = md5.ComputeHash(Encoding.ASCII.GetBytes(s));
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < hash.Length; i++)
                    {
                        sb.Append(hash[i].ToString("X2"));
                    }

                    return(sb.ToString());
                }));
                Console.WriteLine("Passing control to patcher.js");
                engine.Execute(File.ReadAllText("patcher.js")).Invoke(new Func <string>(() =>
                {
                    switch (opts.Mode)
                    {
                    case 'D':
                        return("dump");

                    case 'C':
                        return("create");

                    default:
                        return("main");
                    }
                }).Invoke());
                Console.WriteLine("Exited JavaScript mode.");
                Console.WriteLine("Now writing data.win...");
                if (opts.FileLocation.EndsWith(".bak"))
                {
                    opts.FileLocation = opts.FileLocation.Slice(0, opts.FileLocation.Length - 4);
                }
                Console.WriteLine(opts.FileLocation);
                var write = new UndertaleWriter(File.OpenWrite(opts.FileLocation));
                write.WriteUndertaleData(data);
                write.Close();
                Console.WriteLine("Written!");
                if (!opts.DoNotRunLater)
                {
                    Console.WriteLine("Now starting the game :)");
                    Process.Start(Path.Combine(Path.GetDirectoryName(opts.FileLocation), "MyRabbitsAreGone.exe"));
                    Process.GetCurrentProcess().Kill();
                }

                Console.WriteLine("Seeya!");
            }
            catch (JavaScriptException e)
            {
                Console.Error.WriteLine("Error \"{0}\" at {1}:{2}", e.Message, e.LineNumber, e.Column);
                Console.Error.WriteLine(e.CallStack);
                Environment.Exit(1);
            } catch (Exception e) {
                Console.Error.WriteLine("{0}: \"{1}\"", e.GetType().Name, e.Message);
                Console.Error.WriteLine(e.Source);
                Environment.Exit(1);
            }
        });
    }
 public void Serialize(UndertaleWriter writer)
 {
     writer.Write(Value);
 }
Beispiel #26
0
 internal override void SerializeChunk(UndertaleWriter writer)
 {
     throw new NotImplementedException();
 }
 public override void Serialize(UndertaleWriter writer)
 {
     base.Serialize(writer);
     List.Serialize(writer);
 }
 public void Serialize(UndertaleWriter writer)
 {
     writer.WriteUndertaleString(Name);
     writer.WriteUndertaleString(Value);
 }
    /// <inheritdoc />
    public void Serialize(UndertaleWriter writer)
    {
        writer.WriteUndertaleString(Name);
        writer.Write((uint)Type | 0x80000000u); // in big-endian?

        writer.WriteUndertaleString(GLSL_ES_Vertex);
        writer.WriteUndertaleString(GLSL_ES_Fragment);
        writer.WriteUndertaleString(GLSL_Vertex);
        writer.WriteUndertaleString(GLSL_Fragment);
        writer.WriteUndertaleString(HLSL9_Vertex);
        writer.WriteUndertaleString(HLSL9_Fragment);

        HLSL11_VertexData.Serialize(writer, false);
        HLSL11_PixelData.Serialize(writer, false);

        writer.WriteUndertaleObject(VertexShaderAttributes);

        writer.Write(Version);

        PSSL_VertexData.Serialize(writer);
        PSSL_PixelData.Serialize(writer);
        Cg_PSVita_VertexData.Serialize(writer);
        Cg_PSVita_PixelData.Serialize(writer);

        if (Version >= 2)
        {
            Cg_PS3_VertexData.Serialize(writer);
            Cg_PS3_PixelData.Serialize(writer);
        }

        if (!HLSL11_VertexData.IsNull)
        {
            WritePadding(writer, 7);

            HLSL11_VertexData.WriteData(writer);
        }
        if (!HLSL11_PixelData.IsNull)
        {
            WritePadding(writer, 7);

            HLSL11_PixelData.WriteData(writer);
        }

        if (!PSSL_VertexData.IsNull)
        {
            WritePadding(writer, 7);

            PSSL_VertexData.WriteData(writer);
        }
        if (!PSSL_PixelData.IsNull)
        {
            WritePadding(writer, 7);

            PSSL_PixelData.WriteData(writer);
        }

        if (!Cg_PSVita_VertexData.IsNull)
        {
            WritePadding(writer, 7);

            Cg_PSVita_VertexData.WriteData(writer);
        }
        if (!Cg_PSVita_PixelData.IsNull)
        {
            WritePadding(writer, 7);

            Cg_PSVita_PixelData.WriteData(writer);
        }

        if (Version >= 2)
        {
            if (!Cg_PS3_VertexData.IsNull)
            {
                WritePadding(writer, 15);

                Cg_PS3_VertexData.WriteData(writer);
            }
            if (!Cg_PS3_PixelData.IsNull)
            {
                WritePadding(writer, 15);

                Cg_PS3_PixelData.WriteData(writer);
            }
        }
    }