public void Read(FileData d) { names.Clear(); d.skip(8);// magic and section size int c1 = d.readInt(); int start = d.pos(); for (int i = 0; i < c1; i++) { int offset = d.readInt(); int size = d.readInt(); int temp = d.pos(); d.seek(start + offset); d.readInt(); int s = (sbyte)d.readByte(); names.Add(d.readString(d.pos(), -1)); d.skip(s); d.align(4); d.seek(temp); } }
public void Read(FileData d) { hash = d.readInt(); unk1 = d.readInt(); int s = d.readByte(); name = d.readString(d.pos(), -1); d.skip(s); d.align(4); d.skip(8); offset = d.readInt(); size = d.readInt(); for (int i = 0; i < param.Length; i++) { param[i] = d.readFloat(); } offsets = new int[d.readInt()]; for (int i = 0; i < offsets.Length; i++) { offsets[i] = d.readInt(); } unkvalues = new float[d.readInt()]; for (int i = 0; i < unkvalues.Length; i++) { unkvalues[d.readInt()] = d.readFloat(); } List <int> une = new List <int>(); while (true) { int i = d.readInt(); une.Add(i); if (i == -1) { break; } } unkending = une.ToArray(); end = new int[3 + (int)Math.Ceiling((double)((unk1 >> 8) & 0xFF) / 4)]; for (int i = 0; i < end.Length; i++) { end[i] = d.readInt(); } //Console.WriteLine(id + " " + name + " " + offset.ToString("x")); }
public void Read(FileData d) { d.skip(12); unk1 = d.readInt(); int s = d.readByte(); name = d.readString(d.pos(), s - 1); d.skip(s); d.align(4); flag = d.readInt(); }
// 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 void Read(FileData d) { hash = d.readInt(); unk1 = d.readInt(); int s = d.readByte(); name = d.readString(d.pos(), s - 1); d.skip(s); d.align(4); data = new float[0x2c]; for (int i = 0; i < 0x2c; i++) { data[i] = d.readFloat(); } }
public void Read(FileData d) { d.skip(8); // magic and section size d.skip(4); // 0 padding? unk1 = d.readInt(); d.skip(2); //0 unk2 = d.readShort(); int ssize = d.readByte(); project = d.readString(d.pos(), ssize - 1); d.skip(ssize - 1); d.skip(6); unk3 = d.readShort(); d.align(4); ssize = d.readByte(); timestamp = d.readString(d.pos(), ssize - 1); d.skip(ssize - 1); d.skip(4); }
/** * Reading and saving -------------------- **/ public override void Read(string filename) { FileData d = new FileData(filename); d.seek(0); d.Endian = Endianness.Little; format = d.readUShort(); unknown = d.readUShort(); flags = d.readInt(); mode = d.readInt(); bool hasNameTable = (flags & 2) > 0; int polyCount = d.readInt(); mesh = new List <Mesh>(); descript = new List <Descriptor>(); List <List <int> > prim = new List <List <int> >(); for (int i = 0; i < polyCount; i++) { if (i == 0 && mode == 1) { Descriptor des = new Descriptor(); des.ReadDescription(d); descript.Add(des); } Mesh m = new Mesh(); mesh.Add(m); int faceCount = d.readInt(); List <int> prims = new List <int>(); prim.Add(prims); for (int j = 0; j < faceCount; j++) { int nodeCount = d.readInt(); List <int> nodeList = new List <int>(); m.nodeList.Add(nodeList); for (int k = 0; k < nodeCount; k++) { nodeList.Add(d.readInt()); // for a node list? } int primitiveCount = d.readInt(); prims.Add(primitiveCount); if (hasNameTable) { int nameId = d.readInt(); } if (mode == 0) { if (format == 4) { int[] buffer = new int[primitiveCount]; for (int k = 0; k < primitiveCount; k++) { buffer[k] = d.readUShort(); } d.align(4); List <int> buf = new List <int>(); buf.AddRange(buffer); m.faces.Add(buf); } else { Descriptor des = new Descriptor(); des.ReadDescription(d); descript.Add(des); } } } } if (mode == 0) { //Console.WriteLine("Extra!"); } // TODO: STRING TABLE if (hasNameTable) { for (int i = 0; i < mesh.Count; i++) { int index = d.readByte(); nameTable.Add(d.readString()); } } if (format != 4) { d.align(32); } // Vertex Bank int start = d.pos(); for (int i = 0; i < 1; i++) { if (mode == 0 || i == 0) { Descriptor des = descript[i]; if (format != 4) { while (d.pos() < start + des.length) { Vertex v = new Vertex(); vertices.Add(v); for (int k = 0; k < des.type.Length; k++) { d.align(2); switch (des.type[k]) { case 0: //Position v.pos.X = readType(d, des.format[k], des.scale[k]); v.pos.Y = readType(d, des.format[k], des.scale[k]); v.pos.Z = readType(d, des.format[k], des.scale[k]); break; case 1: //Normal v.nrm.X = readType(d, des.format[k], des.scale[k]); v.nrm.Y = readType(d, des.format[k], des.scale[k]); v.nrm.Z = readType(d, des.format[k], des.scale[k]); break; case 2: //Color v.col.X = (int)(readType(d, des.format[k], des.scale[k])); v.col.Y = (int)(readType(d, des.format[k], des.scale[k])); v.col.Z = (int)(readType(d, des.format[k], des.scale[k])); v.col.W = (int)(readType(d, des.format[k], des.scale[k])); break; case 3: //Tex0 v.tx.Add(new Vector2(readType(d, des.format[k], des.scale[k]), readType(d, des.format[k], des.scale[k]))); break; case 4: //Tex1 v.tx.Add(new Vector2(readType(d, des.format[k], des.scale[k]), readType(d, des.format[k], des.scale[k]))); break; case 5: //Bone Index v.node.Add(d.readByte()); v.node.Add(d.readByte()); break; case 6: //Bone Weight v.weight.Add(readType(d, des.format[k], des.scale[k])); v.weight.Add(readType(d, des.format[k], des.scale[k])); break; //default: // Console.WriteLine("WTF is this"); } } } d.align(32); } } for (int j = 0; j < mesh.Count; j++) { foreach (int l in prim[j]) { List <int> face = new List <int>(); mesh[j].faces.Add(face); for (int k = 0; k < l; k++) { face.Add(d.readUShort()); } d.align(32); } } } PreRender(); }
public void OpenMBN(FileData f) { f.Endian = Endianness.Little; f.seek(0); int format = f.readShort(); f.skip(2);//0xFFFF int flags = f.readInt(); int mode = f.readInt(); int meshCount = f.readInt(); int length = 0; if (mode == 1) { //One Attribute int count = f.readInt(); for (int i = 0; i < count; i++) { VertexAttribute a = new VertexAttribute(); a.Read(f); Attributes.Add(a); } length = f.readInt(); } // Get Mesh Nodes /*List<BCH_Mesh> meshes = new List<BCH_Mesh>(); * foreach(BCH_Mesh m in Nodes) * { * meshes.Add(m); * foreach (BCH_Mesh m2 in m.Nodes) * meshes.Add(m); * }*/ for (int i = 0; i < meshCount; i++) { BCH_Mesh m = (BCH_Mesh)Nodes[i]; int polyCount = f.readInt(); for (int j = 0; j < polyCount; j++) { BCH_PolyGroup pg = new BCH_PolyGroup(); m.Nodes.Add(pg); int nodeCount = f.readInt(); int[] nodeList = new int[nodeCount]; pg.BoneList = (nodeList); for (int k = 0; k < nodeCount; k++) { nodeList[k] = f.readInt(); } pg.Count = (f.readInt()); if ((flags & 2) > 0) { f.readInt(); } } } if (format != 4) { f.align(32); } int stride = 0; foreach (VertexAttribute a in Attributes) { stride += _3DSGPU.getTypeSize(a.format) * _3DSGPU.getFormatSize(a.type); } // Vertex Bank Vertices = new Vertex[length / (stride + stride % 2)]; for (int vi = 0; vi < Vertices.Length; vi++) { Vertex v = new Vertex(); foreach (VertexAttribute a in Attributes) { //f.align(2); a.ReadVertex(f, ref v); } Vertices[vi] = v; } f.align(32); for (int i = 0; i < meshCount; i++) { BCH_Mesh m = (BCH_Mesh)Nodes[i]; int pi = 0; foreach (BCH_PolyGroup pg in m.Nodes) { pg.Text = "Polygroup_" + pi++; pg.Faces = new int[pg.Count]; for (int k = 0; k < pg.Count; k++) { pg.Faces[k] = f.readShort(); } f.align(32); } } }
public void ReadNTP3(FileData d) { d.skip(0x2); int count = d.readShort(); d.skip(0x8); int dataPtr = 0; for (int i = 0; i < count; i++) { Debug.WriteLine(d.pos().ToString("x")); NUD_Texture tex = new NUD_Texture(); tex.type = PixelInternalFormat.Rgba32ui; int totalSize = d.readInt(); d.skip(4); // padding int dataSize = d.readInt(); int headerSize = d.readShort(); d.skip(3); int numMips = d.readByte(); Debug.WriteLine(numMips); d.skip(1); tex.setPixelFormatFromNutFormat(d.readByte()); tex.width = d.readShort(); tex.height = d.readShort(); d.skip(8); // padding? int dataOffset = d.readInt() + dataPtr + 0x10; d.skip(0x0C); int[] mipSizes = new int[numMips]; if (numMips == 1) { mipSizes[0] = dataSize; } else { for (int j = 0; j < numMips; j++) { mipSizes[j] = d.readInt(); } } d.align(16); d.skip(0x18); tex.id = d.readInt(); d.skip(4); // padding align 8 // add mipmap data for (int miplevel = 0; miplevel < numMips; miplevel++) { byte[] texArray = d.getSection(dataOffset, mipSizes[miplevel]); tex.mipmaps.Add(texArray); dataOffset += mipSizes[miplevel]; } dataPtr += headerSize; if (tex.getNutFormat() == 14 || tex.getNutFormat() == 17) { Console.WriteLine("Endian swap"); // swap foreach (byte[] mip in tex.mipmaps) { for (int t = 0; t < mip.Length; t += 4) { byte t1 = mip[t]; mip[t] = mip[t + 1]; mip[t + 1] = mip[t + 2]; mip[t + 2] = mip[t + 3]; mip[t + 3] = t1; /*byte t1 = mip[t]; * byte t2 = mip[t+1]; * mip[t] = mip[t + 3]; * mip[t + 1] = mip[t + 2]; * mip[t + 2] = t2; * mip[t + 3] = t1;*/ } } } textures.Add(tex); /*for (int miplevel = 0; miplevel < numMips; miplevel++) * { * byte[] texArray = d.getSection(dataOffset, mipSizes[miplevel]); * * if (tex.getNutFormat() == 14) * { * byte[] oldArray = texArray; * for (int pos = 0; pos < mipSizes[miplevel]; pos+=4) * { * * for (int p = 0; p < 4; p++) * { * if (p == 0) * texArray[pos + 3] = oldArray[pos]; * else * texArray[pos + p - 1] = oldArray[pos + p]; * } * * } * } * tex.mipmaps.Add(texArray); * dataOffset += mipSizes[miplevel]; * }*/ } foreach (var tex in textures) { if (!draw.ContainsKey(tex.id)) { draw.Add(tex.id, loadImage(tex, true)); } } }
public void ReadNTWU(FileData d) { d.seek(0x4); Version = d.readUShort(); ushort count = d.readUShort(); d.skip(0x8); int headerPtr = 0x10; for (ushort i = 0; i < count; ++i) { d.seek(headerPtr); NutTexture tex = new NutTexture(); tex.pixelInternalFormat = PixelInternalFormat.Rgba32ui; int totalSize = d.readInt(); d.skip(4); int dataSize = d.readInt(); int headerSize = d.readUShort(); d.skip(2); d.skip(1); byte mipmapCount = d.readByte(); d.skip(1); tex.setPixelFormatFromNutFormat(d.readByte()); tex.Width = d.readUShort(); tex.Height = d.readUShort(); d.readInt(); //Always 1? uint caps2 = d.readUInt(); bool isCubemap = false; byte surfaceCount = 1; if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP) == (uint)DDS.DDSCAPS2.CUBEMAP) { //Only supporting all six faces if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) == (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) { isCubemap = true; surfaceCount = 6; } else { throw new NotImplementedException($"Unsupported cubemap face amount for texture {i} with hash 0x{tex.HashId:X}. Six faces are required."); } } int dataOffset = d.readInt() + headerPtr; int mipDataOffset = d.readInt() + headerPtr; int gtxHeaderOffset = d.readInt() + headerPtr; d.readInt(); int cmapSize1 = 0; int cmapSize2 = 0; if (isCubemap) { cmapSize1 = d.readInt(); cmapSize2 = d.readInt(); d.skip(8); } int imageSize = 0; //Total size of first mipmap of every surface int mipSize = 0; //Total size of mipmaps other than the first of every surface if (mipmapCount == 1) { if (isCubemap) { imageSize = cmapSize1; } else { imageSize = dataSize; } } else { imageSize = d.readInt(); mipSize = d.readInt(); d.skip((mipmapCount - 2) * 4); d.align(0x10); } d.skip(0x10); //eXt data - always the same d.skip(4); //GIDX d.readInt(); //Always 0x10 tex.HashId = d.readInt(); d.skip(4); // padding align 8 d.seek(gtxHeaderOffset); GTX.GX2Surface gtxHeader = new GTX.GX2Surface(); gtxHeader.dim = d.readInt(); gtxHeader.width = d.readInt(); gtxHeader.height = d.readInt(); gtxHeader.depth = d.readInt(); gtxHeader.numMips = d.readInt(); gtxHeader.format = d.readInt(); gtxHeader.aa = d.readInt(); gtxHeader.use = d.readInt(); gtxHeader.imageSize = d.readInt(); gtxHeader.imagePtr = d.readInt(); gtxHeader.mipSize = d.readInt(); gtxHeader.mipPtr = d.readInt(); gtxHeader.tileMode = d.readInt(); gtxHeader.swizzle = d.readInt(); gtxHeader.alignment = d.readInt(); gtxHeader.pitch = d.readInt(); //mipOffsets[0] is not in this list and is simply the start of the data (dataOffset) //mipOffsets[1] is relative to the start of the data (dataOffset + mipOffsets[1]) //Other mipOffsets are relative to mipOffset[1] (dataOffset + mipOffsets[1] + mipOffsets[i]) int[] mipOffsets = new int[mipmapCount]; mipOffsets[0] = 0; for (byte mipLevel = 1; mipLevel < mipmapCount; ++mipLevel) { mipOffsets[mipLevel] = 0; mipOffsets[mipLevel] = mipOffsets[1] + d.readInt(); } for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel) { tex.surfaces.Add(new TextureSurface()); } int w = tex.Width, h = tex.Height; for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) { int p = gtxHeader.pitch / (gtxHeader.width / w); int size; if (mipmapCount == 1) { size = imageSize; } else if (mipLevel + 1 == mipmapCount) { size = (mipSize + mipOffsets[1]) - mipOffsets[mipLevel]; } else { size = mipOffsets[mipLevel + 1] - mipOffsets[mipLevel]; } size /= surfaceCount; for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel) { gtxHeader.data = d.getSection(dataOffset + mipOffsets[mipLevel] + (size * surfaceLevel), size); //Real size //Leave the below line commented for now because it breaks RGBA textures //size = ((w + 3) >> 2) * ((h + 3) >> 2) * (GTX.getBPP(gtxHeader.format) / 8); if (size < (GTX.getBPP(gtxHeader.format) / 8)) { size = (GTX.getBPP(gtxHeader.format) / 8); } byte[] deswiz = GTX.swizzleBC( gtxHeader.data, w, h, gtxHeader.format, gtxHeader.tileMode, p, gtxHeader.swizzle ); tex.surfaces[surfaceLevel].mipmaps.Add(new FileData(deswiz).getSection(0, size)); } w /= 2; h /= 2; if (w < 1) { w = 1; } if (h < 1) { h = 1; } } headerPtr += headerSize; Nodes.Add(tex); } }
public void ReadNTP3(FileData d) { d.seek(0x4); Version = d.readUShort(); ushort count = d.readUShort(); if (Version == 0x100) { count -= 1; } d.skip(0x8); int headerPtr = 0x10; for (ushort i = 0; i < count; ++i) { d.seek(headerPtr); NutTexture tex = new NutTexture(); tex.isDds = true; tex.pixelInternalFormat = PixelInternalFormat.Rgba32ui; int totalSize = d.readInt(); d.skip(4); int dataSize = d.readInt(); int headerSize = d.readUShort(); d.skip(2); //It might seem that mipmapCount and pixelFormat would be shorts, but they're bytes because they stay in the same place regardless of endianness d.skip(1); byte mipmapCount = d.readByte(); d.skip(1); tex.setPixelFormatFromNutFormat(d.readByte()); tex.Width = d.readUShort(); tex.Height = d.readUShort(); d.skip(4); uint caps2 = d.readUInt(); bool isCubemap = false; byte surfaceCount = 1; if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP) == (uint)DDS.DDSCAPS2.CUBEMAP) { //Only supporting all six faces if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) == (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) { isCubemap = true; surfaceCount = 6; } else { throw new NotImplementedException($"Unsupported cubemap face amount for texture {i} with hash 0x{tex.HashId:X}. Six faces are required."); } } int dataOffset = d.readInt() + headerPtr; d.readInt(); d.readInt(); d.readInt(); //The size of a single cubemap face (discounting mipmaps). I don't know why it is repeated. If mipmaps are present, this is also specified in the mipSize section anyway. int cmapSize1 = 0; int cmapSize2 = 0; if (isCubemap) { cmapSize1 = d.readInt(); cmapSize2 = d.readInt(); d.skip(8); } int[] mipSizes = new int[mipmapCount]; if (mipmapCount == 1) { if (isCubemap) { mipSizes[0] = cmapSize1; } else { mipSizes[0] = dataSize; } } else { for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) { mipSizes[mipLevel] = d.readInt(); } d.align(0x10); } d.skip(0x10); //eXt data - always the same d.skip(4); //GIDX d.readInt(); //Always 0x10 tex.HashId = d.readInt(); d.skip(4); // padding align 8 if (Version == 0x100) { dataOffset = d.pos(); } for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel) { TextureSurface surface = new TextureSurface(); for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) { byte[] texArray = d.getSection(dataOffset, mipSizes[mipLevel]); surface.mipmaps.Add(texArray); dataOffset += mipSizes[mipLevel]; } tex.surfaces.Add(surface); } if (tex.getNutFormat() == 14 || tex.getNutFormat() == 17) { tex.SwapChannelOrderUp(); } headerPtr += headerSize; Nodes.Add(tex); } }
public void ReadNTWU(FileData d) { d.seek(0x4); Version = d.readUShort(); ushort count = d.readUShort(); d.skip(0x8); int headerPtr = 0x10; for (ushort i = 0; i < count; ++i) { d.seek(headerPtr); NutTexture tex = new NutTexture(); tex.type = PixelInternalFormat.Rgba32ui; int totalSize = d.readInt(); d.skip(4); int dataSize = d.readInt(); int headerSize = d.readUShort(); d.skip(2); d.skip(1); byte mipMapCount = d.readByte(); d.skip(1); tex.setPixelFormatFromNutFormat(d.readByte()); tex.Width = d.readUShort(); tex.Height = d.readUShort(); d.readInt(); //Always 1? uint caps2 = d.readUInt(); bool isCubemap = false; byte surfaceCount = 1; if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP) == (uint)DDS.DDSCAPS2.CUBEMAP) { //Only supporting all six faces if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) == (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) { isCubemap = true; surfaceCount = 6; } else { throw new NotImplementedException($"Unsupported cubemap face amount for texture {i} with hash 0x{tex.HASHID:X}. Six faces are required."); } } int dataOffset = d.readInt() + headerPtr; int mipDataOffset = d.readInt() + headerPtr; int gtxHeaderOffset = d.readInt() + headerPtr; d.readInt(); int cmapSize1 = 0; int cmapSize2 = 0; if (isCubemap) { cmapSize1 = d.readInt(); cmapSize2 = d.readInt(); d.skip(8); } int imageSize = 0; //Total size of first mipmap of every surface int mipSize = 0; //Total size of mipmaps other than the first of every surface if (mipMapCount == 1) { if (isCubemap) { imageSize = cmapSize1; } else { imageSize = dataSize; } } else { imageSize = d.readInt(); mipSize = d.readInt(); d.skip((mipMapCount - 2) * 4); d.align(0x10); } d.skip(0x10); //eXt data - always the same d.skip(4); //GIDX d.readInt(); //Always 0x10 tex.HASHID = d.readInt(); d.skip(4); // padding align 8 d.seek(gtxHeaderOffset); GTX.GX2Surface gtxHeader = new GTX.GX2Surface(); gtxHeader.dim = d.readInt(); gtxHeader.width = d.readInt(); gtxHeader.height = d.readInt(); gtxHeader.depth = d.readInt(); gtxHeader.numMips = d.readInt(); gtxHeader.format = d.readInt(); gtxHeader.aa = d.readInt(); gtxHeader.use = d.readInt(); gtxHeader.imageSize = d.readInt(); gtxHeader.imagePtr = d.readInt(); gtxHeader.mipSize = d.readInt(); gtxHeader.mipPtr = d.readInt(); gtxHeader.tileMode = d.readInt(); gtxHeader.swizzle = d.readInt(); gtxHeader.alignment = d.readInt(); gtxHeader.pitch = d.readInt(); //mipOffsets[0] is not in this list and is simply the start of the data (dataOffset) //mipOffsets[1] is relative to the start of the data (dataOffset + mipOffsets[1]) //Other mipOffsets are relative to mipOffset[1] (dataOffset + mipOffsets[1] + mipOffsets[i]) int[] mipOffsets = new int[mipMapCount]; mipOffsets[0] = 0; for (byte mipLevel = 1; mipLevel < mipMapCount; ++mipLevel) { mipOffsets[mipLevel] = 0; mipOffsets[mipLevel] = mipOffsets[1] + d.readInt(); } for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel) { tex.surfaces.Add(new TextureSurface()); } int w = tex.Width, h = tex.Height; for (byte mipLevel = 0; mipLevel < mipMapCount; ++mipLevel) { int p = gtxHeader.pitch / (gtxHeader.width / w); int size; if (mipMapCount == 1) { size = imageSize; } else if (mipLevel + 1 == mipMapCount) { size = (mipSize + mipOffsets[1]) - mipOffsets[mipLevel]; } else { size = mipOffsets[mipLevel + 1] - mipOffsets[mipLevel]; } size /= surfaceCount; for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel) { gtxHeader.data = d.getSection(dataOffset + mipOffsets[mipLevel] + (size * surfaceLevel), size); //Real size //Leave the below line commented for now because it breaks RGBA textures //size = ((w + 3) >> 2) * ((h + 3) >> 2) * (GTX.getBPP(gtxHeader.format) / 8); if (size < (GTX.getBPP(gtxHeader.format) / 8)) { size = (GTX.getBPP(gtxHeader.format) / 8); } byte[] deswiz = GTX.swizzleBC( gtxHeader.data, w, h, gtxHeader.format, gtxHeader.tileMode, p, gtxHeader.swizzle ); tex.surfaces[surfaceLevel].mipmaps.Add(new FileData(deswiz).getSection(0, size)); } w /= 2; h /= 2; if (w < 1) { w = 1; } if (h < 1) { h = 1; } } headerPtr += headerSize; Nodes.Add(tex); } RefreshGlTexturesByHashId(); //Console.WriteLine("\tMIP: " + size.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + (size == 0 ? ds + dataSize - dataOffset : size)); //Console.WriteLine(tex.id.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + swizzle); //Console.WriteLine((tex.width >> mipLevel) + " " + (tex.height >> mipLevel)); //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++; * }*/ }