} = 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); }
internal override void SerializeChunk(UndertaleWriter writer) { List.Serialize(writer); }
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()); } }
internal override void SerializeChunk(UndertaleWriter writer) { writer.WriteUndertaleObject(Object); }
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; }
public void Serialize(UndertaleWriter writer) { Serialize(writer, true); }
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); }
/// <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; } }
public void Serialize(UndertaleWriter writer) { writer.WriteGMString(Content); }
public virtual void Serialize(UndertaleWriter writer) { Resource.Serialize(writer); }
internal abstract void SerializeChunk(UndertaleWriter writer);
public override void Serialize(UndertaleWriter writer) { base.Serialize(writer); writer.Write((int)0); writer.Write(Mode); }
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); }
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); } } }