Ejemplo n.º 1
0
        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);
            }
        }
Ejemplo n.º 2
0
 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);
             }
         }
     }
 }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
0
        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);
        }