public void Serialize(UndertaleWriter writer) { try { Debug.Assert(Name != null); writer.Write(Name.ToCharArray()); var lenWriter = writer.WriteLengthHere(); writer.SubmitMessage("Writing chunk " + Name); lenWriter.FromHere(); SerializeChunk(writer); if (Name != "FORM" && Name != writer.LastChunkName) { UndertaleGeneralInfo generalInfo = Name == "GEN8" ? ((UndertaleChunkGEN8)this).Object : writer.undertaleData?.GeneralInfo; // These versions introduced new padding // all chunks now start on 16-byte boundaries // (but the padding is included with length of previous chunk) // TODO: what about the debug data?? if (generalInfo != null && (generalInfo.Major >= 2 || (generalInfo.Major == 1 && generalInfo.Build >= 9999))) { int e = writer.undertaleData.PaddingAlignException; uint pad = (e == -1 ? 16 : (uint)e); while (writer.Position % pad != 0) { writer.Write((byte)0); } } } Length = lenWriter.ToHere(); } catch (UndertaleSerializationException e) { throw new UndertaleSerializationException(e.Message + " in chunk " + Name, e); } catch (Exception e) { throw new UndertaleSerializationException(e.Message + "\nat " + writer.Position.ToString("X8") + " while reading chunk " + Name, e); } }
public void Serialize(UndertaleWriter writer) { writer.WriteUndertaleString(Name); writer.Write(Occurrences); if (Occurrences > 0) { uint addr = writer.GetAddressForUndertaleObject(FirstAddress); if (GMS2_3) { writer.Write((addr == 0) ? 0 : (addr + 4)); // in GMS 2.3, it points to the actual reference rather than the instruction } else { writer.Write(addr); } } else { writer.Write((int)-1); } }
/// <inheritdoc /> public void Serialize(UndertaleWriter writer) { writer.Write(Character); writer.Write(SourceX); writer.Write(SourceY); writer.Write(SourceWidth); writer.Write(SourceHeight); writer.Write(Shift); writer.Write(Offset); writer.WriteUndertaleObject(Kerning); }
internal override void SerializeChunk(UndertaleWriter writer) { base.SerializeChunk(writer); if (writer.undertaleData.IsTPAG4ByteAligned) { // padding present in ARM platforms apparently while (writer.Position % 0x4 != 0) { writer.Write((byte)0); } } }
internal override void SerializeChunk(UndertaleWriter writer) { if (writer.undertaleData.GeneralInfo.Major < 2) { throw new InvalidOperationException(); } writer.Position += (4 - (writer.Position % 4)) % 4; writer.Write((uint)1); // Version base.SerializeChunk(writer); }
public void Serialize(UndertaleWriter writer) { try { Debug.Assert(Name != null); writer.Write(Name.ToCharArray()); var lenWriter = writer.WriteLengthHere(); Debug.WriteLine("Writing chunk " + Name); lenWriter.FromHere(); SerializeChunk(writer); if (Name != "FORM" && Name != "AUDO") // TODO: needs a better way to detect last chunk { UndertaleGeneralInfo generalInfo = Name == "GEN8" ? ((UndertaleChunkGEN8)this).Object : writer.undertaleData.GeneralInfo; // These versions introduced new padding // all chunks now start on 16-byte boundaries // (but the padding is included with length of previous chunk) if (generalInfo.Major >= 2 || (generalInfo.Major == 1 && generalInfo.Build >= 9999)) { while (writer.Position % 16 != 0) { writer.Write((byte)0); } } } Length = lenWriter.ToHere(); } catch (UndertaleSerializationException e) { throw new UndertaleSerializationException(e.Message + " in chunk " + Name); } catch (Exception e) { throw new UndertaleSerializationException(e.Message + "\nat " + writer.Position.ToString("X8") + " while reading chunk " + Name, e); } }
public void Serialize(UndertaleWriter writer) { writer.Write((uint)Count); for (int i = 0; i < Count; i++) { try { writer.WriteUndertaleString(this[i]); } catch (UndertaleSerializationException e) { throw new UndertaleSerializationException(e.Message + "\nwhile writing item " + (i + 1) + " of " + Count + " in a string-list", e); } } }
public void Serialize(UndertaleWriter writer) { writer.Write((ushort)Count); for (int i = 0; i < Count; i++) { try { writer.WriteUndertaleObject <T>(this[i]); } catch (UndertaleSerializationException e) { throw new UndertaleSerializationException(e.Message + "\nwhile writing item " + (i + 1) + " of " + Count + " in a list of " + typeof(T).FullName, e); } } }
internal override void SerializeChunk(UndertaleWriter writer) { base.SerializeChunk(writer); // (read above comment) foreach (byte[] data in productIdData) { int Len = data.Length; if (Len != 16) { throw new IOException("Can't write EXTN product id data of invalid length, expected 16, got " + Len); } writer.Write(data); } }
internal override void SerializeChunk(UndertaleWriter writer) { base.SerializeChunk(writer); // texture blobs foreach (UndertaleEmbeddedTexture obj in List) { obj.SerializeBlob(writer); } // padding // TODO: Maybe the padding is more global and every chunk is padded to 4 byte boundaries? while (writer.Position % 4 != 0) { writer.Write((byte)0); } }
public void Serialize(UndertaleWriter writer) { writer.Write(Key); writer.Write(Length); writer.Write(Stretch); writer.Write(Disabled); writer.Write(Channels.Count); foreach (KeyValuePair <int, T> kvp in Channels) { writer.Write(kvp.Key); kvp.Value.Serialize(writer); } }
public void Serialize(UndertaleWriter writer) { writer.Write(X); writer.Write(Value); if (writer.undertaleData.GMS2_3_1) { writer.Write(BezierX0); writer.Write(BezierY0); writer.Write(BezierX1); writer.Write(BezierY1); } else { writer.Write(0); } }
public void Serialize(UndertaleWriter writer) { writer.WriteUndertaleString(Name); writer.Write((uint)Playback); writer.Write(PlaybackSpeed); writer.Write((uint)PlaybackSpeedType); writer.Write(Length); writer.Write(OriginX); writer.Write(OriginY); writer.Write(Volume); BroadcastMessages.Serialize(writer); Tracks.Serialize(writer); writer.Write(FunctionIDs.Count); foreach (KeyValuePair <int, UndertaleString> kvp in FunctionIDs) { writer.Write(kvp.Key); writer.WriteUndertaleString(kvp.Value); } Moments.Serialize(writer); }
public void Serialize(UndertaleWriter writer) { writer.Write((uint)Count); foreach (T obj in this) { writer.WriteUndertaleObjectPointer <T>(obj); } for (int i = 0; i < Count; i++) { try { (this[i] as UndertaleObjectWithBlobs)?.SerializeBlobBefore(writer); } catch (UndertaleSerializationException e) { throw new UndertaleSerializationException(e.Message + "\nwhile writing blob for item " + (i + 1) + " of " + Count + " in a list of " + typeof(T).FullName, e); } } for (int i = 0; i < Count; i++) { try { (this[i] as PrePaddedObject)?.SerializePrePadding(writer); writer.WriteUndertaleObject <T>(this[i]); // The last object does NOT get padding (TODO: at least in AUDO) if (IndexOf(this[i]) != Count - 1) { (this[i] as PaddedObject)?.SerializePadding(writer); } } catch (UndertaleSerializationException e) { throw new UndertaleSerializationException(e.Message + "\nwhile writing item " + (i + 1) + " of " + Count + " in a list of " + typeof(T).FullName, e); } } }
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()); } }
public void Serialize(UndertaleWriter writer) { writer.Write(X); writer.Write(Y); writer.Write(Speed); }
public void Serialize(UndertaleWriter writer) { writer.Write(ID); Tags.Serialize(writer); }
public void Serialize(UndertaleWriter writer) { if (NewFormat) { writer.Write(Unknown1); writer.Write(Unknown2); writer.Write((ulong)Info); writer.Write(Scale); writer.Write(WindowColor); writer.Write(ColorDepth); writer.Write(Resolution); writer.Write(Frequency); writer.Write(VertexSync); writer.Write(Priority); writer.WriteUndertaleObject(BackImage); writer.WriteUndertaleObject(FrontImage); writer.WriteUndertaleObject(LoadImage); writer.Write(LoadAlpha); writer.WriteUndertaleObject(Constants); } else { writer.Write((Info & OptionsFlags.FullScreen) == OptionsFlags.FullScreen); writer.Write((Info & OptionsFlags.InterpolatePixels) == OptionsFlags.InterpolatePixels); writer.Write((Info & OptionsFlags.UseNewAudio) == OptionsFlags.UseNewAudio); writer.Write((Info & OptionsFlags.NoBorder) == OptionsFlags.NoBorder); writer.Write((Info & OptionsFlags.ShowCursor) == OptionsFlags.ShowCursor); writer.Write(Scale); writer.Write((Info & OptionsFlags.Sizeable) == OptionsFlags.Sizeable); writer.Write((Info & OptionsFlags.StayOnTop) == OptionsFlags.StayOnTop); writer.Write(WindowColor); writer.Write((Info & OptionsFlags.ChangeResolution) == OptionsFlags.ChangeResolution); writer.Write(ColorDepth); writer.Write(Resolution); writer.Write(Frequency); writer.Write((Info & OptionsFlags.NoButtons) == OptionsFlags.NoButtons); writer.Write(VertexSync); writer.Write((Info & OptionsFlags.ScreenKey) == OptionsFlags.ScreenKey); writer.Write((Info & OptionsFlags.HelpKey) == OptionsFlags.HelpKey); writer.Write((Info & OptionsFlags.QuitKey) == OptionsFlags.QuitKey); writer.Write((Info & OptionsFlags.SaveKey) == OptionsFlags.SaveKey); writer.Write((Info & OptionsFlags.ScreenShotKey) == OptionsFlags.ScreenShotKey); writer.Write((Info & OptionsFlags.CloseSec) == OptionsFlags.CloseSec); writer.Write(Priority); writer.Write((Info & OptionsFlags.Freeze) == OptionsFlags.Freeze); writer.Write((Info & OptionsFlags.ShowProgress) == OptionsFlags.ShowProgress); writer.WriteUndertaleObject(BackImage); writer.WriteUndertaleObject(FrontImage); writer.WriteUndertaleObject(LoadImage); writer.Write((Info & OptionsFlags.LoadTransparent) == OptionsFlags.LoadTransparent); writer.Write(LoadAlpha); writer.Write((Info & OptionsFlags.ScaleProgress) == OptionsFlags.ScaleProgress); writer.Write((Info & OptionsFlags.DisplayErrors) == OptionsFlags.DisplayErrors); writer.Write((Info & OptionsFlags.WriteErrors) == OptionsFlags.WriteErrors); writer.Write((Info & OptionsFlags.AbortErrors) == OptionsFlags.AbortErrors); writer.Write((Info & OptionsFlags.VariableErrors) == OptionsFlags.VariableErrors); writer.Write((Info & OptionsFlags.CreationEventOrder) == OptionsFlags.CreationEventOrder); writer.WriteUndertaleObject(Constants); } }
} = 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(Unknown1); writer.Write(Unknown2); writer.Write(Unknown3); writer.Write(Unknown4); 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); writer.Write(ActiveTargets1); writer.Write(ActiveTargets2); writer.Write(FunctionClassifications1); writer.Write(FunctionClassifications2); writer.Write(SteamAppID); writer.Write(DebuggerPort); writer.WriteUndertaleObject(RoomOrder); if (Major >= 2) { if (GMS2RandomUID.Length != 40) { throw new IOException("GMS2RandomUID has invalid length"); } writer.Write(GMS2RandomUID); writer.Write(GMS2FPS); if (GMS2GameGUID.Length != 16) { throw new IOException("GMS2GameGUID has invalid length"); } writer.Write(GMS2AllowStatistics); writer.Write(GMS2GameGUID); } }
/// <inheritdoc /> public void Serialize(UndertaleWriter writer) { writer.WriteUndertaleString(Name); writer.WriteUndertaleString(DisplayName); if (EmSizeIsFloat) { // cast to a float and negate. writer.Write(0.0f - EmSize); } else { // pre-GMS2.3 writer.Write(EmSize); } writer.Write(Bold); writer.Write(Italic); writer.Write(RangeStart); writer.Write(Charset); writer.Write(AntiAliasing); writer.Write(RangeEnd); writer.WriteUndertaleObjectPointer(Texture); writer.Write(ScaleX); writer.Write(ScaleY); if (writer.undertaleData.GeneralInfo?.BytecodeVersion >= 17) { writer.Write(AscenderOffset); } if (writer.undertaleData.GMS2022_2) { writer.Write(Ascender); } writer.WriteUndertaleObject(Glyphs); }
public void Serialize(UndertaleWriter writer) { writer.Write(Value); }
public override void Serialize(UndertaleWriter writer) { base.Serialize(writer); writer.Write((int)0); writer.Write(Mode); }
/// <inheritdoc /> public void Serialize(UndertaleWriter writer) { writer.Write(Other); writer.Write(Amount); }
public void Serialize(UndertaleWriter writer) { writer.Write(Unknown1); writer.Write(Unknown2); writer.Write((ulong)Info); writer.Write(Scale); writer.Write(WindowColor); writer.Write(ColorDepth); writer.Write(Resolution); writer.Write(Frequency); writer.Write(VertexSync); writer.Write(Priority); writer.WriteUndertaleObject(BackImage); writer.WriteUndertaleObject(FrontImage); writer.WriteUndertaleObject(LoadImage); writer.Write(LoadAlpha); writer.WriteUndertaleObject(Constants); }
/// <inheritdoc /> public void Serialize(UndertaleWriter writer) { writer.Write((uint)Data.Length); writer.Write(Data); }
public void Serialize(UndertaleWriter writer) { NextOccurrenceOffset = 0xdead; writer.WriteInt24(NextOccurrenceOffset); writer.Write((byte)Type); }
} = 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); 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 override void Serialize(UndertaleWriter writer) { writer.Write(Value); base.Serialize(writer); }
public void Serialize(UndertaleWriter writer) { writer.Write((uint)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; } }