/// <summary> /// Loads the specified level for the editor /// </summary> /// <param name="context">The serialization context</param> /// <param name="loadTextures">Indicates if textures should be loaded</param> /// <returns>The level</returns> public override async UniTask <Unity_Level> LoadAsync(Context context, bool loadTextures) { await Controller.WaitIfNecessary(); Controller.DetailedState = $"Loading files"; uint baseAddress = 0x80018000; var fixDTAPath = FixDataPath; var fixGRPPath = FixGraphicsPath; var sprPLSPath = SpritePalettesPath; var levelDTAPath = GetLevelDataPath(context.Settings); var levelSPRPath = GetLevelImageDescriptorsPath(context.Settings); var levelGRPPath = GetLevelGraphicsPath(context.Settings); baseAddress += await LoadFile(context, fixDTAPath, baseAddress); baseAddress -= 94; // FIX.DTA header size Pointer fixDTAHeader = new Pointer(baseAddress, context.FilePointer(fixDTAPath).file); R1_R2AllfixFooter footer = null; context.Deserializer.DoAt(fixDTAHeader, () => footer = context.Deserializer.SerializeObject <R1_R2AllfixFooter>(null, name: "AllfixFooter")); await LoadFile(context, fixGRPPath, 0); await LoadFile(context, sprPLSPath, 0); baseAddress += await LoadFile(context, levelSPRPath, baseAddress); baseAddress += await LoadFile(context, levelDTAPath, baseAddress); await LoadFile(context, levelGRPPath, 0); // Load every map for (int i = 0; i < 4; i++) { await LoadFile(context, GetSubMapPalettePath(i), 0); await LoadFile(context, GetSubMapTilesetPath(i), 0); await LoadFile(context, GetSubMapPath(i), 0); } await Controller.WaitIfNecessary(); Controller.DetailedState = $"Loading level data"; // Read the level data var lvlData = FileFactory.Read <R1_R2LevDataFile>(levelDTAPath, context); // Read the map blocks var maps = Enumerable.Range(0, MapCount).Select(x => FileFactory.Read <MapData>(GetSubMapPath(x), context)).ToArray(); await Controller.WaitIfNecessary(); Controller.DetailedState = $"Loading sprite data"; var commonEvents = new List <Unity_Object>(); if (loadTextures) { // Get the v-ram FillVRAM(context, VRAMMode.Level); } // Create the global design list var lvlImgDescriptors = FileFactory.Read <ObjectArray <R1_ImageDescriptor> >(levelSPRPath, context, onPreSerialize: (s, a) => a.Length = s.CurrentLength / 0xC).Value; var imgDescriptors = lvlData.FixImageDescriptors.Concat(lvlImgDescriptors).ToArray(); // Get every sprite var globalDesigns = imgDescriptors.Select(img => GetSpriteTexture(context, null, img)).Select(tex => tex == null ? null : tex.CreateSprite()).ToArray(); // Get the events var events = lvlData.Events.Concat(lvlData.AlwaysEvents).ToArray(); Controller.DetailedState = $"Loading animations"; await Controller.WaitIfNecessary(); // Get the animation groups var r2AnimGroups = events.Select(x => x.AnimGroup).Append(footer.RaymanAnimGroup).Distinct().ToArray(); Unity_ObjectManager_R2.AnimGroup[] animGroups = new Unity_ObjectManager_R2.AnimGroup[r2AnimGroups.Length]; for (int i = 0; i < animGroups.Length; i++) { animGroups[i] = await getGroupAsync(r2AnimGroups[i]); await Controller.WaitIfNecessary(); } async UniTask <Unity_ObjectManager_R2.AnimGroup> getGroupAsync(R1_R2EventAnimGroup animGroup) { await UniTask.CompletedTask; // Add DES and ETA return(new Unity_ObjectManager_R2.AnimGroup( pointer: animGroup?.Offset, eta: animGroup?.ETA.EventStates ?? new R1_EventState[0][], animations: animGroup?.AnimationDecriptors?.Select(x => x.ToCommonAnimation()).ToArray(), filePath: animGroup?.AnimationDescriptorsPointer?.file.filePath)); } var objManager = new Unity_ObjectManager_R2( context: context, linkTable: lvlData.EventLinkTable, animGroups: animGroups, sprites: globalDesigns, imageDescriptors: imgDescriptors, levData: lvlData); Controller.DetailedState = $"Loading events"; await Controller.WaitIfNecessary(); // Add every event foreach (var e in events) { // Add the event commonEvents.Add(new Unity_Object_R2(e, objManager) { IsAlwaysEvent = lvlData.AlwaysEvents.Contains(e) }); } await Controller.WaitIfNecessary(); Controller.DetailedState = $"Loading tiles"; var levelMaps = maps.Select((x, i) => new Unity_Map() { // Set the dimensions Width = x.Width, Height = x.Height, // Create the tile array TileSet = new Unity_MapTileMap[1], TileSetWidth = TileSetWidth }).ToArray(); // Convert levelData to common level format Unity_Level level = new Unity_Level(levelMaps, objManager, commonEvents, rayman: new Unity_Object_R2(R1_R2EventData.GetRayman(events.FirstOrDefault(x => x.EventType == R1_R2EventType.RaymanPosition), footer), objManager), getCollisionTypeGraphicFunc: x => ((R2_TileCollsionType)x).GetCollisionTypeGraphic()); await Controller.WaitIfNecessary(); // Load maps for (int i = 0; i < MapCount; i++) { // Get the tile set Unity_MapTileMap tileSet = GetTileSet(context, i); level.Maps[i].TileSet[0] = tileSet; // Set the tiles level.Maps[i].MapTiles = maps[i].Tiles.Select(x => new Unity_Tile(x)).ToArray(); } // Return the level return(level); }
public static GBAVV_Isometric_Animation CrateAndSerialize(SerializerObject s, Pointer framesPointer, int framesCount, int width, int height, Pointer palPointer) { var anim = new GBAVV_Isometric_Animation { Width = width * 8, Height = height * 8, XPos = (FixedPointInt)(-width * 4 / 16f), YPos = (FixedPointInt)(-height * 4 / 16f), FramesPointer = framesPointer, PalettePointer = palPointer, FramesCount = framesCount, }; anim.SerializeData(s); return(anim); }
public void SerializeData(SerializerObject s) { if (FramesCountPointer == 0 && FramesCount == 0) { FramesPointers = new Pointer[] { FramesPointer }; } else { if (FramesCount == 0) { if (s.GameSettings.GameModeSelection == GameModeSelection.Crash2GBAUS) { switch (FramesCountPointer) { case 0x02000578: FramesCount = 0x0A; break; case 0x02000574: FramesCount = 0x0E; break; case 0x0200057c: FramesCount = 0x0A; break; case 0x02000580: FramesCount = 0x0A; break; case 0x02000588: FramesCount = 0x02; break; case 0x02000584: FramesCount = 0x0F; break; default: throw new ArgumentOutOfRangeException(nameof(FramesCountPointer), FramesCountPointer, null); } } else if (s.GameSettings.GameModeSelection == GameModeSelection.Crash2GBAEU) { switch (FramesCountPointer) { case 0x0200058C: FramesCount = 0x0A; break; case 0x02000588: FramesCount = 0x0E; break; case 0x02000590: FramesCount = 0x0A; break; case 0x02000594: FramesCount = 0x0A; break; case 0x0200059C: FramesCount = 0x02; break; case 0x02000598: FramesCount = 0x0F; break; default: throw new ArgumentOutOfRangeException(nameof(FramesCountPointer), FramesCountPointer, null); } } else if (s.GameSettings.GameModeSelection == GameModeSelection.Crash2GBAJP) { switch (FramesCountPointer) { case 0x0200059C: FramesCount = 0x0A; break; case 0x02000598: FramesCount = 0x0E; break; case 0x020005A0: FramesCount = 0x0A; break; case 0x020005A4: FramesCount = 0x0A; break; case 0x020005AC: FramesCount = 0x02; break; case 0x020005A8: FramesCount = 0x0F; break; default: throw new ArgumentOutOfRangeException(nameof(FramesCountPointer), FramesCountPointer, null); } } } FramesPointers = s.DoAt(FramesPointer, () => s.SerializePointerArray(FramesPointers, FramesCount, name: nameof(FramesPointer))); } if (PalettePointer != null) { Palette = s.DoAt(PalettePointer, () => s.SerializeObjectArray <RGBA5551Color>(Palette, 16, name: nameof(Palette))); } if (AnimFrames == null) { AnimFrames = new byte[FramesPointers.Length][]; } for (int i = 0; i < AnimFrames.Length; i++) { AnimFrames[i] = s.DoAt(FramesPointers[i], () => s.SerializeArray <byte>(AnimFrames[i], (Width * Height) / 2, name: $"{nameof(AnimFrames)}[{i}]")); } }
public DataContainer(T data, Pointer primaryPointer, string name = null) { Data = data; PrimaryPointer = primaryPointer; Name = name; }
public DESData(Unity_ObjGraphics graphics, R1_ImageDescriptor[] imageDescriptors, Pointer imageDescriptorPointer = null, Pointer animationDescriptorPointer = null, Pointer imageBufferPointer = null) { Graphics = graphics; ImageDescriptors = imageDescriptors ?? new R1_ImageDescriptor[0]; ImageDescriptorPointer = imageDescriptorPointer; AnimationDescriptorPointer = animationDescriptorPointer; ImageBufferPointer = imageBufferPointer; }
/// <summary> /// Handles the data serialization /// </summary> /// <param name="s">The serializer object</param> public override void SerializeImpl(SerializerObject s) { ETAPointer = s.SerializePointer(ETAPointer, name: nameof(ETAPointer)); CommandsPointer = s.SerializePointer(CommandsPointer, name: nameof(CommandsPointer)); XPosition = s.Serialize <short>(XPosition, name: nameof(XPosition)); YPosition = s.Serialize <short>(YPosition, name: nameof(YPosition)); DisplayPrio = s.Serialize <ushort>(DisplayPrio, name: nameof(DisplayPrio)); LinkGroup = s.Serialize <ushort>(LinkGroup, name: nameof(LinkGroup)); Etat = s.Serialize <byte>(Etat, name: nameof(Etat)); SubEtat = s.Serialize <byte>(SubEtat, name: nameof(SubEtat)); OffsetBX = s.Serialize <byte>(OffsetBX, name: nameof(OffsetBX)); OffsetBY = s.Serialize <byte>(OffsetBY, name: nameof(OffsetBY)); OffsetHY = s.Serialize <byte>(OffsetHY, name: nameof(OffsetHY)); FollowEnabled = s.Serialize <bool>(FollowEnabled, name: nameof(FollowEnabled)); FollowSprite = s.Serialize <byte>(FollowSprite, name: nameof(FollowSprite)); HitPoints = s.Serialize <byte>(HitPoints, name: nameof(HitPoints)); Type = s.Serialize <R1_EventType>(Type, name: nameof(Type)); HitSprite = s.Serialize <byte>(HitSprite, name: nameof(HitSprite)); Unk = s.Serialize <byte>(Unk, name: nameof(Unk)); // Serialize data from pointers // Serialize the current state if (ETAPointer != null) { do { var hasSerialized = ETA != null && s is BinaryDeserializer; int etatCount; if (!hasSerialized) { etatCount = Etat + 1; // Get correct etat count on GBA if (s.GameSettings.EngineVersion == EngineVersion.R1_GBA) { s.DoAt(ETAPointer, () => { int curEtatCount = 0; Pointer off_prev = null; while (true) { Pointer off_next = s.SerializePointer(null, allowInvalid: true, name: "TestPointer"); if (curEtatCount < etatCount || (off_next != null && off_next != ETAPointer && (off_prev == null || ((off_next.AbsoluteOffset - off_prev.AbsoluteOffset > 0) && (off_next.AbsoluteOffset - off_prev.AbsoluteOffset < 0x10000)) || (off_next.file != off_prev.file && off_next.file != Offset.file) ))) { curEtatCount++; off_prev = off_next; } else { break; } } etatCount = curEtatCount; }); } } else { etatCount = ETA.Length; } // Get max linked etat if we've already serialized ETA if (hasSerialized) { var maxLinked = ETA.SelectMany(x => x).Where(x => x != null).Max(x => x.LinkedEtat) + 1; if (etatCount < maxLinked) { etatCount = maxLinked; } } // Serialize etat pointers Pointer[] EtatPointers = s.DoAt(ETAPointer, () => s.SerializePointerArray(default, etatCount, name: $"{nameof(EtatPointers)}"));
protected override bool DoMemoryLoading(Context gameMemoryContext, Pointer offset) { var lvl = LevelEditorData.Level; bool madeEdits = false; Pointer currentOffset; SerializerObject s; void SerializeEvent(Unity_Object_R1 ed, Context context) { s = ed.HasPendingEdits ? (SerializerObject)context.Serializer : context.Deserializer; s.Goto(currentOffset); ed.EventData.Init(s.CurrentPointer); ed.EventData.Serialize(s); if (s is BinarySerializer) { Debug.Log($"Edited event {ed.EventData.EventIndex}"); madeEdits = true; } ed.HasPendingEdits = false; currentOffset = s.CurrentPointer; } // Events if (GameMemoryData.EventArrayOffset != null) { currentOffset = GameMemoryData.EventArrayOffset; foreach (var ed in lvl.EventData.OfType <Unity_Object_R1>()) { SerializeEvent(ed, gameMemoryContext); } } // Rayman if (GameMemoryData.RayEventOffset != null && lvl.Rayman is Unity_Object_R1 r1Ray) { currentOffset = GameMemoryData.RayEventOffset; SerializeEvent(r1Ray, gameMemoryContext); } // Tiles if (GameMemoryData.TileArrayOffset != null) { currentOffset = GameMemoryData.TileArrayOffset; var map = lvl.Maps[0]; for (int y = 0; y < map.Height; y++) { for (int x = 0; x < map.Width; x++) { var tileIndex = y * map.Width + x; var mapTile = map.MapTiles[tileIndex]; s = mapTile.HasPendingEdits ? (SerializerObject)gameMemoryContext.Serializer : gameMemoryContext.Deserializer; s.Goto(currentOffset); var prevX = mapTile.Data.TileMapX; var prevY = mapTile.Data.TileMapY; mapTile.Data.Init(s.CurrentPointer); mapTile.Data.Serialize(s); if (s is BinarySerializer) { madeEdits = true; } mapTile.HasPendingEdits = false; if (prevX != mapTile.Data.TileMapX || prevY != mapTile.Data.TileMapY) { Controller.obj.levelController.controllerTilemap.SetTileAtPos(x, y, mapTile); } currentOffset = s.CurrentPointer; // On PC we need to also update the BigMap pointer table if (GameMemoryData.BigMap != null && s is BinarySerializer) { var pointerOffset = GameMemoryData.BigMap.MapTileTexturesPointersPointer + (4 * tileIndex); var newPointer = GameMemoryData.BigMap.TileTexturesPointer + (lvl.Maps[0].PCTileOffsetTable[mapTile.Data.TileMapY]).SerializedOffset; s.Goto(pointerOffset); s.SerializePointer(newPointer); } } } } // Global values GlobalData.Update(new ToggleSerializer(gameMemoryContext, x => GlobalPendingEdits || GlobalDataForceWrite.Contains(x), offset)); GlobalPendingEdits = false; return(madeEdits); }
public override Pointer <T> SerializePointer <T>(Pointer <T> obj, Pointer anchor = null, bool resolve = false, Action <T> onPreSerialize = null, bool allowInvalid = false, string name = null) { UpdateCurrentSerializer(name); return(CurrentSerializer.SerializePointer(obj, anchor, resolve, onPreSerialize, allowInvalid, name)); }
public override Pointer SerializePointer(Pointer obj, Pointer anchor = null, bool allowInvalid = false, string name = null) { UpdateCurrentSerializer(name); return(CurrentSerializer.SerializePointer(obj, anchor, allowInvalid, name)); }
public override void Goto(Pointer offset) => CurrentSerializer.Goto(offset);
public override Pointer <T>[] SerializePointerArray <T>(Pointer <T>[] obj, long count, Pointer anchor = null, bool resolve = false, Action <T> onPreSerialize = null, bool allowInvalid = false, string name = null) { if (obj == null) { obj = new Pointer <T> [count]; } else if (count != obj.Length) { Array.Resize(ref obj, (int)count); } for (int i = 0; i < count; i++) { obj[i] = SerializePointer <T>(obj[i], anchor: anchor, resolve: resolve, onPreSerialize: onPreSerialize, allowInvalid: allowInvalid, name: name == null ? null : name + "[" + i + "]"); } return(obj); }
public ToggleSerializer(Context context, Func <string, bool> shouldWriteFunc, Pointer baseOffset) : base(context) { // Set properties ShouldWriteFunc = shouldWriteFunc; Serializer = context.Serializer; Deserializer = context.Deserializer; CurrentName = new Stack <string>(); // Init serializers Serializer.Goto(baseOffset); Deserializer.Goto(baseOffset); CurrentSerializer = Deserializer; }