예제 #1
0
        public GameActor(ROMHandler.ROMHandler rom, ActorTableEntry ate)
        {
            ROM     = rom;
            ATEntry = ate;

            /* General stuff */
            HierarchyAddresses = new List <AddressClass>();
            AnimationAddresses = new List <AddressClass>();
            Hierarchies        = new List <LimbClass[]>();
            HierarchyMatrices  = new List <byte[]>();
            GlobalTranslation  = Vector3d.Zero;

            /* Object list */
            ObjectsUsed = new List <ObjectTableEntry>();
            ObjectsUsed.Add(ROM.Objects[1]);
            ObjectsUsed.Add(ROM.Objects[2]);
            ObjectsUsed.Add(ROM.Objects[3]);
            ObjectsUsed.Add(ROM.Objects[ATEntry.ObjectNumber]);

            /* Display list list */
            DisplayLists = new List <DisplayListEx>();

            /* Numbers */
            TotalFrames = CurrentHierarchy = CurrentAnimation = CurrentFrame = 0;

            /* Temp DL address list */
            List <uint> dladrs = new List <uint>();

            /* MIPS evaluation of overlay */
            if (ATEntry.StartAddress != 0)
            {
                DMATableEntry ovldma = ROM.Files.Find(x => x.VStart == ATEntry.StartAddress);
                if (ovldma != null)
                {
                    try
                    {
                        /* Create evaluator and begin */
                        //LogWriter = System.IO.File.CreateText("E:\\temp\\sorata\\log.txt");
                        MIPS = new MIPSEvaluator(rom, ovldma, ATEntry.RAMStartAddress, new MIPSEvaluator.RegisterHookDelegate(RegisterChecker), 0);
                        MIPS.BeginEvaluation();
                        //LogWriter.Close();

                        /* Parse results for DL addresses & additional objects */
                        foreach (MIPSEvaluator.Result res in MIPS.Results)
                        {
                            if (res.TargetAddress == (FunctionDisplayList1 & 0xFFFFFF) && res.Arguments[1] != 0)
                            {
                                dladrs.Add(res.Arguments[1]);
                            }
                            else if (res.TargetAddress == (FunctionDisplayList2 & 0xFFFFFF) && res.Arguments[3] != 0)
                            {
                                dladrs.Add(res.Arguments[3]);
                            }
                            else if (res.TargetAddress == (FunctionDisplayList3 & 0xFFFFFF) && res.Arguments[0] != 0)
                            {
                                dladrs.Add(res.Arguments[0]);
                            }

                            if (res.TargetAddress == (FunctionObjectNumber & 0xFFFFFF) && res.Arguments[1] != 0 && (ushort)res.Arguments[1] < ROM.ObjectCount)
                            {
                                ObjectsUsed.Add(ROM.Objects[(ushort)res.Arguments[1]]);
                            }
                        }

                        /* Log results with address arguments in segments 0x04, 0x05 or 0x06 */
                        //LogSuspiciousResults();
                    }
                    catch (Exception ex)
                    {
                        System.Windows.Forms.MessageBox.Show("Exception in MIPS evaluator!\n\n" + ex.ToString() + "\n\nPlease notify the developers of this error!", "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation);
                    }
                }
            }

            /* If no hierarchy/animation addresses found, use addresses from MIPS evaluation if any */
            if (MIPS != null && (HierarchyAddresses.Count == 0 || AnimationAddresses.Count == 0))
            {
                foreach (MIPSEvaluator.Result res in MIPS.Results)
                {
                    if (res.TargetAddress == (FunctionHierarchyAnim1 & 0xFFFFFF) ||
                        res.TargetAddress == (FunctionHierarchyAnim2 & 0xFFFFFF))
                    {
                        HierarchyAddresses.Add(new AddressClass(res.Arguments[2]));
                        AnimationAddresses.Add(new AddressClass(res.Arguments[3]));
                    }
                }
            }

            /* Remove garbage zeroes from address results */
            HierarchyAddresses.RemoveAll(x => x.Address == 0);
            AnimationAddresses.RemoveAll(x => x.Address == 0);

            /* Parse objects & scan for hierarchies and animations if needed */
            for (int i = 0; i < ObjectsUsed.Count; i++)
            {
                if (ObjectsUsed[i].DMA != null)
                {
                    byte seg = (byte)(ObjectsUsed[i].DMA.AssumedSegment == 0 ? 0x06 : ObjectsUsed[i].DMA.AssumedSegment);

                    byte[] loadsegdata = new byte[ObjectsUsed[i].DMA.PEnd - ObjectsUsed[i].DMA.PStart];
                    Buffer.BlockCopy(rom.Data, (int)ObjectsUsed[i].DMA.PStart, loadsegdata, 0, loadsegdata.Length);

                    ROM.SegmentMapping.Remove((byte)0x06);
                    ROM.SegmentMapping.Add((byte)0x06, loadsegdata);

                    if (seg == 0x06 /* && HierarchyAddresses.Count == 0*/)
                    {
                        ScanForHierarchies(seg);
                    }
                    if (seg == 0x06 /* && AnimationAddresses.Count == 0*/)
                    {
                        ScanForAnimations(seg);
                    }
                }
            }

            /* Hackish RAM segment generation for facial textures */
            ProcessFacialTextureHack();

            /* Ensure display list address validity */
            dladrs = dladrs.Where(x => ROM.IsAddressSupported(x) == true).ToList();

            /* If still no hierarchy/animation and display list addresses found, search for display lists in segment 0x06 */
            if (HierarchyAddresses.Count == 0 && AnimationAddresses.Count == 0 && dladrs.Count == 0)
            {
                dladrs = ScanForDisplayLists(0x06);
            }

            /* Execute display lists */
            if (dladrs != null)
            {
                foreach (uint dla in dladrs)
                {
                    DisplayListEx dlex = new DisplayListEx(ListMode.Compile);
                    ROM.Renderer.Render(dla);
                    dlex.End();
                    DisplayLists.Add(dlex);
                }
            }

            /* Clean up address results */
            if (HierarchyAddresses.Count != 0 && AnimationAddresses.Count != 0)
            {
                HierarchyAddresses = HierarchyAddresses.Where(x => ROM.IsAddressSupported(x.Address) == true).GroupBy(x => x.Address).Select(x => x.First()).ToList();
                AnimationAddresses = AnimationAddresses.Where(x => ROM.IsAddressSupported(x.Address) == true).GroupBy(x => x.Address).Select(x => x.First()).ToList();
            }

            /* Initial data read */
            ReadHierarchies();
            ReadAnimation(CurrentHierarchy, CurrentAnimation, CurrentFrame);
        }
예제 #2
0
        public GameActor(ROMHandler.ROMHandler rom, ActorTableEntry ate)
        {
            ROM = rom;
            ATEntry = ate;

            /* General stuff */
            HierarchyAddresses = new List<AddressClass>();
            AnimationAddresses = new List<AddressClass>();
            Hierarchies = new List<LimbClass[]>();
            HierarchyMatrices = new List<byte[]>();
            GlobalTranslation = Vector3d.Zero;

            /* Object list */
            ObjectsUsed = new List<ObjectTableEntry>();
            ObjectsUsed.Add(ROM.Objects[1]);
            ObjectsUsed.Add(ROM.Objects[2]);
            ObjectsUsed.Add(ROM.Objects[3]);
            ObjectsUsed.Add(ROM.Objects[ATEntry.ObjectNumber]);

            /* Display list list */
            DisplayLists = new List<DisplayListEx>();

            /* Numbers */
            TotalFrames = CurrentHierarchy = CurrentAnimation = CurrentFrame = 0;

            /* Temp DL address list */
            List<uint> dladrs = new List<uint>();

            /* MIPS evaluation of overlay */
            if (ATEntry.StartAddress != 0)
            {
                DMATableEntry ovldma = ROM.Files.Find(x => x.VStart == ATEntry.StartAddress);
                if (ovldma != null)
                {
                    try
                    {
                        /* Create evaluator and begin */
                        //LogWriter = System.IO.File.CreateText("E:\\temp\\sorata\\log.txt");
                        MIPS = new MIPSEvaluator(rom, ovldma, ATEntry.RAMStartAddress, new MIPSEvaluator.RegisterHookDelegate(RegisterChecker), 0);
                        MIPS.BeginEvaluation();
                        //LogWriter.Close();

                        /* Parse results for DL addresses & additional objects */
                        foreach (MIPSEvaluator.Result res in MIPS.Results)
                        {
                            if (res.TargetAddress == (FunctionDisplayList1 & 0xFFFFFF) && res.Arguments[1] != 0)
                                dladrs.Add(res.Arguments[1]);
                            else if (res.TargetAddress == (FunctionDisplayList2 & 0xFFFFFF) && res.Arguments[3] != 0)
                                dladrs.Add(res.Arguments[3]);
                            else if (res.TargetAddress == (FunctionDisplayList3 & 0xFFFFFF) && res.Arguments[0] != 0)
                                dladrs.Add(res.Arguments[0]);

                            if (res.TargetAddress == (FunctionObjectNumber & 0xFFFFFF) && res.Arguments[1] != 0 && (ushort)res.Arguments[1] < ROM.ObjectCount)
                                ObjectsUsed.Add(ROM.Objects[(ushort)res.Arguments[1]]);
                        }

                        /* Log results with address arguments in segments 0x04, 0x05 or 0x06 */
                        //LogSuspiciousResults();
                    }
                    catch (Exception ex)
                    {
                        System.Windows.Forms.MessageBox.Show("Exception in MIPS evaluator!\n\n" + ex.ToString() + "\n\nPlease notify the developers of this error!", "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation);
                    }
                }
            }

            /* If no hierarchy/animation addresses found, use addresses from MIPS evaluation if any */
            if (MIPS != null && (HierarchyAddresses.Count == 0 || AnimationAddresses.Count == 0))
            {
                foreach (MIPSEvaluator.Result res in MIPS.Results)
                {
                    if (res.TargetAddress == (FunctionHierarchyAnim1 & 0xFFFFFF) ||
                        res.TargetAddress == (FunctionHierarchyAnim2 & 0xFFFFFF))
                    {
                        HierarchyAddresses.Add(new AddressClass(res.Arguments[2]));
                        AnimationAddresses.Add(new AddressClass(res.Arguments[3]));
                    }
                }
            }

            /* Remove garbage zeroes from address results */
            HierarchyAddresses.RemoveAll(x => x.Address == 0);
            AnimationAddresses.RemoveAll(x => x.Address == 0);

            /* Parse objects & scan for hierarchies and animations if needed */
            for (int i = 0; i < ObjectsUsed.Count; i++)
            {
                if (ObjectsUsed[i].DMA != null)
                {
                    byte seg = (byte)(ObjectsUsed[i].DMA.AssumedSegment == 0 ? 0x06 : ObjectsUsed[i].DMA.AssumedSegment);

                    byte[] loadsegdata = new byte[ObjectsUsed[i].DMA.PEnd - ObjectsUsed[i].DMA.PStart];
                    Buffer.BlockCopy(rom.Data, (int)ObjectsUsed[i].DMA.PStart, loadsegdata, 0, loadsegdata.Length);

                    ROM.SegmentMapping.Remove((byte)0x06);
                    ROM.SegmentMapping.Add((byte)0x06, loadsegdata);

                    if (seg == 0x06/* && HierarchyAddresses.Count == 0*/) ScanForHierarchies(seg);
                    if (seg == 0x06/* && AnimationAddresses.Count == 0*/) ScanForAnimations(seg);
                }
            }

            /* Hackish RAM segment generation for facial textures */
            ProcessFacialTextureHack();

            /* Ensure display list address validity */
            dladrs = dladrs.Where(x => ROM.IsAddressSupported(x) == true).ToList();

            /* If still no hierarchy/animation and display list addresses found, search for display lists in segment 0x06 */
            if (HierarchyAddresses.Count == 0 && AnimationAddresses.Count == 0 && dladrs.Count == 0)
                dladrs = ScanForDisplayLists(0x06);

            /* Execute display lists */
            if (dladrs != null)
            {
                foreach (uint dla in dladrs)
                {
                    DisplayListEx dlex = new DisplayListEx(ListMode.Compile);
                    ROM.Renderer.Render(dla);
                    dlex.End();
                    DisplayLists.Add(dlex);
                }
            }

            /* Clean up address results */
            if (HierarchyAddresses.Count != 0 && AnimationAddresses.Count != 0)
            {
                HierarchyAddresses = HierarchyAddresses.Where(x => ROM.IsAddressSupported(x.Address) == true).GroupBy(x => x.Address).Select(x => x.First()).ToList();
                AnimationAddresses = AnimationAddresses.Where(x => ROM.IsAddressSupported(x.Address) == true).GroupBy(x => x.Address).Select(x => x.First()).ToList();
            }

            /* Initial data read */
            ReadHierarchies();
            ReadAnimation(CurrentHierarchy, CurrentAnimation, CurrentFrame);
        }