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); }
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); }