public void readJointTable(string fname) { FileData d = new FileData(fname); d.Endian = Endianness.Big; int tableSize = 2; int table1 = d.readShort(); if (table1 * 2 + 2 >= d.size()) tableSize = 1; int table2 = -1; if (tableSize != 1) table2 = d.readShort(); //if (table2 == 0) // d.seek(d.pos() - 2); List<int> t1 = new List<int>(); for (int i = 0; i < table1; i++) t1.Add(d.readShort()); jointTable.Clear(); jointTable.Add(t1); if (tableSize != 1) { List<int> t2 = new List<int>(); for (int i = 0; i < table2; i++) t2.Add(d.readShort()); jointTable.Add(t2); } }
public void ReadParameters(FileData f, int count) { for (int i = 0; i < count; i++) { BCH_TextureParameter p = new BCH_TextureParameter() { Value = f.readInt() }; p.ParseParameter(f.readInt()); Nodes.Add(p); if (p.Id == BCH_TextureParameter.Parameter.texUnit0Size) { Width = p.GetHalf1(); Height = p.GetHalf2(); } if (p.Id == BCH_TextureParameter.Parameter.texUnit0Type) { type = p.Value; } if (p.Id == BCH_TextureParameter.Parameter.texUnit0Address) { data = f.getSection(p.Value, f.size() - p.Value); } } if (Width > 0 && Height > 0) { texture = _3DS.DecodeImage(data, Width, Height, (_3DS.Tex_Formats)type); //Texture glTex = new Texture2D(texture); //display = glTex.Id; } }
public void Read(FileData f) { f.Endian = endianess; if (f.size() < 4) { return; } int entryCount = f.readInt(); int otherCount = f.readInt(); int startOffset = f.readInt(); int unk = f.readInt(); //0x20 - Entry size? int unk2 = f.readInt(); //0x8? - values per entry? int unk3 = f.readInt(); //0x30? - start offset again? int otherStartOffset = f.readInt(); if (unk != 0x20 || unk2 != 0x8 || unk3 != 0x30) { throw new Exception("Unexpected Unkowns Please Report to Jam"); } f.seek(startOffset); for (int i = 0; i < entryCount; i++) { Entry temp = new Entry(); temp.values = new int[8]; for (int j = 0; j < 8; j++) { temp.values[j] = f.readInt(); } int returnOffset = f.pos(); f.seek(temp.values[0]); temp.name = f.readString(); f.seek(returnOffset); entries.Add(temp); } f.seek(otherStartOffset); for (int i = 0; i < otherCount; i++) { Entry temp = new Entry(); temp.values = new int[2]; for (int j = 0; j < 2; j++) { temp.values[j] = f.readInt(); } int returnOffset = f.pos(); f.seek(temp.values[0]); temp.name = f.readString(); f.seek(returnOffset); otherEntries.Add(temp); } }
public override void Read(string filename) { { { FileData d = new FileData(filename); var size1 = d.readShort(); if (size1 > 255) { d.seek(0); d.Endian = Endianness.Little; size1 = d.readShort(); } if (d.size() < 4) { return; } var size2 = d.readShort(); List <short> Table1 = new List <short>(); for (int i = 0; i < size1; i++) { if (d.pos() + 2 > d.size()) { break; } Table1.Add((short)d.readShort()); } List <short> Table2 = new List <short>(); for (int i = 0; i < size2; i++) { if (d.pos() + 2 > d.size()) { break; } Table2.Add((short)d.readShort()); } Tables = new List <List <short> >(); Tables.Add(Table1); Tables.Add(Table2); } } }
// temp stuff public static Dictionary <string, SkelAnimation> LoadAJ(string fname, VBN vbn) { // a note, I know that the main player file has the offsets for // animations, this is just for viewing FileData f = new FileData(fname); f.Endian = System.IO.Endianness.Big; int pos = 0; Dictionary <string, SkelAnimation> animations = new Dictionary <string, SkelAnimation>(); AnimationGroupNode group = new AnimationGroupNode() { Text = fname }; MainForm.Instance.animList.treeView1.Nodes.Add(group); while (pos < f.size()) { Console.WriteLine(pos.ToString("x")); int len = f.readInt(); DAT_Animation anim = new DAT_Animation(); anim.Read(new FileData(f.getSection(pos, len))); AnimTrack track = new AnimTrack(anim); if (pos == 0) { //track.Show(); } group.Nodes.Add(track.toAnimation(vbn)); SkelAnimation sa = track.BakeToSkel(vbn); //sa.Tag = track; //Runtime.Animations.Add(anim.Name, sa); // MainForm.Instance.animList.treeView1.Nodes.Add(anim.Name); animations.Add(anim.Name, sa); if (pos != 0) { track.Dispose(); track.Close(); } f.skip(len - 4); f.align(32); pos = f.pos(); } return(animations); }
public DDS(FileData d) { d.Endian = System.IO.Endianness.Little; d.seek(0); if (d.readUInt() != magic) { MessageBox.Show("The file does not appear to be a valid DDS file."); } header = new Header(); header.size = d.readUInt(); header.flags = d.readUInt(); header.height = d.readUInt(); header.width = d.readUInt(); header.pitchOrLinearSize = d.readUInt(); header.depth = d.readUInt(); header.mipmapCount = d.readUInt(); header.reserved1 = new uint[11]; for (int i = 0; i < 11; ++i) { header.reserved1[i] = d.readUInt(); } header.ddspf.size = d.readUInt(); header.ddspf.flags = d.readUInt(); header.ddspf.fourCC = d.readUInt(); header.ddspf.RGBBitCount = d.readUInt(); header.ddspf.RBitMask = d.readUInt(); header.ddspf.GBitMask = d.readUInt(); header.ddspf.BBitMask = d.readUInt(); header.ddspf.ABitMask = d.readUInt(); header.caps = d.readUInt(); header.caps2 = d.readUInt(); header.caps3 = d.readUInt(); header.caps4 = d.readUInt(); header.reserved2 = d.readUInt(); d.seek((int)(4 + header.size)); bdata = d.read(d.size() - d.pos()); }
public void read(FileData f) { f.Endian = Endian; if (f.size() < 4) { return; } f.seek(4); unknown = f.readUInt(); frameCount = f.readUInt(); startFrame = f.readUInt(); endFrame = f.readUInt(); frameRate = f.readUInt(); int matCount = f.readInt(); int matOffset = f.readInt(); int visCount = f.readInt(); int visOffset = f.readInt(); int returnPos; f.seek(matOffset); for (int i = 0; i < matCount; i++) { returnPos = f.pos() + 4; f.seek(f.readInt()); MatEntry tempMatEntry = new MatEntry(); tempMatEntry.read(f); matEntries.Add(tempMatEntry); f.seek(returnPos); } f.seek(visOffset); for (int i = 0; i < visCount; i++) { returnPos = f.pos() + 4; f.seek(f.readInt()); VisEntry tempVisEntry = new VisEntry(); tempVisEntry.read(f); visEntries.Add(tempVisEntry); f.seek(returnPos); } }
public DDS(FileData d) { d.Endian = System.IO.Endianness.Little; d.seek(0); header = new Header(); header.magic = new char[4]; header.magic [0] = (char)d.readByte(); header.magic [1] = (char)d.readByte(); header.magic [2] = (char)d.readByte(); header.magic [3] = (char)d.readByte(); header.size = d.readInt(); header.flags = d.readInt(); header.height = d.readInt(); header.width = d.readInt(); header.pitchOrLinear = d.readInt(); header.depth = d.readInt(); header.mipmapCount = d.readInt(); header.reserved = new int[11]; for (int i = 0; i < 11; i++) { header.reserved [i] = d.readInt(); } header.dwSize = d.readInt(); header.dwFlags = d.readInt(); header.dwFourCC = d.readInt(); header.dwBitmask = d.readInt(); header.dwCaps = (uint)d.readInt(); header.dwCaps2 = (uint)d.readInt(); header.dwCaps3 = (uint)d.readInt(); header.dwCaps4 = (uint)d.readInt(); header.reserve = d.readInt(); d.skip(16); // not needed another header data = new byte[d.size() - d.pos()]; for (int i = 0; i < data.Length; i++) { data [i] = (byte)d.readByte(); } }
public void OpenTEX(string fname) { Edited = true; FileData d = new FileData(fname); d.Endian = System.IO.Endianness.Little; int width = d.readInt(); int height = d.readInt(); int type = d.readByte(); int dunno = d.readByte(); d.skip(2); // padding string name = ""; int i = d.readByte(); while (i != 0x00) { name += (char)i; i = d.readByte(); } if (type > 0xD || type < 0) { return; } nameBox.Text = name; formatSelector.SelectedIndex = type; label3.Text = "Width: " + width; label4.Text = "Height: " + height; byte[] data = d.getSection(0x80, d.size() - 0x80); pictureBox1.Image = _3DS.DecodeImage(data, width, height, (_3DS.Tex_Formats)type); pictureBox1.Image.RotateFlip(RotateFlipType.RotateNoneFlipY); }
public void read(FileData f) { f.Endian = Endian; if (f.size() < 4) { throw new EndOfStreamException("Blank/Broken MTA"); } f.seek(4); unknown = (uint)f.readInt(); numFrames = (uint)f.readInt(); f.skip(8); frameRate = (uint)f.readInt(); int matCount = f.readInt(); int matOffset = f.readInt(); int visCount = f.readInt(); int visOffset = f.readInt(); int returnPos; f.seek(matOffset); for (int i = 0; i < matCount; i++) { returnPos = f.pos() + 4; f.seek(f.readInt()); MatEntry tempMatEntry = new MatEntry(); tempMatEntry.read(f); matEntries.Add(tempMatEntry); f.seek(returnPos); } f.seek(visOffset); for (int i = 0; i < visCount; i++) { returnPos = f.pos() + 4; f.seek(f.readInt()); VisEntry tempVisEntry = new VisEntry(); tempVisEntry.read(f); visEntries.Add(tempVisEntry); f.seek(returnPos); } }
public override void Read(string filename) { bchHeader header = new bchHeader(); FileData f = new FileData(filename); f.Endian = System.IO.Endianness.Little; f.skip(4); header.backwardCompatibility = f.readByte(); header.forwardCompatibility = f.readByte(); header.version = f.readUShort(); header.mainHeaderOffset = f.readInt(); header.stringTableOffset = f.readInt(); header.gpuCommandsOffset = f.readInt(); header.dataOffset = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedOffset = f.readInt(); } header.relocationTableOffset = f.readInt(); header.mainHeaderLength = f.readInt(); header.stringTableLength = f.readInt(); header.gpuCommandsLength = f.readInt(); header.dataLength = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedLength = f.readInt(); } header.relocationTableLength = f.readInt(); header.uninitializedDataSectionLength = f.readInt(); header.uninitializedDescriptionSectionLength = f.readInt(); if (header.backwardCompatibility > 7) { header.flags = f.readUShort(); header.addressCount = f.readUShort(); } // Relocation table for (int i = 0; i < header.relocationTableLength; i += 4) { f.seek(header.relocationTableOffset + i); int val = f.readInt(); int off = val & 0x1FFFFFF; byte flag = (byte)(val >> 25); switch (flag) { case 0: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset); break; case 1: f.seek(off + header.mainHeaderOffset); f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset); break; case 2: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset); break; case 0xc: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; } f.seek((off * 4) + header.gpuCommandsOffset); if (header.backwardCompatibility < 6) { switch (flag) { case 0x23: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, ((f.readInt() + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (header.backwardCompatibility < 8) { switch (flag) { case 0x24: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (header.backwardCompatibility < 0x21) { switch (flag) { case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x28: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x29: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else { switch (flag) { case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex relative to Data Offset //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset case 0x2b: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataExtendedOffset); break; //Vertex relative to Data Extended Offset //case 0x2c: writer.Write(((peek(input) + header.dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset case 0x2d: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataExtendedOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Extended Offset } } } // Content Header f.seek(header.mainHeaderOffset); bchContentHeader content = new bchContentHeader(); { content.modelsPointerTableOffset = f.readInt(); content.modelsPointerTableEntries = f.readInt(); content.modelsNameOffset = f.readInt(); content.materialsPointerTableOffset = f.readInt(); content.materialsPointerTableEntries = f.readInt(); content.materialsNameOffset = f.readInt(); content.shadersPointerTableOffset = f.readInt(); content.shadersPointerTableEntries = f.readInt(); content.shadersNameOffset = f.readInt(); content.texturesPointerTableOffset = f.readInt(); content.texturesPointerTableEntries = f.readInt(); content.texturesNameOffset = f.readInt(); content.materialsLUTPointerTableOffset = f.readInt(); content.materialsLUTPointerTableEntries = f.readInt(); content.materialsLUTNameOffset = f.readInt(); content.lightsPointerTableOffset = f.readInt(); content.lightsPointerTableEntries = f.readInt(); content.lightsNameOffset = f.readInt(); content.camerasPointerTableOffset = f.readInt(); content.camerasPointerTableEntries = f.readInt(); content.camerasNameOffset = f.readInt(); content.fogsPointerTableOffset = f.readInt(); content.fogsPointerTableEntries = f.readInt(); content.fogsNameOffset = f.readInt(); content.skeletalAnimationsPointerTableOffset = f.readInt(); content.skeletalAnimationsPointerTableEntries = f.readInt(); content.skeletalAnimationsNameOffset = f.readInt(); content.materialAnimationsPointerTableOffset = f.readInt(); content.materialAnimationsPointerTableEntries = f.readInt(); content.materialAnimationsNameOffset = f.readInt(); content.visibilityAnimationsPointerTableOffset = f.readInt(); content.visibilityAnimationsPointerTableEntries = f.readInt(); content.visibilityAnimationsNameOffset = f.readInt(); content.lightAnimationsPointerTableOffset = f.readInt(); content.lightAnimationsPointerTableEntries = f.readInt(); content.lightAnimationsNameOffset = f.readInt(); content.cameraAnimationsPointerTableOffset = f.readInt(); content.cameraAnimationsPointerTableEntries = f.readInt(); content.cameraAnimationsNameOffset = f.readInt(); content.fogAnimationsPointerTableOffset = f.readInt(); content.fogAnimationsPointerTableEntries = f.readInt(); content.fogAnimationsNameOffset = f.readInt(); content.scenePointerTableOffset = f.readInt(); content.scenePointerTableEntries = f.readInt(); content.sceneNameOffset = f.readInt(); } //Skeletal animation for (int index1 = 0; index1 < content.skeletalAnimationsPointerTableEntries; index1++) { f.seek(content.skeletalAnimationsPointerTableOffset + (index1 * 4)); int dataOffset = f.readInt(); f.seek(dataOffset); string skeletalAnimationName = f.readString(f.readInt(), -1); int animationFlags = f.readInt(); //int skeletalAnimationloopMode = f.readByte(); //pas ça du tout float skeletalAnimationframeSize = f.readFloat(); int boneTableOffset = f.readInt(); int boneTableEntries = f.readInt(); int metaDataPointerOffset = f.readInt(); //Debug.WriteLine("Animation Name: " + skeletalAnimationName); //Debug.WriteLine("BonetableOffset: " + boneTableOffset.ToString("X")); //Debug.WriteLine("BonetableEntry: " + boneTableEntries.ToString("X")); for (int i = 0; i < boneTableEntries; i++) { f.seek(boneTableOffset + (i * 4)); int offset = f.readInt(); OSkeletalAnimationBone bone = new OSkeletalAnimationBone(); f.seek(offset); bone.name = f.readString(f.readInt(), -1); Console.WriteLine("Bone Name: " + bone.name); int animationTypeFlags = f.readInt(); int flags = f.readInt(); OSegmentType segmentType = (OSegmentType)((animationTypeFlags >> 16) & 0xf); switch (segmentType) { case OSegmentType.transform: f.seek(offset + 0x18); int notExistMask = 0x80000; int constantMask = 0x200; for (int j = 0; j < 2; j++) { for (int axis = 0; axis < 3; axis++) { bool notExist = (flags & notExistMask) > 0; bool constant = (flags & constantMask) > 0; OAnimationKeyFrameGroup frame = new OAnimationKeyFrameGroup(); frame.exists = !notExist; if (frame.exists) { if (constant) { frame.interpolation = OInterpolationMode.linear; frame.keyFrames.Add(new OAnimationKeyFrame(f.readFloat(), 0)); } else { int frameOffset = f.readInt(); int position = f.pos(); f.seek(frameOffset); //getAnimationKeyFrame(input, frame); f.seek(position); } } else { f.seek(f.pos() + 0x04); } if (j == 0) { switch (axis) { case 0: bone.rotationX = frame; break; case 1: bone.rotationY = frame; break; case 2: bone.rotationZ = frame; break; } } else { switch (axis) { case 0: bone.translationX = frame; break; case 1: bone.translationY = frame; break; case 2: bone.translationZ = frame; break; } } notExistMask <<= 1; constantMask <<= 1; } constantMask <<= 1; } break; case OSegmentType.transformQuaternion: bone.isFrameFormat = true; int scaleOffset = f.readInt(); int rotationOffset = f.readInt(); int translationOffset = f.readInt(); if ((flags & 0x20) == 0) { bone.scale.exists = true; f.seek(scaleOffset); if ((flags & 4) > 0) { bone.scale.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), 0)); } else { bone.scale.startFrame = f.readFloat(); bone.scale.endFrame = f.readFloat(); int scaleFlags = f.readInt(); int scaleDataOffset = f.readInt(); int scaleEntries = f.readInt(); f.seek(scaleDataOffset); for (int j = 0; j < scaleEntries; j++) { bone.scale.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), 0)); } } } if ((flags & 0x10) == 0) { bone.rotationQuaternion.exists = true; f.seek(rotationOffset); if ((flags & 2) > 0) { bone.rotationQuaternion.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat())); } else { bone.rotationQuaternion.startFrame = f.readFloat(); bone.rotationQuaternion.endFrame = f.readFloat(); int rotationFlags = f.readInt(); int rotationDataOffset = f.readInt(); int rotationEntries = f.readInt(); f.seek(rotationDataOffset); for (int j = 0; j < rotationEntries; j++) { bone.rotationQuaternion.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat())); } } } if ((flags & 8) == 0) { bone.translation.exists = true; f.seek(translationOffset); if ((flags & 1) > 0) { bone.translation.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), 0)); } else { bone.translation.startFrame = f.readFloat(); bone.translation.endFrame = f.readFloat(); int translationFlags = f.readInt(); int translationDataOffset = f.readInt(); int translationEntries = f.readInt(); f.seek(translationDataOffset); for (int j = 0; j < translationEntries; j++) { bone.translation.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), 0)); } } } break; case OSegmentType.transformMatrix: bone.isFullBakedFormat = true; f.readInt(); f.readInt(); int matrixOffset = f.readInt(); int entries = f.readInt(); f.seek(matrixOffset); for (int j = 0; j < entries; j++) { /*OMatrix transform = new OMatrix(); * transform.M11 = f.readFloat(); * transform.M21 = f.readFloat(); * transform.M31 = f.readFloat(); * transform.M41 = f.readFloat(); * * transform.M12 = f.readFloat(); * transform.M22 = f.readFloat(); * transform.M32 = f.readFloat(); * transform.M42 = f.readFloat(); * * transform.M13 = f.readFloat(); * transform.M23 = f.readFloat(); * transform.M33 = f.readFloat(); * transform.M43 = f.readFloat(); * * bone.transform.Add(transform);*/ } break; default: throw new Exception(string.Format("BCH: Unknow Segment Type {0} on Skeletal Animation bone {1}! STOP!", segmentType, bone.name)); } //skeletalAnimation.bone.Add(bone); } } //Shaders (unused for now, until someone wants to add them) for (int index = 0; index < content.shadersPointerTableEntries; index++) { f.seek(content.shadersPointerTableOffset + (index * 4)); int dataOffset = f.readInt(); f.seek(dataOffset); int shaderDataOffset = f.readInt(); int shaderDataLength = f.readInt(); } // Textures // WIP Section for (int index = 0; index < content.texturesPointerTableEntries; index++) { f.seek(content.texturesPointerTableOffset + (index * 4)); int dOffset = f.readInt(); f.seek(dOffset); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); f.seek(f.pos() + 0x14); String textureName = f.readString(f.readInt(), -1); f.seek(textureCommandsOffset); BCH_Texture tex = new BCH_Texture(); textures.Add(textureName, tex); tex.Height = f.readUShort(); tex.Width = f.readUShort(); f.skip(12); int doffset = f.readInt(); f.skip(4); tex.type = f.readInt(); tex.data = f.getSection(doffset, f.size() - doffset); tex.texture = _3DS.DecodeImage(tex.data, tex.Width, tex.Height, (_3DS.Tex_Formats)tex.type); //Texture texture = new Texture2D(tex.texture); //tex.display = texture.Id; } // Model data for (int modelIndex = 0; modelIndex < content.modelsPointerTableEntries; modelIndex++) { f.seek(content.modelsPointerTableOffset + (modelIndex * 4)); int objectsHeaderOffset = f.readInt(); // Objects f.seek(objectsHeaderOffset); BCH_Model model = new BCH_Model(); models.Add(model); model.flags = f.readByte(); model.skeletonScaleType = f.readByte(); model.silhouetteMaterialEntries = f.readUShort(); model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , 0, 0, 0, 1); int materialsTableOffset = f.readInt(); int materialsTableEntries = f.readInt(); int materialsNameOffset = f.readInt(); int verticesTableOffset = f.readInt(); int verticesTableEntries = f.readInt(); f.skip(0x28); int skeletonOffset = f.readInt(); int skeletonEntries = f.readInt(); int skeletonNameOffset = f.readInt(); int objectsNodeVisibilityOffset = f.readInt(); int objectsNodeCount = f.readInt(); String name = f.readString(f.readInt(), -1); int objectsNodeNameEntries = f.readInt(); int objectsNodeNameOffset = f.readInt(); f.readInt(); //0x0 int metaDataPointerOffset = f.readInt(); f.seek(objectsNodeVisibilityOffset); int nodeVisibility = f.readInt(); string[] objectName = new string[objectsNodeNameEntries]; f.seek(objectsNodeNameOffset); int rootReferenceBit = f.readInt(); //Radix tree int rootLeftNode = f.readUShort(); int rootRightNode = f.readUShort(); int rootNameOffset = f.readInt(); for (int i = 0; i < objectsNodeNameEntries; i++) { int referenceBit = f.readInt(); short leftNode = f.readShort(); short rightNode = f.readShort(); objectName[i] = f.readString(f.readInt(), -1); } // Materials // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM String[] materialNames = new String[materialsTableEntries]; for (int index = 0; index < materialsTableEntries; index++) { f.seek(materialsTableOffset + (index * 0x2c)); int materialParametersOffset = f.readInt(); f.readInt(); f.readInt(); f.readInt(); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); int materialMapperOffset = f.readInt(); materialNames[index] = f.readString(f.readInt(), -1); } // Object Descriptions... // Assumes MBN is already loaded for now f.seek(verticesTableOffset); List <objDes> objDescriptors = new List <objDes>(); if (mbn == null) { mbn = new Smash_Forge.MBN(); for (int index = 0; index < verticesTableEntries; index++) { mbn.mesh.Add(new MBN.Mesh()); } mbn.PreRender(); } for (int index = 0; index < mbn.mesh.Count; index++) { int i = f.readUShort(); if (index > mbn.mesh.Count) { break; } if (i > materialNames.Length) { break; } mbn.mesh[index].texId = textures[materialNames[i]].display; Console.WriteLine("Tex index" + mbn.mesh[index].texId); f.skip(2); // flags int nameId = f.readUShort(); mbn.mesh[index].Text = objectName[nameId]; // node visibility TODO: finish... mbn.mesh[index].Checked = ((nodeVisibility & (1 << nameId)) > 0); mbn.mesh[index].renderPriority = f.readUShort(); objDes des = new objDes(); objDescriptors.Add(des); des.vshAttBufferCommandOffset = f.readInt(); des.vshAttBufferCommandCount = f.readInt(); des.faceOffset = f.readInt(); des.faceCount = f.readInt(); des.vshAttBufferCommandOffsetEx = f.readInt(); des.vshAttBufferCommandCountEx = f.readInt(); f.skip(12); // center vector f.skip(4); // flagsOffset f.skip(4); // 0? f.readInt(); //bbOffsets[i] } //Skeleton f.seek(skeletonOffset); for (int index = 0; index < skeletonEntries; index++) { Bone bone = new Bone(model.skeleton); int boneFlags = f.readInt(); bone.parentIndex = f.readShort(); short boneSpace = f.readShort(); bone.scale = new float[3]; bone.rotation = new float[3]; bone.position = new float[3]; bone.scale[0] = f.readFloat(); bone.scale[1] = f.readFloat(); bone.scale[2] = f.readFloat(); bone.rotation[0] = f.readFloat(); bone.rotation[1] = f.readFloat(); bone.rotation[2] = f.readFloat(); bone.position[0] = f.readFloat(); bone.position[1] = f.readFloat(); bone.position[2] = f.readFloat(); // bone matrix... not really needed to be stored per say f.skip(4 * 4 * 3); bone.Text = f.readString(f.readInt(), -1); f.skip(4); // Meta data bones.bones.Add(bone); model.skeleton.bones.Add(bone); } model.skeleton.reset(); model.skeleton.update(); } }
public override void Read(string filename) { FileData f = new FileData(filename); f.Endian = System.IO.Endianness.Little; f.skip(8); int mainHeaderOffset = f.readInt(); int stringTableOffset = f.readInt(); int gpuCommandOffset = f.readInt(); int dataOffset = f.readInt(); int dataExtendOffset = f.readInt(); int relocationTableOffset = f.readInt(); int mainHeaderLength = f.readInt(); int stringTableLength = f.readInt(); int gpuCommandLength = f.readInt(); int dataLength = f.readInt(); int dataExtendLength = f.readInt(); int relocationTableLength = f.readInt(); int datsSecLength = f.readInt(); int desSecLength = f.readInt(); int flags = f.readShort(); int addressCount = f.readShort(); // TODO: Finished Relocation table stuff for (int i = 0; i < relocationTableLength; i += 4) { f.seek(relocationTableOffset + i); int val = f.readInt(); int off = val & 0x1FFFFFF; byte flag = (byte)(val >> 25); switch (flag) { case 0: f.seek((off * 4) + mainHeaderOffset); break; } } // Content Header f.seek(mainHeaderOffset); int modelsPointerTableOffset = f.readInt() + mainHeaderOffset; int modelsPointerTableEntries = f.readInt(); int modelsNameOffset = f.readInt() + mainHeaderOffset; int materialsPointerTableOffset = f.readInt() + mainHeaderOffset; int materialsPointerTableEntries = f.readInt(); int materialsNameOffset = f.readInt() + mainHeaderOffset; int shadersPointerTableOffset = f.readInt() + mainHeaderOffset; int shadersPointerTableEntries = f.readInt(); int shadersNameOffset = f.readInt() + mainHeaderOffset; int texturesPointerTableOffset = f.readInt() + mainHeaderOffset; int texturesPointerTableEntries = f.readInt(); int texturesNameOffset = f.readInt() + mainHeaderOffset; int materialsLUTPointerTableOffset = f.readInt() + mainHeaderOffset; int materialsLUTPointerTableEntries = f.readInt(); int materialsLUTNameOffset = f.readInt() + mainHeaderOffset; int lightsPointerTableOffset = f.readInt() + mainHeaderOffset; int lightsPointerTableEntries = f.readInt(); int lightsNameOffset = f.readInt() + mainHeaderOffset; int camerasPointerTableOffset = f.readInt() + mainHeaderOffset; int camerasPointerTableEntries = f.readInt(); int camerasNameOffset = f.readInt() + mainHeaderOffset; int fogsPointerTableOffset = f.readInt() + mainHeaderOffset; int fogsPointerTableEntries = f.readInt(); int fogsNameOffset = f.readInt() + mainHeaderOffset; int skeletalAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int skeletalAnimationsPointerTableEntries = f.readInt(); int skeletalAnimationsNameOffset = f.readInt() + mainHeaderOffset; int materialAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int materialAnimationsPointerTableEntries = f.readInt(); int materialAnimationsNameOffset = f.readInt() + mainHeaderOffset; int visibilityAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int visibilityAnimationsPointerTableEntries = f.readInt(); int visibilityAnimationsNameOffset = f.readInt() + mainHeaderOffset; int lightAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int lightAnimationsPointerTableEntries = f.readInt(); int lightAnimationsNameOffset = f.readInt() + mainHeaderOffset; int cameraAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int cameraAnimationsPointerTableEntries = f.readInt(); int cameraAnimationsNameOffset = f.readInt() + mainHeaderOffset; int fogAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int fogAnimationsPointerTableEntries = f.readInt(); int fogAnimationsNameOffset = f.readInt() + mainHeaderOffset; int scenePointerTableOffset = f.readInt() + mainHeaderOffset; int scenePointerTableEntries = f.readInt(); int sceneNameOffset = f.readInt() + mainHeaderOffset; // Textures // WIP Section for (int index = 0; index < texturesPointerTableEntries; index++) { f.seek(texturesPointerTableOffset + (index * 4)); int dOffset = f.readInt(); f.seek(dOffset + mainHeaderOffset); int textureCommandsOffset = f.readInt() + gpuCommandOffset; int textureCommandsWordCount = f.readInt(); f.seek(f.pos() + 0x14); String textureName = f.readString(f.readInt() + stringTableOffset, -1); f.seek(textureCommandsOffset); BCH_Texture tex = new BCH_Texture(); textures.Add(textureName, tex); tex.height = f.readShort(); tex.width = f.readShort(); f.skip(12); int doffset = f.readInt() + dataOffset; f.skip(4); tex.type = f.readInt(); tex.data = f.getSection(doffset, f.size() - doffset); if (tex.type == 12) { tex.display = NUT.loadImage(Pixel.decodeETC(tex.data, tex.width, tex.height)); } } // Model data for (int modelIndex = 0; modelIndex < modelsPointerTableEntries; modelIndex++) { f.seek(modelsPointerTableOffset + (modelIndex * 4)); int objectsHeaderOffset = f.readInt() + mainHeaderOffset; // Objects f.seek(objectsHeaderOffset); BCH_Model model = new BCH_Model(); models.Add(model); model.flags = f.readByte(); model.skeletonScaleType = f.readByte(); model.silhouetteMaterialEntries = f.readShort(); model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , 0, 0, 0, 1); int materialsTableOffset = f.readInt() + mainHeaderOffset; int materialsTableEntries = f.readInt(); int materialsNamesOffset = f.readInt() + mainHeaderOffset; int verticesTableOffset = f.readInt() + mainHeaderOffset; //Debug.WriteLine("Mesh Count: " + f.pos().ToString("X")); int verticesTableEntries = f.readInt(); f.skip(0x28); int skeletonOffset = f.readInt() + mainHeaderOffset; int skeletonEntries = f.readInt(); int skeletonNameOffset = f.readInt() + mainHeaderOffset; int objectsNodeVisibilityOffset = f.readInt() + mainHeaderOffset; int objectsNodeCount = f.readInt(); model.name = f.readString(f.readInt() + stringTableOffset, -1); int objectsNodeNameEntries = f.readInt(); int objectsNodeNameOffset = f.readInt() + mainHeaderOffset; f.readInt(); //0x0 int metaDataPointerOffset = f.readInt() + mainHeaderOffset; f.seek(objectsNodeVisibilityOffset); int nodeVisibility = f.readInt(); string[] objectName = new string[objectsNodeNameEntries]; f.seek(objectsNodeNameOffset); int rootReferenceBit = f.readInt(); //Radix tree int rootLeftNode = f.readShort(); int rootRightNode = f.readShort(); int rootNameOffset = f.readInt() + mainHeaderOffset; for (int i = 0; i < objectsNodeNameEntries; i++) { int referenceBit = f.readInt(); short leftNode = (short)f.readShort(); short rightNode = (short)f.readShort(); objectName[i] = f.readString(f.readInt() + stringTableOffset, -1); //Debug.WriteLine(objectName[i]); } // Materials // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM String[] materialNames = new String[materialsTableEntries]; for (int index = 0; index < materialsTableEntries; index++) { f.seek(materialsTableOffset + (index * 0x2c)); int materialParametersOffset = f.readInt(); f.readInt(); f.readInt(); f.readInt(); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); int materialMapperOffset = f.readInt(); materialNames[index] = f.readString(f.readInt() + stringTableOffset, -1); } // Object Descriptions... // Assumes MBN is already loaded for now f.seek(verticesTableOffset); List <objDes> objDescriptors = new List <objDes>(); Debug.WriteLine(model.name); if (mbn == null) { mbn = new Smash_Forge.MBN(); for (int index = 0; index < verticesTableEntries; index++) { mbn.mesh.Add(new MBN.Mesh()); } mbn.PreRender(); } for (int index = 0; index < mbn.mesh.Count; index++) { int i = f.readShort(); if (index > mbn.mesh.Count) { break; } if (i > materialNames.Length) { break; } mbn.mesh[index].texId = textures[materialNames[i]].display; f.skip(2); // flags int nameId = f.readShort(); mbn.mesh[index].name = objectName[nameId]; // node visibility TODO: finish... //mbn.mesh[index].isVisible = ((nodeVisibility & (1 << nameId)) > 0); mbn.mesh[index].renderPriority = f.readShort(); objDes des = new objDes(); objDescriptors.Add(des); des.vshAttBufferCommandOffset = f.readInt() + mainHeaderOffset; des.vshAttBufferCommandCount = f.readInt(); des.faceOffset = f.readInt() + mainHeaderOffset; des.faceCount = f.readInt(); des.vshAttBufferCommandOffsetEx = f.readInt() + mainHeaderOffset; des.vshAttBufferCommandCountEx = f.readInt(); f.skip(12); // center vector f.skip(4); // flagsOffset f.skip(4); // 0? f.readInt(); //bbOffsets[i] = + mainheaderOffset //Debug.WriteLine(des.vshAttBufferCommandOffset.ToString("X")); } //Skeleton f.seek(skeletonOffset); for (int index = 0; index < skeletonEntries; index++) { Bone bone = new Smash_Forge.Bone(model.skeleton); int boneFlags = f.readInt(); bone.parentIndex = (short)f.readShort(); short boneSpace = (short)f.readShort(); bone.scale = new float[3]; bone.rotation = new float[3]; bone.position = new float[3]; bone.scale[0] = f.readFloat(); bone.scale[1] = f.readFloat(); bone.scale[2] = f.readFloat(); bone.rotation[0] = f.readFloat(); bone.rotation[1] = f.readFloat(); bone.rotation[2] = f.readFloat(); bone.position[0] = f.readFloat(); bone.position[1] = f.readFloat(); bone.position[2] = f.readFloat(); // bone matrix... not really needed to be stored per say f.skip(4 * 4 * 3); bone.boneName = f.readString(f.readInt() + stringTableOffset, -1).ToCharArray(); f.skip(4); // Meta data model.skeleton.bones.Add(bone); } model.skeleton.reset(); } }
public override void Read(string filename) { FileData f = new FileData(filename); f.Endian = System.IO.Endianness.Little; f.skip(4); int backwardCompatibility = f.readByte(); int forwardCompatibility = f.readByte(); int version = f.readShort(); int mainHeaderOffset = f.readInt(); int stringTableOffset = f.readInt(); int gpuCommandsOffset = f.readInt(); int dataOffset = f.readInt(); int dataExtendedOffset = 0; int dataExtendedLength = 0; if (backwardCompatibility > 0x20) { dataExtendedOffset = f.readInt(); } int relocationTableOffset = f.readInt(); int mainHeaderLength = f.readInt(); int stringTableLength = f.readInt(); int gpuCommandsLength = f.readInt(); int dataLength = f.readInt(); if (backwardCompatibility > 0x20) { dataExtendedLength = f.readInt(); } int relocationTableLength = f.readInt(); int uninitializedDataSectionLength = f.readInt(); int uninitializedDescriptionSectionLength = f.readInt(); if (backwardCompatibility > 7) { int flags = f.readShort(); int addressCount = f.readShort(); } // Relocation table for (int i = 0; i < relocationTableLength; i += 4) { f.seek(relocationTableOffset + i); int val = f.readInt(); int off = val & 0x1FFFFFF; byte flag = (byte)(val >> 25); switch (flag) { case 0: f.seek((off * 4) + mainHeaderOffset); f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + mainHeaderOffset); break; case 1: f.seek(off + mainHeaderOffset); f.writeInt((off) + mainHeaderOffset, f.readInt() + stringTableOffset); break; case 2: f.seek((off * 4) + mainHeaderOffset); f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + gpuCommandsOffset); break; case 0xc: f.seek((off * 4) + mainHeaderOffset); f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + dataOffset); break; } f.seek((off * 4) + gpuCommandsOffset); if (backwardCompatibility < 6) { switch (flag) { case 0x23: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Texture case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Vertex //case 0x26: f.writeInt((off * 4) + int gpuCommandsOffset, ((f.readInt() + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x27: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (backwardCompatibility < 8) { switch (flag) { case 0x24: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Vertex //case 0x27: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x28: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (backwardCompatibility < 0x21) { switch (flag) { case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Texture case 0x27: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Vertex //case 0x28: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x29: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else { switch (flag) { case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Vertex relative to Data Offset //case 0x27: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset case 0x28: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset case 0x2b: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataExtendedOffset); break; //Vertex relative to Data Extended Offset //case 0x2c: writer.Write(((peek(input) + int dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset case 0x2d: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataExtendedOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Extended Offset } } } File.WriteAllBytes(filename + "_offset", f.getSection(0, f.size())); f.seek(mainHeaderOffset); int modelsPointerTableOffset = f.readInt(); int modelsPointerTableEntries = f.readInt(); int modelsNameOffset = f.readInt(); int materialsPointerTableOffset = f.readInt(); int materialsPointerTableEntries = f.readInt(); int materialsNameOffset = f.readInt(); int shadersPointerTableOffset = f.readInt(); int shadersPointerTableEntries = f.readInt(); int shadersNameOffset = f.readInt(); int texturesPointerTableOffset = f.readInt(); int texturesPointerTableEntries = f.readInt(); int texturesNameOffset = f.readInt(); int materialsLUTPointerTableOffset = f.readInt(); int materialsLUTPointerTableEntries = f.readInt(); int materialsLUTNameOffset = f.readInt(); int lightsPointerTableOffset = f.readInt(); int lightsPointerTableEntries = f.readInt(); int lightsNameOffset = f.readInt(); int camerasPointerTableOffset = f.readInt(); int camerasPointerTableEntries = f.readInt(); int camerasNameOffset = f.readInt(); int fogsPointerTableOffset = f.readInt(); int fogsPointerTableEntries = f.readInt(); int fogsNameOffset = f.readInt(); int skeletalAnimationsPointerTableOffset = f.readInt(); int skeletalAnimationsPointerTableEntries = f.readInt(); int skeletalAnimationsNameOffset = f.readInt(); int materialAnimationsPointerTableOffset = f.readInt(); int materialAnimationsPointerTableEntries = f.readInt(); int materialAnimationsNameOffset = f.readInt(); int visibilityAnimationsPointerTableOffset = f.readInt(); int visibilityAnimationsPointerTableEntries = f.readInt(); int visibilityAnimationsNameOffset = f.readInt(); int lightAnimationsPointerTableOffset = f.readInt(); int lightAnimationsPointerTableEntries = f.readInt(); int lightAnimationsNameOffset = f.readInt(); int cameraAnimationsPointerTableOffset = f.readInt(); int cameraAnimationsPointerTableEntries = f.readInt(); int cameraAnimationsNameOffset = f.readInt(); int fogAnimationsPointerTableOffset = f.readInt(); int fogAnimationsPointerTableEntries = f.readInt(); int fogAnimationsNameOffset = f.readInt(); int scenePointerTableOffset = f.readInt(); int scenePointerTableEntries = f.readInt(); int sceneNameOffset = f.readInt(); Console.WriteLine(modelsPointerTableEntries > 0 ? "Has Models" : ""); Console.WriteLine(shadersPointerTableEntries > 0 ? "Has Shaders" : ""); Console.WriteLine(texturesPointerTableEntries > 0 ? "Has Textures" : ""); Console.WriteLine(materialsPointerTableEntries > 0 ? "Has Materials" : ""); Console.WriteLine(materialsLUTPointerTableEntries > 0 ? "Has Material LUT" : ""); Console.WriteLine(materialAnimationsPointerTableEntries > 0 ? "Has Material Animation" : ""); Console.WriteLine(lightsPointerTableEntries > 0 ? "Has Lights" : ""); Console.WriteLine(lightAnimationsPointerTableEntries > 0 ? "Has LightAnimations" : ""); Console.WriteLine(camerasPointerTableEntries > 0 ? "Has Camera" : ""); Console.WriteLine(cameraAnimationsPointerTableEntries > 0 ? "Has CameraAnimation" : ""); Console.WriteLine(fogsPointerTableEntries > 0 ? "Has Fog" : ""); Console.WriteLine(fogAnimationsPointerTableEntries > 0 ? "Has FogAnimation" : ""); Console.WriteLine(skeletalAnimationsPointerTableEntries > 0 ? "Has Skeletal Animations" : ""); Console.WriteLine(visibilityAnimationsPointerTableEntries > 0 ? "Has Visibility" : ""); Console.WriteLine(scenePointerTableEntries > 0 ? "Has Scene" : ""); // Textures for (int index = 0; index < texturesPointerTableEntries; index++) { f.seek(texturesPointerTableOffset + (index * 4)); int dOffset = f.readInt(); f.seek(dOffset); // one for each mip I assume int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); int textureCommandsOffset2 = f.readInt(); int textureCommandsWordCount2 = f.readInt(); int textureCommandsOffset3 = f.readInt(); int textureCommandsWordCount3 = f.readInt(); int unk = f.readInt(); BCH_Texture tex = new BCH_Texture(); tex.Text = f.readString(f.readInt(), -1); Textures.Nodes.Add(tex); f.seek(textureCommandsOffset); tex.ReadParameters(f, textureCommandsWordCount); } //Models for (int index = 0; index < modelsPointerTableEntries; index++) { f.seek(modelsPointerTableOffset + (index * 4)); f.seek(f.readInt()); BCH_Model model = new BCH_Model(); Models.Nodes.Add(model); model.flags = f.readByte(); model.skeletonScaleType = f.readByte(); model.silhouetteMaterialEntries = f.readShort(); model.worldTransform = new OpenTK.Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , 0, 0, 0, 1); int materialsTableOffset = f.readInt(); int materialsTableEntries = f.readInt(); int materialNameOffset = f.readInt(); int verticesTableOffset = f.readInt(); int verticesTableEntries = f.readInt(); f.skip(0x28); int skeletonOffset = f.readInt(); int skeletonEntries = f.readInt(); int skeletonNameOffset = f.readInt(); int objectsNodeVisibilityOffset = f.readInt(); int objectsNodeCount = f.readInt(); model.Text = f.readString(f.readInt(), -1); int objectsNodeNameEntries = f.readInt(); int objectsNodeNameOffset = f.readInt(); f.readInt(); //0x0 int metaDataPointerOffset = f.readInt(); f.seek(objectsNodeVisibilityOffset); int nodeVisibility = f.readInt(); string[] objectName = new string[objectsNodeNameEntries]; f.seek(objectsNodeNameOffset); int rootReferenceBit = f.readInt(); int rootLeftNode = f.readShort(); int rootRightNode = f.readShort(); int rootNameOffset = f.readInt(); Console.WriteLine(f.readString(rootNameOffset, -1) + " " + rootLeftNode + " " + rootRightNode); // Object name tree for (int i = 0; i < objectsNodeNameEntries; i++) { int referenceBit = f.readInt(); short leftNode = (short)f.readShort(); short rightNode = (short)f.readShort(); objectName[i] = f.readString(f.readInt(), -1); Console.WriteLine(i + " " + objectName[i] + " " + leftNode + " " + rightNode); } //TODO: Metadata, boundingbox, normal mesh, materials f.seek(verticesTableOffset); for (int i = 0; i < verticesTableEntries; i++) { BCH_Mesh Mesh = new BCH_Mesh(); model.Nodes.Add(Mesh); Mesh.MaterialIndex = f.readShort(); int mflags = f.readShort(); int nameId = f.readShort(); Mesh.Text = objectName[nameId]; // node visibility TODO: finish... Mesh.Checked = ((nodeVisibility & (1 << nameId)) > 0); Mesh.renderPriority = f.readShort(); int vshAttBufferCommandOffset = f.readInt(); int vshAttBufferCommandCount = f.readInt(); int faceOffset = f.readInt(); int faceCount = f.readInt(); int vshAttBufferCommandOffsetEx = f.readInt(); int vshAttBufferCommandCountEx = f.readInt(); Vector3 Center = new Vector3(f.readFloat(), f.readFloat(), f.readFloat()); int flagoffset = f.readInt(); // flagsOffset f.skip(4); // 0? int boundingBoxOffset = f.readInt(); } //Materials Console.WriteLine(materialsTableOffset.ToString("x") + " " + materialsPointerTableOffset.ToString("x")); for (int i = 0; i < materialsTableEntries; i++) { f.seek(materialsTableOffset + (i * 0x2c)); int paramOffset = f.readInt(); f.skip(12); // other offsets int texCommandOffset = f.readInt(); int texCommandCount = f.readInt(); int mapperOffset = f.readInt(); BCH_Material mat = new BCH_Material(); Materials.Nodes.Add(mat); mat.Text = f.readString(f.readInt(), -1); Console.WriteLine(mat.Text); //Console.WriteLine(f.readString(f.readInt(), -1)); //Console.WriteLine(f.readString(f.readInt(), -1)); //Console.WriteLine(f.readString(f.readInt(), -1)); // TODO: Parameters } //Skeleton f.seek(skeletonOffset); for (int bindex = 0; bindex < skeletonEntries; bindex++) { Bone bone = new Bone(model.skeleton); int boneFlags = f.readInt(); bone.parentIndex = (short)f.readShort(); short boneSpace = (short)f.readShort(); bone.scale = new float[3]; bone.rotation = new float[3]; bone.position = new float[3]; bone.scale[0] = f.readFloat(); bone.scale[1] = f.readFloat(); bone.scale[2] = f.readFloat(); bone.rotation[0] = f.readFloat(); bone.rotation[1] = f.readFloat(); bone.rotation[2] = f.readFloat(); bone.position[0] = f.readFloat(); bone.position[1] = f.readFloat(); bone.position[2] = f.readFloat(); // bone matrix... not really needed to be stored per say f.skip(4 * 4 * 3); bone.Text = f.readString(f.readInt(), -1); int metaDataPointerOffset2 = f.readInt(); if (metaDataPointerOffset2 != 0) { int position = f.pos(); f.seek(metaDataPointerOffset2); //bone.userData = getMetaData(input); f.seek(position); } model.skeleton.bones.Add(bone); } model.skeleton.reset(); model.skeleton.update(); } }
private static void getAnimationKeyFrame(FileData input, Animation.KeyGroup group, out float endFrame) { float startFrame = input.readFloat(); endFrame = input.readFloat(); uint frameFlags = (uint)input.readInt(); //Debug.WriteLine(frameFlags.ToString("x")); //int preRepeat = (RenderBase.ORepeatMethod)(frameFlags & 0xf); //int postRepeat = (RenderBase.ORepeatMethod)((frameFlags >> 8) & 0xf); uint segmentFlags = (uint)input.readInt(); int interpolation = ((int)segmentFlags & 0xf); uint quantization = ((segmentFlags >> 8) & 0xff); uint entries = segmentFlags >> 16; float valueScale = input.readFloat(); float valueOffset = input.readFloat(); float frameScale = input.readFloat(); float frameOffset = input.readFloat(); uint offset = (uint)input.readInt(); if (offset < input.size()) { input.seek((int)offset); } for (int key = 0; key < entries; key++) { Animation.KeyFrame keyFrame = new Animation.KeyFrame(); //Console.WriteLine(quantization); switch (quantization) { /*case RenderBase.OSegmentQuantization.hermite128: * keyFrame.frame = input.ReadSingle(); * keyFrame.value = input.ReadSingle(); * keyFrame.inSlope = input.ReadSingle(); * keyFrame.outSlope = input.ReadSingle(); * break; * case RenderBase.OSegmentQuantization.hermite64: * uint h64Value = input.ReadUInt32(); * keyFrame.frame = h64Value & 0xfff; * keyFrame.value = h64Value >> 12; * keyFrame.inSlope = input.ReadInt16() / 256f; * keyFrame.outSlope = input.ReadInt16() / 256f; * break; * case RenderBase.OSegmentQuantization.hermite48: * keyFrame.frame = input.ReadByte(); * keyFrame.value = input.ReadUInt16(); * byte slope0 = input.ReadByte(); * byte slope1 = input.ReadByte(); * byte slope2 = input.ReadByte(); * keyFrame.inSlope = IOUtils.signExtend(slope0 | ((slope1 & 0xf) << 8), 12) / 32f; * keyFrame.outSlope = IOUtils.signExtend((slope1 >> 4) | (slope2 << 4), 12) / 32f; * break; * case RenderBase.OSegmentQuantization.unifiedHermite96: * keyFrame.frame = input.ReadSingle(); * keyFrame.value = input.ReadSingle(); * keyFrame.inSlope = input.ReadSingle(); * keyFrame.outSlope = keyFrame.inSlope; * break; * case RenderBase.OSegmentQuantization.unifiedHermite48: * keyFrame.frame = input.ReadUInt16() / 32f; * keyFrame.value = input.ReadUInt16(); * keyFrame.inSlope = input.ReadInt16() / 256f; * keyFrame.outSlope = keyFrame.inSlope; * break; * case RenderBase.OSegmentQuantization.unifiedHermite32: * keyFrame.frame = input.ReadByte(); * ushort uH32Value = input.ReadUInt16(); * keyFrame.value = uH32Value & 0xfff; * keyFrame.inSlope = IOUtils.signExtend((uH32Value >> 12) | (input.ReadByte() << 4), 12) / 32f; * keyFrame.outSlope = keyFrame.inSlope; * break; * case RenderBase.OSegmentQuantization.stepLinear64: * keyFrame.frame = input.ReadSingle(); * keyFrame.value = input.ReadSingle(); * break;*/ case 7: // RenderBase.OSegmentQuantization.stepLinear32: uint sL32Value = (uint)input.readInt(); keyFrame.Frame = sL32Value & 0xfff; keyFrame.Value = sL32Value >> 12; break; default: Console.WriteLine("Unknown type " + quantization); break; } keyFrame.Frame = (keyFrame.Frame * frameScale) + frameOffset; keyFrame.Value = (keyFrame.Value * valueScale) + valueOffset; group.Keys.Add(keyFrame); } }
public override void Read(string filename) { bchHeader header = new bchHeader(); FileData f = new FileData(filename); f.Endian = System.IO.Endianness.Little; f.skip(4); header.backwardCompatibility = f.readByte(); header.forwardCompatibility = f.readByte(); header.version = f.readShort(); header.mainHeaderOffset = f.readInt(); header.stringTableOffset = f.readInt(); header.gpuCommandsOffset = f.readInt(); header.dataOffset = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedOffset = f.readInt(); } header.relocationTableOffset = f.readInt(); header.mainHeaderLength = f.readInt(); header.stringTableLength = f.readInt(); header.gpuCommandsLength = f.readInt(); header.dataLength = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedLength = f.readInt(); } header.relocationTableLength = f.readInt(); header.uninitializedDataSectionLength = f.readInt(); header.uninitializedDescriptionSectionLength = f.readInt(); if (header.backwardCompatibility > 7) { header.flags = f.readShort(); header.addressCount = f.readShort(); } // Relocation table for (int i = 0; i < header.relocationTableLength; i += 4) { f.seek(header.relocationTableOffset + i); int val = f.readInt(); int off = val & 0x1FFFFFF; byte flag = (byte)(val >> 25); switch (flag) { case 0: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset); break; case 1: f.seek(off + header.mainHeaderOffset); f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset); break; case 2: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset); break; case 0xc: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; } f.seek((off * 4) + header.gpuCommandsOffset); if (header.backwardCompatibility < 6) { switch (flag) { case 0x23: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, ((f.readInt() + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (header.backwardCompatibility < 8) { switch (flag) { case 0x24: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (header.backwardCompatibility < 0x21) { switch (flag) { case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x28: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x29: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else { switch (flag) { case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex relative to Data Offset //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset case 0x2b: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataExtendedOffset); break; //Vertex relative to Data Extended Offset //case 0x2c: writer.Write(((peek(input) + header.dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset case 0x2d: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataExtendedOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Extended Offset } } } // Content Header f.seek(header.mainHeaderOffset); bchContentHeader content = new bchContentHeader(); { content.modelsPointerTableOffset = f.readInt(); content.modelsPointerTableEntries = f.readInt(); content.modelsNameOffset = f.readInt(); content.materialsPointerTableOffset = f.readInt(); content.materialsPointerTableEntries = f.readInt(); content.materialsNameOffset = f.readInt(); content.shadersPointerTableOffset = f.readInt(); content.shadersPointerTableEntries = f.readInt(); content.shadersNameOffset = f.readInt(); content.texturesPointerTableOffset = f.readInt(); content.texturesPointerTableEntries = f.readInt(); content.texturesNameOffset = f.readInt(); content.materialsLUTPointerTableOffset = f.readInt(); content.materialsLUTPointerTableEntries = f.readInt(); content.materialsLUTNameOffset = f.readInt(); content.lightsPointerTableOffset = f.readInt(); content.lightsPointerTableEntries = f.readInt(); content.lightsNameOffset = f.readInt(); content.camerasPointerTableOffset = f.readInt(); content.camerasPointerTableEntries = f.readInt(); content.camerasNameOffset = f.readInt(); content.fogsPointerTableOffset = f.readInt(); content.fogsPointerTableEntries = f.readInt(); content.fogsNameOffset = f.readInt(); content.skeletalAnimationsPointerTableOffset = f.readInt(); content.skeletalAnimationsPointerTableEntries = f.readInt(); content.skeletalAnimationsNameOffset = f.readInt(); content.materialAnimationsPointerTableOffset = f.readInt(); content.materialAnimationsPointerTableEntries = f.readInt(); content.materialAnimationsNameOffset = f.readInt(); content.visibilityAnimationsPointerTableOffset = f.readInt(); content.visibilityAnimationsPointerTableEntries = f.readInt(); content.visibilityAnimationsNameOffset = f.readInt(); content.lightAnimationsPointerTableOffset = f.readInt(); content.lightAnimationsPointerTableEntries = f.readInt(); content.lightAnimationsNameOffset = f.readInt(); content.cameraAnimationsPointerTableOffset = f.readInt(); content.cameraAnimationsPointerTableEntries = f.readInt(); content.cameraAnimationsNameOffset = f.readInt(); content.fogAnimationsPointerTableOffset = f.readInt(); content.fogAnimationsPointerTableEntries = f.readInt(); content.fogAnimationsNameOffset = f.readInt(); content.scenePointerTableOffset = f.readInt(); content.scenePointerTableEntries = f.readInt(); content.sceneNameOffset = f.readInt(); } //Shaders (unused for now, until someone wants to add them) for (int index = 0; index < content.shadersPointerTableEntries; index++) { f.seek(content.shadersPointerTableOffset + (index * 4)); int dataOffset = f.readInt(); f.seek(dataOffset); int shaderDataOffset = f.readInt(); int shaderDataLength = f.readInt(); } // Textures // WIP Section for (int index = 0; index < content.texturesPointerTableEntries; index++) { f.seek(content.texturesPointerTableOffset + (index * 4)); int dOffset = f.readInt(); f.seek(dOffset); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); f.seek(f.pos() + 0x14); String textureName = f.readString(f.readInt(), -1); //Debug.WriteLine("gpuCommandOffset: " + header.gpuCommandsOffset.ToString("X")); f.seek(textureCommandsOffset); //Debug.WriteLine("textureCommandOffset: " + textureCommandsOffset.ToString("X")); BCH_Texture tex = new BCH_Texture(); textures.Add(textureName, tex); tex.height = f.readShort(); tex.width = f.readShort(); f.skip(12); int doffset = f.readInt(); //Debug.WriteLine("doffset: " + doffset.ToString("X")); f.skip(4); tex.type = f.readInt(); tex.data = f.getSection(doffset, f.size() - doffset); if (tex.type == 12) { tex.display = NUT.loadImage(Pixel.decodeETC(tex.data, tex.width, tex.height)); } } // Model data for (int modelIndex = 0; modelIndex < content.modelsPointerTableEntries; modelIndex++) { f.seek(content.modelsPointerTableOffset + (modelIndex * 4)); int objectsHeaderOffset = f.readInt(); // Objects f.seek(objectsHeaderOffset); BCH_Model model = new BCH_Model(); models.Add(model); model.flags = f.readByte(); model.skeletonScaleType = f.readByte(); model.silhouetteMaterialEntries = f.readShort(); model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , 0, 0, 0, 1); model.materialsTableOffset = f.readInt(); model.materialsTableEntries = f.readInt(); model.materialsNameOffset = f.readInt(); model.verticesTableOffset = f.readInt(); //Debug.WriteLine("Mesh Count: " + f.pos().ToString("X")); model.verticesTableEntries = f.readInt(); f.skip(0x28); model.skeletonOffset = f.readInt(); model.skeletonEntries = f.readInt(); model.skeletonNameOffset = f.readInt(); model.objectsNodeVisibilityOffset = f.readInt(); model.objectsNodeCount = f.readInt(); model.name = f.readString(f.readInt(), -1); model.objectsNodeNameEntries = f.readInt(); model.objectsNodeNameOffset = f.readInt(); f.readInt(); //0x0 model.metaDataPointerOffset = f.readInt(); f.seek(model.objectsNodeVisibilityOffset); int nodeVisibility = f.readInt(); string[] objectName = new string[model.objectsNodeNameEntries]; f.seek(model.objectsNodeNameOffset); int rootReferenceBit = f.readInt(); //Radix tree int rootLeftNode = f.readShort(); int rootRightNode = f.readShort(); int rootNameOffset = f.readInt() + header.mainHeaderOffset; for (int i = 0; i < model.objectsNodeNameEntries; i++) { int referenceBit = f.readInt(); short leftNode = (short)f.readShort(); short rightNode = (short)f.readShort(); objectName[i] = f.readString(f.readInt(), -1); //Debug.WriteLine(objectName[i]); } // Materials // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM String[] materialNames = new String[model.materialsTableEntries]; for (int index = 0; index < model.materialsTableEntries; index++) { f.seek(model.materialsTableOffset + (index * 0x2c)); int materialParametersOffset = f.readInt(); f.readInt(); f.readInt(); f.readInt(); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); int materialMapperOffset = f.readInt(); materialNames[index] = f.readString(f.readInt(), -1); } // Object Descriptions... // Assumes MBN is already loaded for now f.seek(model.verticesTableOffset); List <objDes> objDescriptors = new List <objDes>(); Debug.WriteLine(model.name); if (mbn == null) { mbn = new Smash_Forge.MBN(); for (int index = 0; index < model.verticesTableEntries; index++) { mbn.mesh.Add(new MBN.Mesh()); } mbn.PreRender(); } for (int index = 0; index < mbn.mesh.Count; index++) { int i = f.readShort(); if (index > mbn.mesh.Count) { break; } if (i > materialNames.Length) { break; } mbn.mesh[index].texId = textures[materialNames[i]].display; Console.WriteLine("Tex index" + mbn.mesh[index].texId); f.skip(2); // flags int nameId = f.readShort(); mbn.mesh[index].name = objectName[nameId]; // node visibility TODO: finish... //mbn.mesh[index].isVisible = ((nodeVisibility & (1 << nameId)) > 0); mbn.mesh[index].renderPriority = f.readShort(); objDes des = new objDes(); objDescriptors.Add(des); des.vshAttBufferCommandOffset = f.readInt(); des.vshAttBufferCommandCount = f.readInt(); des.faceOffset = f.readInt(); des.faceCount = f.readInt(); des.vshAttBufferCommandOffsetEx = f.readInt(); des.vshAttBufferCommandCountEx = f.readInt(); f.skip(12); // center vector f.skip(4); // flagsOffset f.skip(4); // 0? f.readInt(); //bbOffsets[i] = + mainheaderOffset //Debug.WriteLine(des.vshAttBufferCommandOffset.ToString("X")); } //Skeleton f.seek(model.skeletonOffset); for (int index = 0; index < model.skeletonEntries; index++) { Bone bone = new Smash_Forge.Bone(model.skeleton); int boneFlags = f.readInt(); bone.parentIndex = (short)f.readShort(); short boneSpace = (short)f.readShort(); bone.scale = new float[3]; bone.rotation = new float[3]; bone.position = new float[3]; bone.scale[0] = f.readFloat(); bone.scale[1] = f.readFloat(); bone.scale[2] = f.readFloat(); bone.rotation[0] = f.readFloat(); bone.rotation[1] = f.readFloat(); bone.rotation[2] = f.readFloat(); bone.position[0] = f.readFloat(); bone.position[1] = f.readFloat(); bone.position[2] = f.readFloat(); // bone matrix... not really needed to be stored per say f.skip(4 * 4 * 3); bone.Text = f.readString(f.readInt(), -1); f.skip(4); // Meta data model.skeleton.bones.Add(bone); } model.skeleton.reset(); } }
public override void Read(string filename) { bchHeader header = new bchHeader(); FileData f = new FileData(filename); f.Endian = System.IO.Endianness.Little; f.skip(4); header.backwardCompatibility = f.readByte(); header.forwardCompatibility = f.readByte(); header.version = f.readShort(); header.mainHeaderOffset = f.readInt(); header.stringTableOffset = f.readInt(); header.gpuCommandsOffset = f.readInt(); header.dataOffset = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedOffset = f.readInt(); } header.relocationTableOffset = f.readInt(); header.mainHeaderLength = f.readInt(); header.stringTableLength = f.readInt(); header.gpuCommandsLength = f.readInt(); header.dataLength = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedLength = f.readInt(); } header.relocationTableLength = f.readInt(); header.uninitializedDataSectionLength = f.readInt(); header.uninitializedDescriptionSectionLength = f.readInt(); if (header.backwardCompatibility > 7) { header.flags = f.readShort(); header.addressCount = f.readShort(); } // TODO: Finished Relocation table stuff for (int i = 0; i < header.relocationTableLength; i += 4) { f.seek(header.relocationTableOffset + i); int val = f.readInt(); int off = val & 0x1FFFFFF; byte flag = (byte)(val >> 25); switch (flag) { case 0: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset); break; case 1: f.seek(off + header.mainHeaderOffset); f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset); break; case 2: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset); break; case 0xc: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; } /*f.seek((off * 4) + header.gpuCommandsOffset); * if (header.backwardCompatibility < 6) * { * switch (flag) * { * case 0x23: f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; //Texture * case 0x25: f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; //Vertex * // Trying to understand the mess first * case 0x26: f.writeInt((off * 4) + header.mainHeaderOffset, Convert.ToInt32(((f.readInt() + header.dataOffset) & 0x7fffffff) | 0x80000000)); break; //Index 16 bits mode * //case 0x27: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode * } * } * else if (header.backwardCompatibility < 8) * { * switch (flag) * { * case 0x24: writer.Write(peek(input) + header.dataOffset); break; //Texture * case 0x26: writer.Write(peek(input) + header.dataOffset); break; //Vertex * case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode * case 0x28: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode * } * } * else if (header.backwardCompatibility < 0x21) * { * switch (flag) * { * case 0x25: writer.Write(peek(input) + header.dataOffset); break; //Texture * case 0x27: writer.Write(peek(input) + header.dataOffset); break; //Vertex * case 0x28: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode * case 0x29: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode * } * } * else * { * switch (flag) * { * case 0x25: writer.Write(peek(input) + header.dataOffset); break; //Texture * case 0x26: writer.Write(peek(input) + header.dataOffset); break; //Vertex relative to Data Offset * case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset * case 0x28: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset * case 0x2b: writer.Write(peek(input) + header.dataExtendedOffset); break; //Vertex relative to Data Extended Offset * case 0x2c: writer.Write(((peek(input) + header.dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset * case 0x2d: writer.Write((peek(input) + header.dataExtendedOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Extended Offset * } * } */ } // Content Header f.seek(header.mainHeaderOffset); bchContentHeader content = new bchContentHeader(); { content.modelsPointerTableOffset = f.readInt(); content.modelsPointerTableEntries = f.readInt(); content.modelsNameOffset = f.readInt(); content.materialsPointerTableOffset = f.readInt(); content.materialsPointerTableEntries = f.readInt(); content.materialsNameOffset = f.readInt(); content.shadersPointerTableOffset = f.readInt(); content.shadersPointerTableEntries = f.readInt(); content.shadersNameOffset = f.readInt(); content.texturesPointerTableOffset = f.readInt(); content.texturesPointerTableEntries = f.readInt(); content.texturesNameOffset = f.readInt(); content.materialsLUTPointerTableOffset = f.readInt(); content.materialsLUTPointerTableEntries = f.readInt(); content.materialsLUTNameOffset = f.readInt(); content.lightsPointerTableOffset = f.readInt(); content.lightsPointerTableEntries = f.readInt(); content.lightsNameOffset = f.readInt(); content.camerasPointerTableOffset = f.readInt(); content.camerasPointerTableEntries = f.readInt(); content.camerasNameOffset = f.readInt(); content.fogsPointerTableOffset = f.readInt(); content.fogsPointerTableEntries = f.readInt(); content.fogsNameOffset = f.readInt(); content.skeletalAnimationsPointerTableOffset = f.readInt(); content.skeletalAnimationsPointerTableEntries = f.readInt(); content.skeletalAnimationsNameOffset = f.readInt(); content.materialAnimationsPointerTableOffset = f.readInt(); content.materialAnimationsPointerTableEntries = f.readInt(); content.materialAnimationsNameOffset = f.readInt(); content.visibilityAnimationsPointerTableOffset = f.readInt(); content.visibilityAnimationsPointerTableEntries = f.readInt(); content.visibilityAnimationsNameOffset = f.readInt(); content.lightAnimationsPointerTableOffset = f.readInt(); content.lightAnimationsPointerTableEntries = f.readInt(); content.lightAnimationsNameOffset = f.readInt(); content.cameraAnimationsPointerTableOffset = f.readInt(); content.cameraAnimationsPointerTableEntries = f.readInt(); content.cameraAnimationsNameOffset = f.readInt(); content.fogAnimationsPointerTableOffset = f.readInt(); content.fogAnimationsPointerTableEntries = f.readInt(); content.fogAnimationsNameOffset = f.readInt(); content.scenePointerTableOffset = f.readInt(); content.scenePointerTableEntries = f.readInt(); content.sceneNameOffset = f.readInt(); } //Shaders (unused for now, until someone wants to add them) for (int index = 0; index < content.shadersPointerTableEntries; index++) { f.seek(content.shadersPointerTableOffset + (index * 4)); int dataOffset = f.readInt(); f.seek(dataOffset); int shaderDataOffset = f.readInt(); int shaderDataLength = f.readInt(); } // Textures // WIP Section for (int index = 0; index < content.texturesPointerTableEntries; index++) { f.seek(content.texturesPointerTableOffset + (index * 4)); int dOffset = f.readInt(); f.seek(dOffset); Debug.WriteLine("dOffset: " + dOffset.ToString("X")); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); f.seek(f.pos() + 0x14); String textureName = f.readString(f.readInt(), -1); //Debug.WriteLine("gpuCommandOffset: " + header.gpuCommandsOffset.ToString("X")); f.seek(textureCommandsOffset); //Debug.WriteLine("textureCommandOffset: " + textureCommandsOffset.ToString("X")); BCH_Texture tex = new BCH_Texture(); textures.Add(textureName, tex); tex.height = f.readShort(); tex.width = f.readShort(); f.skip(12); int doffset = f.readInt(); //Debug.WriteLine("doffset: " + doffset.ToString("X")); f.skip(4); tex.type = f.readInt(); tex.data = f.getSection(doffset, f.size() - doffset); if (tex.type == 12) { tex.display = NUT.loadImage(Pixel.decodeETC(tex.data, tex.width, tex.height)); } } // Model data for (int modelIndex = 0; modelIndex < content.modelsPointerTableEntries; modelIndex++) { f.seek(content.modelsPointerTableOffset + (modelIndex * 4)); int objectsHeaderOffset = f.readInt(); // Objects f.seek(objectsHeaderOffset); BCH_Model model = new BCH_Model(); models.Add(model); model.flags = f.readByte(); model.skeletonScaleType = f.readByte(); model.silhouetteMaterialEntries = f.readShort(); model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , 0, 0, 0, 1); model.materialsTableOffset = f.readInt(); model.materialsTableEntries = f.readInt(); model.materialsNameOffset = f.readInt(); model.verticesTableOffset = f.readInt(); //Debug.WriteLine("Mesh Count: " + f.pos().ToString("X")); model.verticesTableEntries = f.readInt(); f.skip(0x28); model.skeletonOffset = f.readInt(); model.skeletonEntries = f.readInt(); model.skeletonNameOffset = f.readInt(); model.objectsNodeVisibilityOffset = f.readInt(); model.objectsNodeCount = f.readInt(); model.name = f.readString(f.readInt(), -1); model.objectsNodeNameEntries = f.readInt(); model.objectsNodeNameOffset = f.readInt(); f.readInt(); //0x0 model.metaDataPointerOffset = f.readInt(); f.seek(model.objectsNodeVisibilityOffset); int nodeVisibility = f.readInt(); string[] objectName = new string[model.objectsNodeNameEntries]; f.seek(model.objectsNodeNameOffset); int rootReferenceBit = f.readInt(); //Radix tree int rootLeftNode = f.readShort(); int rootRightNode = f.readShort(); int rootNameOffset = f.readInt() + header.mainHeaderOffset; for (int i = 0; i < model.objectsNodeNameEntries; i++) { int referenceBit = f.readInt(); short leftNode = (short)f.readShort(); short rightNode = (short)f.readShort(); objectName[i] = f.readString(f.readInt(), -1); //Debug.WriteLine(objectName[i]); } // Materials // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM String[] materialNames = new String[model.materialsTableEntries]; for (int index = 0; index < model.materialsTableEntries; index++) { f.seek(model.materialsTableOffset + (index * 0x2c)); int materialParametersOffset = f.readInt(); f.readInt(); f.readInt(); f.readInt(); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); int materialMapperOffset = f.readInt(); materialNames[index] = f.readString(f.readInt(), -1); } // Object Descriptions... // Assumes MBN is already loaded for now f.seek(model.verticesTableOffset); List <objDes> objDescriptors = new List <objDes>(); Debug.WriteLine(model.name); if (mbn == null) { mbn = new Smash_Forge.MBN(); for (int index = 0; index < model.verticesTableEntries; index++) { mbn.mesh.Add(new MBN.Mesh()); } mbn.PreRender(); } for (int index = 0; index < mbn.mesh.Count; index++) { int i = f.readShort(); if (index > mbn.mesh.Count) { break; } if (i > materialNames.Length) { break; } mbn.mesh[index].texId = textures[materialNames[i]].display; Console.WriteLine("Tex index" + mbn.mesh[index].texId); f.skip(2); // flags int nameId = f.readShort(); mbn.mesh[index].name = objectName[nameId]; // node visibility TODO: finish... //mbn.mesh[index].isVisible = ((nodeVisibility & (1 << nameId)) > 0); mbn.mesh[index].renderPriority = f.readShort(); objDes des = new objDes(); objDescriptors.Add(des); des.vshAttBufferCommandOffset = f.readInt(); des.vshAttBufferCommandCount = f.readInt(); des.faceOffset = f.readInt(); des.faceCount = f.readInt(); des.vshAttBufferCommandOffsetEx = f.readInt(); des.vshAttBufferCommandCountEx = f.readInt(); f.skip(12); // center vector f.skip(4); // flagsOffset f.skip(4); // 0? f.readInt(); //bbOffsets[i] = + mainheaderOffset //Debug.WriteLine(des.vshAttBufferCommandOffset.ToString("X")); } //Skeleton f.seek(model.skeletonOffset); for (int index = 0; index < model.skeletonEntries; index++) { Bone bone = new Smash_Forge.Bone(model.skeleton); int boneFlags = f.readInt(); bone.parentIndex = (short)f.readShort(); short boneSpace = (short)f.readShort(); bone.scale = new float[3]; bone.rotation = new float[3]; bone.position = new float[3]; bone.scale[0] = f.readFloat(); bone.scale[1] = f.readFloat(); bone.scale[2] = f.readFloat(); bone.rotation[0] = f.readFloat(); bone.rotation[1] = f.readFloat(); bone.rotation[2] = f.readFloat(); bone.position[0] = f.readFloat(); bone.position[1] = f.readFloat(); bone.position[2] = f.readFloat(); // bone matrix... not really needed to be stored per say f.skip(4 * 4 * 3); bone.boneName = f.readString(f.readInt(), -1).ToCharArray(); f.skip(4); // Meta data model.skeleton.bones.Add(bone); } model.skeleton.reset(); /* //Skeletal Animations * * SkelAnimation anim = new SkelAnimation(); * * for (int index = 0; index < content.skeletalAnimationsPointerTableEntries; index++) * { * f.seek(content.skeletalAnimationsPointerTableOffset + (index * 4)); * int dataOffset = f.readInt(); * f.seek(dataOffset); * * RenderBase.OSkeletalAnimation skeletalAnimation = new RenderBase.OSkeletalAnimation(); * * skeletalAnimation.name = f.readString(f.readInt(), -1); * int animationFlags = f.readInt(); * skeletalAnimation.loopMode = (RenderBase.OLoopMode)(animationFlags & 1); * skeletalAnimation.frameSize = f.readFloat(); * int boneTableOffset = f.readInt(); * int boneTableEntries = f.readInt(); * int metaDataPointerOffset = f.readInt(); * * // /*if (metaDataPointerOffset != 0) * // { * // data.Seek(metaDataPointerOffset, SeekOrigin.Begin); * // skeletalAnimation.userData = getMetaData(input); * // } * * for (int i = 0; i < boneTableEntries; i++) * { * f.seek(boneTableOffset + (i * 4)); * int offset = f.readInt(); * * RenderBase.OSkeletalAnimationBone bone = new RenderBase.OSkeletalAnimationBone(); * * f.seek(offset); * bone.name = f.readString(f.readInt(), -1); * int animationTypeFlags = f.readInt(); * * int flags = f.readInt(); * * RenderBase.OSegmentType segmentType = (RenderBase.OSegmentType)((animationTypeFlags >> 16) & 0xf); * switch (segmentType) * { * case RenderBase.OSegmentType.transform: * f.seek(offset + 0x18); * * uint notExistMask = 0x80000; * uint constantMask = 0x200; * * for (int j = 0; j < 2; j++) * { * for (int axis = 0; axis < 3; axis++) * { * bool notExist = (flags & notExistMask) > 0; * bool constant = (flags & constantMask) > 0; * * RenderBase.OAnimationKeyFrameGroup frame = new RenderBase.OAnimationKeyFrameGroup(); * frame.exists = !notExist; * if (frame.exists) * { * if (constant) * { * frame.interpolation = RenderBase.OInterpolationMode.linear; * frame.keyFrames.Add(new RenderBase.OAnimationKeyFrame(input.ReadSingle(), 0)); * } * else * { * int frameOffset = f.readInt(); * long position = data.Position; * f.seek(frameOffset); * getAnimationKeyFrame(input, frame); * f.seek(position); * } * } * else * data.Seek(4, SeekOrigin.Current); * * if (j == 0) * { * switch (axis) * { * case 0: bone.rotationX = frame; break; * case 1: bone.rotationY = frame; break; * case 2: bone.rotationZ = frame; break; * } * } * else * { * switch (axis) * { * case 0: bone.translationX = frame; break; * case 1: bone.translationY = frame; break; * case 2: bone.translationZ = frame; break; * } * } * * notExistMask <<= 1; * constantMask <<= 1; * } * * constantMask <<= 1; * } * * break; * case RenderBase.OSegmentType.transformQuaternion: * bone.isFrameFormat = true; * * uint scaleOffset = input.ReadUInt32(); * uint rotationOffset = input.ReadUInt32(); * uint translationOffset = input.ReadUInt32(); * * if ((flags & 0x20) == 0) * { * bone.scale.exists = true; * data.Seek(scaleOffset, SeekOrigin.Begin); * * if ((flags & 4) > 0) * { * bone.scale.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * 0)); * } * else * { * bone.scale.startFrame = input.ReadSingle(); * bone.scale.endFrame = input.ReadSingle(); * * uint scaleFlags = input.ReadUInt32(); * uint scaleDataOffset = input.ReadUInt32(); * uint scaleEntries = input.ReadUInt32(); * * data.Seek(scaleDataOffset, SeekOrigin.Begin); * for (int j = 0; j < scaleEntries; j++) * { * bone.scale.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * 0)); * } * } * } * * if ((flags & 0x10) == 0) * { * bone.rotationQuaternion.exists = true; * data.Seek(rotationOffset, SeekOrigin.Begin); * * if ((flags & 2) > 0) * { * bone.rotationQuaternion.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle())); * } * else * { * bone.rotationQuaternion.startFrame = input.ReadSingle(); * bone.rotationQuaternion.endFrame = input.ReadSingle(); * * uint rotationFlags = input.ReadUInt32(); * uint rotationDataOffset = input.ReadUInt32(); * uint rotationEntries = input.ReadUInt32(); * * data.Seek(rotationDataOffset, SeekOrigin.Begin); * for (int j = 0; j < rotationEntries; j++) * { * bone.rotationQuaternion.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle())); * } * } * } * * if ((flags & 8) == 0) * { * bone.translation.exists = true; * data.Seek(translationOffset, SeekOrigin.Begin); * * if ((flags & 1) > 0) * { * bone.translation.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * 0)); * } * else * { * bone.translation.startFrame = input.ReadSingle(); * bone.translation.endFrame = input.ReadSingle(); * * uint translationFlags = input.ReadUInt32(); * uint translationDataOffset = input.ReadUInt32(); * uint translationEntries = input.ReadUInt32(); * * data.Seek(translationDataOffset, SeekOrigin.Begin); * for (int j = 0; j < translationEntries; j++) * { * bone.translation.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * 0)); * } * } * } * * break; * case RenderBase.OSegmentType.transformMatrix: * bone.isFullBakedFormat = true; * * input.ReadUInt32(); * input.ReadUInt32(); * uint matrixOffset = input.ReadUInt32(); * uint entries = input.ReadUInt32(); * * data.Seek(matrixOffset, SeekOrigin.Begin); * for (int j = 0; j < entries; j++) * { * RenderBase.OMatrix transform = new RenderBase.OMatrix(); * transform.M11 = input.ReadSingle(); * transform.M21 = input.ReadSingle(); * transform.M31 = input.ReadSingle(); * transform.M41 = input.ReadSingle(); * * transform.M12 = input.ReadSingle(); * transform.M22 = input.ReadSingle(); * transform.M32 = input.ReadSingle(); * transform.M42 = input.ReadSingle(); * * transform.M13 = input.ReadSingle(); * transform.M23 = input.ReadSingle(); * transform.M33 = input.ReadSingle(); * transform.M43 = input.ReadSingle(); * * bone.transform.Add(transform); * } * * break; * default: throw new Exception(string.Format("BCH: Unknow Segment Type {0} on Skeletal Animation bone {1}! STOP!", segmentType, bone.name)); * } * * skeletalAnimation.bone.Add(bone); * } * * models.skeletalAnimation.list.Add(skeletalAnimation); * } * * //Material Animations * for (int index = 0; index < contentHeader.materialAnimationsPointerTableEntries; index++) * { * data.Seek(contentHeader.materialAnimationsPointerTableOffset + (index * 4), SeekOrigin.Begin); * uint dataOffset = input.ReadUInt32(); * data.Seek(dataOffset, SeekOrigin.Begin); * * RenderBase.OMaterialAnimation materialAnimation = new RenderBase.OMaterialAnimation(); * * materialAnimation.name = readString(input); * uint animationFlags = input.ReadUInt32(); * materialAnimation.loopMode = (RenderBase.OLoopMode)(animationFlags & 1); * materialAnimation.frameSize = input.ReadSingle(); * uint dataTableOffset = input.ReadUInt32(); * uint dataTableEntries = input.ReadUInt32(); * input.ReadUInt32(); * uint textureNameTableOffset = input.ReadUInt32(); * uint textureNameTableEntries = input.ReadUInt32(); * * data.Seek(textureNameTableOffset, SeekOrigin.Begin); * for (int i = 0; i < textureNameTableEntries; i++) * { * string name = readString(input); * materialAnimation.textureName.Add(name); * } * * for (int i = 0; i < dataTableEntries; i++) * { * data.Seek(dataTableOffset + (i * 4), SeekOrigin.Begin); * uint offset = input.ReadUInt32(); * * RenderBase.OMaterialAnimationData animationData = new RenderBase.OMaterialAnimationData(); * * data.Seek(offset, SeekOrigin.Begin); * animationData.name = readString(input); * uint animationTypeFlags = input.ReadUInt32(); * uint flags = input.ReadUInt32(); * * animationData.type = (RenderBase.OMaterialAnimationType)(animationTypeFlags & 0xff); * RenderBase.OSegmentType segmentType = (RenderBase.OSegmentType)((animationTypeFlags >> 16) & 0xf); * * int segmentCount = 0; * switch (segmentType) * { * case RenderBase.OSegmentType.rgbaColor: segmentCount = 4; break; * case RenderBase.OSegmentType.vector2: segmentCount = 2; break; * case RenderBase.OSegmentType.single: segmentCount = 1; break; * case RenderBase.OSegmentType.integer: segmentCount = 1; break; * } * * for (int j = 0; j < segmentCount; j++) * { * RenderBase.OAnimationKeyFrameGroup frame = new RenderBase.OAnimationKeyFrameGroup(); * * data.Seek(offset + 0xc + (j * 4), SeekOrigin.Begin); * * frame.exists = (flags & (0x100 << j)) == 0; * bool constant = (flags & (1 << j)) > 0; * * if (frame.exists) * { * if (constant) * { * frame.interpolation = RenderBase.OInterpolationMode.linear; * frame.keyFrames.Add(new RenderBase.OAnimationKeyFrame(input.ReadSingle(), 0)); * } * else * { * uint frameOffset = input.ReadUInt32(); * data.Seek(frameOffset, SeekOrigin.Begin); * getAnimationKeyFrame(input, frame); * } * } * * animationData.frameList.Add(frame); * } * * materialAnimation.data.Add(animationData); * } * * models.materialAnimation.list.Add(materialAnimation); * } * */ } }
private byte[] Decrypt(FileData d) { int[] filedata = null; filedata = new int[d.size() / 4]; int size = (int)d.size(); int words = size >> 2; int xorval = 0; d.seek(0x1C); d.Endian = Endianness.Big; int SEED = d.readInt(); RandomXS _rand = new RandomXS(SEED); d.Endian = Endianness.Big; d.seek(0); if (size % 8 == 0) { goto Dword_loop; } else if (size == 0) { return(null); } else if (size / 8 <= 0) { goto BYTE_loop; } else { ;//goto default_loop } #region DWORD Loop Dword_loop: if (words == 0) { goto loops_end; } else if (words / 8 <= 0) { goto Word_Loop; } else { for (int i = 0; i < (words >> 3); i++) { for (int x = 0; x < 8; x++) { var randInt = _rand.GetInt(); var XOR = d.readInt() ^ randInt; var val = XOR ^ xorval; xorval = (randInt << 13) & unchecked ((int)0x80000000); filedata[x + (i * 8)] = val.Reverse(); } } } #endregion #region Word Loop Word_Loop: if ((words & 7) <= 0) { goto loops_end; } int offset = (size >> 2 >> 3 << 3 << 2); d.seek(offset); for (int i = 0; i < (words & 7); i++) { var randInt = _rand.GetInt(); var XOR = d.readInt() ^ randInt; var val = XOR ^ xorval; xorval = (randInt << 13) & unchecked ((int)0x80000000); filedata[offset / 4 + i] = val.Reverse(); } goto loops_end; #endregion #region BYTE Loop BYTE_loop: if ((size & 7) == 0) { goto func_end; } d.seek(4); for (int i = 4; i < (size & 7); i++) { byte[] data = BitConverter.GetBytes(filedata[i.RoundDown(4)]); var b = d.readByte(); var shifted = (b >> 3) | (b << 32 - 3); var val = b ^ shifted; data[i] = (byte)val; } #endregion loops_end: filedata[7] = SEED.Reverse(); func_end: byte[] result = new byte[filedata.Length * sizeof(int)]; Buffer.BlockCopy(filedata, 0, result, 0, result.Length); return(result); }
public void ReadNTWU(FileData d) { d.skip(0x02); int count = d.readShort(); d.skip(0x10); int headerPtr = d.pos(); int dataPtr = 0; int gtxHeaderOffset = 0; for (int i = 0; i < count; i++) { NutTexture tex = new NutTexture(); tex.type = PixelInternalFormat.Rgba32ui; d.seek(headerPtr); int totalSize = d.readInt(); int headerSize = d.readShort(); int numMips = d.readInt(); tex.setPixelFormatFromNutFormat(d.readShort()); tex.Width = d.readShort(); tex.Height = d.readShort(); d.skip(8); // mipmaps and padding int dataOffset = d.readInt() + dataPtr + 0x10; headerPtr += headerSize; dataPtr += headerSize; d.skip(0x04); if (i == 0) { gtxHeaderOffset = d.readInt() + 0x10; } else { gtxHeaderOffset += 0x80; d.skip(0x04); } d.skip(0x04); // check for cubemap bool cmap = (d.readInt() == d.readInt()); d.seek(d.pos() - 8); if (cmap) { Console.WriteLine("cubemap detected"); } d.skip(headerSize - 0x50); d.skip(0x18); tex.HASHID = d.readInt(); Console.WriteLine(gtxHeaderOffset.ToString("x")); d.seek(gtxHeaderOffset); d.skip(0x04); // dim d.skip(0x04); // width d.skip(0x04); // height d.skip(0x04); // depth d.skip(0x04); // numMips int format = d.readInt(); d.skip(0x04); // aa d.skip(0x04); // use int imageSize = d.readInt(); d.skip(0x04); // imagePtr int maxSize = d.readInt(); // mipSize d.skip(0x04); // mipPtr int tileMode = d.readInt(); int swizzle = d.readInt(); d.skip(0x04); // alignment int pitch = d.readInt(); int ds = dataOffset; int s1 = 0; int size = 0; Console.WriteLine(totalSize.ToString("x")); for (int mipLevel = 0; mipLevel < numMips; mipLevel++) { // Maybe this is the problem? int mipSize = imageSize >> (mipLevel * 2); int p = pitch >> mipLevel; size = d.readInt(); //Console.WriteLine("\tMIP: " + size.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + (size == 0 ? ds + totalSize - dataOffset : size)); //Console.WriteLine(tex.id.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + swizzle); //Console.WriteLine((tex.width >> mipLevel) + " " + (tex.height >> mipLevel)); //if (cmap) tex.height *= 2; int w = (tex.Width >> mipLevel); int h = (tex.Height >> mipLevel); { byte[] deswiz = GTX.swizzleBC( d.getSection(dataOffset, d.size() - dataOffset), w, h, format, tileMode, p, swizzle ); tex.mipmaps.Add(new FileData(deswiz).getSection(0, mipSize)); } if (mipLevel == 0) { s1 = size; dataOffset = ds + size; } else { dataOffset = ds + s1 + size; } //dataOffset += mipSize; /*if (cmap) * { * for(int k = 0; k < 5; k++) * { * p = pitch >> (mipLevel + k + 1); * tex.mipmaps.Add(GTX.swizzleBC( * d.getSection(dataOffset, mipSize), * w, * h, * format, * tileMode, * p, * swizzle * )); * * dataOffset += mipSize; * } * }*/ //while (dataOffset % 1024 != 0) dataOffset++; //if (mipSize == 0x4000) dataOffset += 0x400; } Nodes.Add(tex); } foreach (NutTexture tex in Nodes) { if (!draw.ContainsKey(tex.HASHID)) { draw.Add(tex.HASHID, loadImage(tex, false)); } // redo mipmaps /*GL.BindTexture(TextureTarget.Texture2D, draw[tex.id]); * for (int k = 1; k < tex.mipmaps.Count; k++) * { * tex.mipmaps[k] = new byte[tex.mipmaps[k].Length]; * GCHandle pinnedArray = GCHandle.Alloc(tex.mipmaps[k], GCHandleType.Pinned); * IntPtr pointer = pinnedArray.AddrOfPinnedObject(); * GL.GetCompressedTexImage(TextureTarget.Texture2D, 0, pointer); * pinnedArray.Free(); * }*/ } //File.WriteAllBytes("C:\\s\\Smash\\extract\\data\\fighter\\duckhunt\\model\\body\\mip1.bin", bytearray); //Console.WriteLine(GL.GetError()); /*int j = 0; * foreach(byte[] b in textures[0].mipmaps) * { * if (j == 3) * { * for(int w = 3; w < 8; w++) * { * for (int p = 3; p < 6; p++) * { * byte[] deswiz = GTX.swizzleBC( * b, * (int)Math.Pow(2, w), * 64, * 51, * 4, * (int)Math.Pow(2, p), * 197632 * ); * File.WriteAllBytes("C:\\s\\Smash\\extract\\data\\fighter\\duckhunt\\model\\body\\chunk_" + (int)Math.Pow(2, p) + "_" + (int)Math.Pow(2, w), deswiz); * } * } * * } * j++; * }*/ }