private void RemoveActor0001FromHeader(SceneHeader header, RomFile sceneFile) { var item = header[HeaderCommands.TransitionActorList]; if (item != null) { RemoveActor0001(sceneFile, item); } item = header[HeaderCommands.ActorList]; if (item != null) { RemoveActor0001(sceneFile, item); } }
private void RemoveActor0001FromFile(MemoryStream ms, RomFile sceneFile, SceneHeader header) { RemoveActor0001FromHeader(header, sceneFile); if (header.HasAlternateHeaders()) { foreach (var item in header.Alternate.Headers) { if (item != null) { RemoveActor0001FromHeader(item, sceneFile); } } } }
public static bool WriteWorldToFile(World world, FileInfo outputFile) { // TODO need to bring this back #if false // Check for missing assembly references var unresolvedComponentTypes = GetAllUsedComponentTypes(world).Where(t => !DomainCache.IsIncludedInProject(project, t.GetManagedType())).ToArray(); if (unresolvedComponentTypes.Length > 0) { foreach (var unresolvedComponentType in unresolvedComponentTypes) { var type = unresolvedComponentType.GetManagedType(); Debug.LogError($"Could not resolve component type '{type.FullName}' while exporting {scenePath.ToHyperLink()}. Are you missing an assembly reference to '{type.Assembly.GetName().Name}' ?"); } return(false); } #endif var directoryName = Path.GetDirectoryName(outputFile.FullName); if (string.IsNullOrEmpty(directoryName)) { throw new ArgumentException($"Invalid output file directory: {directoryName}", nameof(outputFile)); } if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } // Merges the entities and shared component streams, (optionally) compresses them, and finally serializes to disk with a small header in front using (var fileStream = new StreamBinaryWriter(outputFile.FullName)) using (var entitiesWriter = new MemoryBinaryWriter()) { var entityRemapInfos = new NativeArray <EntityRemapUtility.EntityRemapInfo>(world.EntityManager.EntityCapacity, Allocator.Temp); SerializeUtility.SerializeWorldInternal(world.EntityManager, entitiesWriter, out var referencedObjects, entityRemapInfos, isDOTSRuntime: true); entityRemapInfos.Dispose(); if (referencedObjects != null) { throw new ArgumentException("We are serializing a world that contains UnityEngine.Object references which are not supported in Dots Runtime."); } #if TINY_SCENE_DEP unsafe { var worldHeader = new SceneHeader(); worldHeader.DecompressedSize = entitiesWriter.Length; worldHeader.Codec = Codec.LZ4; worldHeader.SerializeHeader(fileStream); if (worldHeader.Codec != Codec.None) { int compressedSize = CodecService.Compress(worldHeader.Codec, entitiesWriter.Data, entitiesWriter.Length, out var compressedData); fileStream.WriteBytes(compressedData, compressedSize); } else { fileStream.WriteBytes(entitiesWriter.Data, entitiesWriter.Length); } } #endif } return(true); }
public static StringBuilder Calculate(IExperimentFace face, List <string> files) { StringBuilder result = new StringBuilder(); int N0_SceneEndAddr = 0x384980; int N0_CodeAddr = 0x110A0; SegmentAddress[] SegmentTable = new SegmentAddress[16]; Dictionary <short, EntranceTableRecord> EntranceTableSimplified = new Dictionary <short, EntranceTableRecord>(); Rom N0 = new ORom(files[0], ORom.Build.N0); Addresser.TryGetRom(ORom.FileList.code, N0.Version, AddressToken.EntranceIndexTable_Start, out int entranceTableAddress); Addresser.TryGetRom(ORom.FileList.code, N0.Version, AddressToken.ActorTable_Start, out int actorTableRomAddress); var code_File = N0.Files.GetFile(ORom.FileList.code); var codeStr = new BinaryReader(code_File); codeStr.BaseStream.Position = code_File.Record.GetRelativeAddress(entranceTableAddress); //remove redundant entrance table records for (int i = 0; i < 0x614; i++) { var record = new EntranceTableRecord(codeStr); short key = (short)((record.Scene << 8) + record.Spawn); if (!EntranceTableSimplified.ContainsKey(key)) { EntranceTableSimplified.Add(key, record); } } int lastScene = -1; RomFile scene_File = null; BinaryReader sceneStr = null; foreach (EntranceTableRecord record in EntranceTableSimplified.Values.OrderBy(x => x.Scene)) { if (sceneStr != null) { sceneStr.BaseStream.Position = 0; } if (record.Scene != lastScene) { if (record.Scene >= 101) { WriteResult(result, record, -1, ResultType.Crash, "No Scene"); continue; } scene_File = N0.Files.GetSceneFile(record.Scene); sceneStr = new BinaryReader(scene_File.Stream); SegmentTable[2] = N0_SceneEndAddr - scene_File.Record.VRom.Size; } //First, 0x18 command byte cmdId = sceneStr.ReadByte(); sceneStr.BaseStream.Position--; List <AlternateSetup> setups = new List <AlternateSetup>(); if (cmdId == 0x18) { sceneStr.BaseStream.Position += 4; int headerListOffset = sceneStr.ReadBigInt32() & 0xFFFFFF; sceneStr.BaseStream.Position = headerListOffset + 0xC; for (int i = 0; i < 0xD; i++) { int data = sceneStr.ReadBigInt32(); setups.Add(new AlternateSetup(i, data)); } } else { setups.Add(new AlternateSetup(-1, 0x02000000)); } //parse headers foreach (var setup in setups) { SceneHeader sceneHeader = new SceneHeader(); FaroresTest ft = FaroresTest.NA; //resolve header start if (setup.SegmentAddress.Segment != 2 || !(setup.SegmentAddress.Offset < scene_File.Record.VRom.Size)) { WriteResult(result, record, setup.SceneSetup, ResultType.Crash_Likely, UnresolvedAddress("Scene Setup", setup.SegmentAddress)); continue; } //set header start sceneStr.BaseStream.Position = setup.SegmentAddress.Offset; int loop = 32; while (loop > 0) { loop--; cmdId = sceneStr.ReadByte(); sceneStr.BaseStream.Position--; switch (cmdId) { case 0x14: if (sceneHeader.Cutscene == 0) { WriteResult(result, record, setup.SceneSetup, ResultType.Cutscene_Pointer, "No Known Issues", ft); } else { WriteResult(result, record, setup.SceneSetup, ResultType.Cutscene, "No Known Issues", ft); } loop = -1; break; case 0x04: //room definitions { sceneStr.BaseStream.Position += 1; sceneHeader.Rooms = sceneStr.ReadByte(); sceneStr.BaseStream.Position += 2; sceneHeader.RoomsAddress = sceneStr.ReadBigInt32(); break; } case 0x06: //entrance index definitions { sceneStr.BaseStream.Position += 4; sceneHeader.EntranceIndexDefinitionsAddress = sceneStr.ReadBigInt32(); break; } case 0x00: //Link spawns definitions { long seekBack; sceneStr.BaseStream.Position += 1; sceneHeader.LinkSpawns = sceneStr.ReadByte(); sceneStr.BaseStream.Position += 2; sceneHeader.LinkSpawnsAddress = sceneStr.ReadBigInt32(); //start resolving things here I guess SegmentAddress selectEntDefAddr = sceneHeader.EntranceIndexDefinitionsAddress + (record.Spawn << 1); if (selectEntDefAddr.Segment != 2 && selectEntDefAddr.Offset > scene_File.Record.VRom.Size) { WriteResult(result, record, setup.SceneSetup, ResultType.Crash_Likely, UnresolvedAddress("Entrance Definitions", selectEntDefAddr)); loop = -1; break; } seekBack = sceneStr.BaseStream.Position; sceneStr.BaseStream.Position = selectEntDefAddr.Offset; int spawnId = sceneStr.ReadByte(); int mapId = sceneStr.ReadByte(); //test if Link Spawn is invalid (phase 1) SegmentAddress selectSpawnAddr = sceneHeader.LinkSpawnsAddress + (spawnId << 4); if (selectSpawnAddr.Segment != 2 && selectSpawnAddr.Offset > scene_File.Record.VRom.Size) { WriteResult(result, record, setup.SceneSetup, ResultType.Crash_Likely, UnresolvedAddress("Link Spawn", selectSpawnAddr), ft); loop = -1; break; } //test if Map Id is invalid, making FW mandatory if (!(mapId < sceneHeader.Rooms)) { WriteResult(result, record, setup.SceneSetup, ResultType.Crash, string.Format("Invalid Room Id ({0})", mapId), FaroresTest.Without); ft = FaroresTest.With; //Don't break because we can continue parsing for FW purposes } //Check if Link spawn is valid (phase 2) sceneStr.BaseStream.Position = selectSpawnAddr.Offset; var actorId = sceneStr.ReadBigInt16(); int linkActorVarsRomAddr = actorId * 0x20 + 0x14; linkActorVarsRomAddr += actorTableRomAddress; var linkActorVarsRelOff = code_File.Record.GetRelativeAddress(linkActorVarsRomAddr); //pointer to Link's Actor vars can't be resolved if (linkActorVarsRelOff < 0 || !(linkActorVarsRelOff < code_File.Record.VRom.Size)) { WriteResult(result, record, setup.SceneSetup, ResultType.Crash_Likely, UnresolvedAddress("Link Actor Var Pointer", (int)(linkActorVarsRelOff + N0_CodeAddr)), ft); loop = -1; break; } codeStr.BaseStream.Position = linkActorVarsRelOff; int linkActorVarsWriteAddr = codeStr.ReadBigInt32(); int linkActorVarsWriteOff = (linkActorVarsWriteAddr - N0_CodeAddr + 8) & 0xFFFFFF; //pointer to where to update Link's object number can't be resolved if (linkActorVarsWriteOff < 0 || !(linkActorVarsWriteOff < code_File.Record.VRom.Size)) { WriteResult(result, record, setup.SceneSetup, ResultType.Crash_Likely, UnresolvedAddress("Link Object Dependency Write", linkActorVarsWriteAddr + 8), ft); loop = -1; break; } //check if pointer is going to do an unaligned write if (linkActorVarsWriteAddr % 2 == 1) { WriteResult(result, record, setup.SceneSetup, ResultType.Crash, string.Format("N64: Unaligned SH write to address {0:X8}", linkActorVarsWriteAddr + 8), ft); } sceneStr.BaseStream.Position = seekBack; break; } case 0x17: { sceneStr.BaseStream.Position += 4; sceneHeader.Cutscene = sceneStr.ReadBigInt32(); break; } default: sceneStr.BaseStream.Position += 8; break; } if (loop == 0) { WriteResult(result, record, setup.SceneSetup, ResultType.Error, "Header Parse Error"); } } } } face.OutputText(result.ToString()); return(result); }
private static bool ExportWorld(FileInfo outputFile, Project project, string scenePath, World world, bool performConversion = true) { if (performConversion) { SceneConversion.Convert(world); } // Null out any references to avoid the SerializeUtility from trying to patch asset entities. world.GetOrCreateSystem <ClearRemappedEntityReferenceSystem>().Update(); // Check for missing assembly references var unresolvedComponentTypes = GetAllUsedComponentTypes(world).Where(t => !DomainCache.IsIncludedInProject(project, t.GetManagedType())).ToArray(); if (unresolvedComponentTypes.Length > 0) { foreach (var unresolvedComponentType in unresolvedComponentTypes) { var type = unresolvedComponentType.GetManagedType(); Debug.LogError($"Could not resolve component type '{type.FullName}' while exporting {scenePath.HyperLink()}. Are you missing an assembly reference to '{type.Assembly.GetName().Name}' ?"); } return(false); } // Remove non-exported components var nonExportedComponentTypes = UnityEditor.TypeCache.GetTypesWithAttribute <NonExportedAttribute>().Select(t => new ComponentType(t)); world.EntityManager.RemoveComponent(world.EntityManager.UniversalQuery, new ComponentTypes(nonExportedComponentTypes.ToArray())); // Merges the entities and shared component streams, (optionally) compresses them, and finally serializes to disk with a small header in front using (var fileStream = new StreamBinaryWriter(outputFile.FullName)) using (var entitiesWriter = new MemoryBinaryWriter()) using (var sharedComponentWriter = new MemoryBinaryWriter()) using (var combinedDataWriter = new MemoryBinaryWriter()) { SerializeUtility.SerializeWorld(world.EntityManager, entitiesWriter, out var sharedComponentsToSerialize); if (sharedComponentsToSerialize.Length > 0) { SerializeUtility.SerializeSharedComponents(world.EntityManager, sharedComponentWriter, sharedComponentsToSerialize); } unsafe { combinedDataWriter.WriteBytes(sharedComponentWriter.Data, sharedComponentWriter.Length); combinedDataWriter.WriteBytes(entitiesWriter.Data, entitiesWriter.Length); var worldHeader = new SceneHeader(); worldHeader.SharedComponentCount = sharedComponentsToSerialize.Length; worldHeader.DecompressedSize = entitiesWriter.Length + sharedComponentWriter.Length; worldHeader.Codec = Codec.LZ4; worldHeader.SerializeHeader(fileStream); if (worldHeader.Codec != Codec.None) { int compressedSize = CodecService.Compress(worldHeader.Codec, combinedDataWriter.Data, combinedDataWriter.Length, out var compressedData); fileStream.WriteBytes(compressedData, compressedSize); } else { fileStream.WriteBytes(combinedDataWriter.Data, combinedDataWriter.Length); } } } return(true); }