//private bool CheckAddressValidity(byte bankNo, uint offset) //{ // if (offset == 0) return false; // if (!MemoryManager.Instance.HasBank(bankNo)) // { // ErrorLog.Add(string.Format("- Warning: Segment 0x{0:X2} was not initialized, cannot access offset 0x{0:X6}!\n", bankNo, offset)); // return false; // } // else if (!MemoryManager.Instance.LocateBank(bankNo, offset).IsValid()) // { // ErrorLog.Add(string.Format("- Warning: Offset 0x{0:X6} is out of bounds for segment 0x{0:X2}!\n", offset, bankNo)); // return false; // } // return true; //} public void StartReadingLevelDataAt(byte bankNo, uint index) { //This will need to parse the commands from the level data and pick off the F3DEX SFGfx.sv_ClearStructures(false); SFGfx.gl_ClearRenderer(true); SFGfx.GameObjects.Clear(); SFGfx.GameObjCount = 0; byte limbCount = MemoryManager.Instance.ReadByte(bankNo, index + 3); //This should be the number of limbs //First 4 bytes are things I don't know (+ the limb count), next 8 bytes are header pointers, then it starts the data index += 0xC; List<stuffToAdd> hierarchyTesting = new List<stuffToAdd>(); stuffToAdd topStuff = new stuffToAdd(); for(int i = 0; i < limbCount; i++) { if (!CheckAddressValidity(bankNo, index)) break; SFGfx.GameObject newObj = new SFGfx.GameObject(); newObj.LvlPos = 0; newObj.Z = (short)MemoryManager.Instance.ReadFloat(bankNo, index + 0x4); newObj.Y = (short)MemoryManager.Instance.ReadFloat(bankNo, index + 0x8); newObj.X = (short)MemoryManager.Instance.ReadFloat(bankNo, index + 0xC); newObj.XRot = (short)((double)MemoryManager.Instance.ReadUShort(bankNo, index + 0x10) / 182.0444444); newObj.YRot = (short)((double)MemoryManager.Instance.ReadUShort(bankNo, index + 0x12) / 182.0444444); newObj.ZRot = (short)((double)MemoryManager.Instance.ReadUShort(bankNo, index + 0x14) / 182.0444444); newObj.ID = 0; newObj.Unk = 0; // default dlist offset to 0 newObj.DListOffset = MemoryManager.Instance.ReadUInt(bankNo, index); //// if object id == 0xffff, break out because this marks end of data! //if (newObj.ID == 0xFFFF) break; //// if object id < 0x190, get offset like this //if (newObj.ID < 0x190) //{ // //NOTE: SET -2 TO DMA 1 // newObj.DListOffset = MemoryManager.Instance.ReadUInt((byte)0xFF, (0xC72E4 + ((uint)newObj.ID * 0x24))); //} // dlist offset sanity checks if (((newObj.DListOffset & 3) != 0x0) || // dlist offset not 4 byte aligned ((newObj.DListOffset & 0xFF000000) == 0x80000000)) // dlist offset lies in ram newObj.DListOffset = 0x00; stuffToAdd newHier = new stuffToAdd(); newHier.id = index + 0x04000000; newHier.siblingID = MemoryManager.Instance.ReadUInt(bankNo, index + 0x18); newHier.childID = MemoryManager.Instance.ReadUInt(bankNo, index + 0x1C); index += 0x20; //if (newObj.DListOffset != 0x00) //{ SFGfx.GameObjects.Add(newObj); newHier.gameObjectCount = SFGfx.GameObjCount; SFGfx.GameObjCount++; //} //else // newHier.gameObjectCount = -1; hierarchyTesting.Add(newHier); } //Apply hierarchy stuff. For now, assume that there is only 1 at the top which is not a child stuffToAdd topLevel = hierarchyTesting.SingleOrDefault(x => hierarchyTesting.Count(y => y.childID == x.id || y.siblingID == x.id) == 0); Queue<stuffToAdd> nextTopLevel = new Queue<stuffToAdd>(); while (topLevel.id != 0) { //Apply transformations each step down if (topLevel.childID != 0) { SFGfx.GameObject parentObject = SFGfx.GameObjects[topLevel.gameObjectCount]; stuffToAdd childNode = hierarchyTesting.SingleOrDefault(x => topLevel.childID == x.id); while (childNode.id != 0) { //Do the adding here SFGfx.GameObject gameObject = SFGfx.GameObjects[childNode.gameObjectCount]; gameObject.X += parentObject.X; gameObject.Y += parentObject.Y; gameObject.Z += parentObject.Z; gameObject.XRot += parentObject.XRot; gameObject.YRot += parentObject.YRot; gameObject.ZRot += parentObject.ZRot; SFGfx.GameObjects[childNode.gameObjectCount] = gameObject; if (childNode.siblingID != 0) childNode = hierarchyTesting.SingleOrDefault(x => childNode.siblingID == x.id); else childNode.id = 0; } } if(topLevel.siblingID != 0) nextTopLevel.Enqueue(hierarchyTesting.SingleOrDefault(x => topLevel.siblingID == x.id)); if(topLevel.childID != 0) nextTopLevel.Enqueue(hierarchyTesting.SingleOrDefault(x => topLevel.childID == x.id)); if (nextTopLevel.Count > 0) topLevel = nextTopLevel.Dequeue(); else topLevel.id = 0; } for (int j = hierarchyTesting.Count - 1; j >= 0; j--) { if (SFGfx.GameObjects[hierarchyTesting[j].gameObjectCount].DListOffset == 0x0) { SFGfx.GameObjects.RemoveAt(hierarchyTesting[j].gameObjectCount); SFGfx.GameObjCount--; } } ExecuteDisplayLists(); SFCamera.Reset(); }
//private bool CheckAddressValidity(byte bankNo, uint offset) //{ // if (offset == 0) return false; // if (!MemoryManager.Instance.HasBank(bankNo)) // { // ErrorLog.Add(string.Format("- Warning: Segment 0x{0:X2} was not initialized, cannot access offset 0x{0:X6}!\n", bankNo, offset)); // return false; // } // else if (!MemoryManager.Instance.LocateBank(bankNo, offset).IsValid()) // { // ErrorLog.Add(string.Format("- Warning: Offset 0x{0:X6} is out of bounds for segment 0x{0:X2}!\n", offset, bankNo)); // return false; // } // return true; //} public void StartReadingLevelDataAt(byte bankNo, uint index) { //This will need to parse the commands from the level data and pick off the F3DEX SFGfx.sv_ClearStructures(false); SFGfx.gl_ClearRenderer(true); SFGfx.GameObjects.Clear(); SFGfx.GameObjCount = 0; byte limbCount = MemoryManager.Instance.ReadByte(bankNo, index + 3); //This should be the number of limbs //First 4 bytes are things I don't know (+ the limb count), next 8 bytes are header pointers, then it starts the data index += 0xC; List <stuffToAdd> hierarchyTesting = new List <stuffToAdd>(); stuffToAdd topStuff = new stuffToAdd(); for (int i = 0; i < limbCount; i++) { if (!CheckAddressValidity(bankNo, index)) { break; } SFGfx.GameObject newObj = new SFGfx.GameObject(); newObj.LvlPos = 0; newObj.Z = (short)MemoryManager.Instance.ReadFloat(bankNo, index + 0x4); newObj.Y = (short)MemoryManager.Instance.ReadFloat(bankNo, index + 0x8); newObj.X = (short)MemoryManager.Instance.ReadFloat(bankNo, index + 0xC); newObj.XRot = (short)((double)MemoryManager.Instance.ReadUShort(bankNo, index + 0x10) / 182.0444444); newObj.YRot = (short)((double)MemoryManager.Instance.ReadUShort(bankNo, index + 0x12) / 182.0444444); newObj.ZRot = (short)((double)MemoryManager.Instance.ReadUShort(bankNo, index + 0x14) / 182.0444444); newObj.ID = 0; newObj.Unk = 0; // default dlist offset to 0 newObj.DListOffset = MemoryManager.Instance.ReadUInt(bankNo, index); //// if object id == 0xffff, break out because this marks end of data! //if (newObj.ID == 0xFFFF) break; //// if object id < 0x190, get offset like this //if (newObj.ID < 0x190) //{ // //NOTE: SET -2 TO DMA 1 // newObj.DListOffset = MemoryManager.Instance.ReadUInt((byte)0xFF, (0xC72E4 + ((uint)newObj.ID * 0x24))); //} // dlist offset sanity checks if (((newObj.DListOffset & 3) != 0x0) || // dlist offset not 4 byte aligned ((newObj.DListOffset & 0xFF000000) == 0x80000000)) // dlist offset lies in ram { newObj.DListOffset = 0x00; } stuffToAdd newHier = new stuffToAdd(); newHier.id = index + 0x04000000; newHier.siblingID = MemoryManager.Instance.ReadUInt(bankNo, index + 0x18); newHier.childID = MemoryManager.Instance.ReadUInt(bankNo, index + 0x1C); index += 0x20; //if (newObj.DListOffset != 0x00) //{ SFGfx.GameObjects.Add(newObj); newHier.gameObjectCount = SFGfx.GameObjCount; SFGfx.GameObjCount++; //} //else // newHier.gameObjectCount = -1; hierarchyTesting.Add(newHier); } //Apply hierarchy stuff. For now, assume that there is only 1 at the top which is not a child stuffToAdd topLevel = hierarchyTesting.SingleOrDefault(x => hierarchyTesting.Count(y => y.childID == x.id || y.siblingID == x.id) == 0); Queue <stuffToAdd> nextTopLevel = new Queue <stuffToAdd>(); while (topLevel.id != 0) { //Apply transformations each step down if (topLevel.childID != 0) { SFGfx.GameObject parentObject = SFGfx.GameObjects[topLevel.gameObjectCount]; stuffToAdd childNode = hierarchyTesting.SingleOrDefault(x => topLevel.childID == x.id); while (childNode.id != 0) { //Do the adding here SFGfx.GameObject gameObject = SFGfx.GameObjects[childNode.gameObjectCount]; gameObject.X += parentObject.X; gameObject.Y += parentObject.Y; gameObject.Z += parentObject.Z; gameObject.XRot += parentObject.XRot; gameObject.YRot += parentObject.YRot; gameObject.ZRot += parentObject.ZRot; SFGfx.GameObjects[childNode.gameObjectCount] = gameObject; if (childNode.siblingID != 0) { childNode = hierarchyTesting.SingleOrDefault(x => childNode.siblingID == x.id); } else { childNode.id = 0; } } } if (topLevel.siblingID != 0) { nextTopLevel.Enqueue(hierarchyTesting.SingleOrDefault(x => topLevel.siblingID == x.id)); } if (topLevel.childID != 0) { nextTopLevel.Enqueue(hierarchyTesting.SingleOrDefault(x => topLevel.childID == x.id)); } if (nextTopLevel.Count > 0) { topLevel = nextTopLevel.Dequeue(); } else { topLevel.id = 0; } } for (int j = hierarchyTesting.Count - 1; j >= 0; j--) { if (SFGfx.GameObjects[hierarchyTesting[j].gameObjectCount].DListOffset == 0x0) { SFGfx.GameObjects.RemoveAt(hierarchyTesting[j].gameObjectCount); SFGfx.GameObjCount--; } } ExecuteDisplayLists(); SFCamera.Reset(); }