public EventEntity(byte[] file, int address, uint imageBase, bool battle, Dictionary <string, NJS_OBJECT> models, List <NJS_MOTION> motions) { Model = Event.GetModel(file, address, imageBase, models); if (battle) { Motion = motions[ByteConverter.ToInt32(file, address + 4)]; ShapeMotion = motions[ByteConverter.ToInt32(file, address + 8)]; GCModel = Event.GetGCModel(file, address + 12, imageBase, models); ShadowModel = Event.GetModel(file, address + 16, imageBase, models); Position = new Vertex(file, address + 24); Flags = ByteConverter.ToUInt32(file, address + 36); Layer = ByteConverter.ToUInt32(file, address + 40); } else { int ptr = file.GetPointer(address + 4, imageBase); if (ptr != 0) { Motion = new NJS_MOTION(file, ptr, imageBase, Model.CountAnimated()); } ptr = file.GetPointer(address + 8, imageBase); if (ptr != 0) { ShapeMotion = new NJS_MOTION(file, ptr, imageBase, Model.CountMorph()); } Position = new Vertex(file, address + 16); Flags = ByteConverter.ToUInt32(file, address + 28); } }
// Scan for Actions in a specific range static int ScanActions(uint addr, uint nummdl, ModelFormat modelfmt) { int count = 0; ByteConverter.BigEndian = BigEndian; if (nummdl == 0) { return(0); } for (uint address = addr; address < datafile.Length - 8; address += 1) { CurrentAddress = address; if (CancelScan) { break; } if (ByteConverter.ToUInt32(datafile, (int)address) != addr + ImageBase) { continue; } uint motaddr = ByteConverter.ToUInt32(datafile, (int)address + 4); if (motaddr < ImageBase) { continue; } try { NJS_MOTION mot = new NJS_MOTION(datafile, (int)(motaddr - ImageBase), ImageBase, (int)nummdl, null, false); if (mot.Models.Count == 0) { continue; } addresslist.Add(motaddr - ImageBase, "NJS_MOTION"); Console.WriteLine("\rMotion found for model {0} at address {1}", addr.ToString("X8"), (motaddr - ImageBase).ToString("X")); string fileOutputPath = Path.Combine(OutputFolder, "actions", (motaddr - ImageBase).ToString("X8")); if (SingleOutputFolder) { fileOutputPath = Path.Combine(OutputFolder, (motaddr - ImageBase).ToString("X8")); } mot.Save(fileOutputPath + ".saanim", NoMeta); uint[] arr = new uint[2]; arr[0] = addr; arr[1] = nummdl; actionlist.Add(motaddr - ImageBase, arr); AddAction(addr, motaddr - ImageBase); address += 7; count++; } catch (Exception) { continue; } } return(count); }
public EventScene(byte[] file, int address, uint imageBase, bool battle, Dictionary <string, NJS_OBJECT> models, List <NJS_MOTION> motions) { int ptr = file.GetPointer(address, imageBase); if (ptr != 0) { int cnt = ByteConverter.ToInt32(file, address + 4); Entities = new List <EventEntity>(cnt); for (int i = 0; i < cnt; i++) { Entities.Add(new EventEntity(file, ptr, imageBase, battle, models, motions)); ptr += EventEntity.Size(battle); } } ptr = file.GetPointer(address + 8, imageBase); if (ptr != 0) { int cnt = ByteConverter.ToInt32(file, address + 12); CameraMotions = new List <NJS_MOTION>(cnt); for (int i = 0; i < cnt; i++) { if (battle) { CameraMotions.Add(motions[ByteConverter.ToInt32(file, ptr)]); } else { CameraMotions.Add(new NJS_MOTION(file, file.GetPointer(ptr, imageBase), imageBase, 1)); } ptr += sizeof(int); } } ptr = file.GetPointer(address + 24, imageBase); if (ptr != 0) { Big = new EventBig(file, ptr, imageBase, battle, models, motions); } FrameCount = ByteConverter.ToInt32(file, address + 28); }
public static List <NJS_MOTION> ReadMotionFile(string filename) { List <NJS_MOTION> motions = new List <NJS_MOTION>(); byte[] fc = File.ReadAllBytes(filename); int addr = 0; while (ByteConverter.ToInt64(fc, addr) != 0) { int ptr = ByteConverter.ToInt32(fc, addr); if (ptr == -1) { motions.Add(null); } else { motions.Add(new NJS_MOTION(fc, ptr, 0, ByteConverter.ToInt32(fc, addr + 4))); } addr += 8; } return(motions); }
public byte[] GetBytes(uint imageBase, LandTableFormat format, Dictionary <string, uint> labels, out uint address) { List <byte> result = new List <byte>(); byte[] tmpbyte; uint[] colmdladdrs = new uint[COL.Count]; uint tmpaddr; List <COL> cnk = new List <COL>(); List <COL> bas = new List <COL>(); foreach (COL item in COL) { if (item.Model.Attach is BasicAttach) { bas.Add(item); } else { cnk.Add(item); } } COL.Clear(); COL.AddRange(cnk); COL.AddRange(bas); for (int i = 0; i < COL.Count; i++) { if (labels.ContainsKey(COL[i].Model.Name)) { colmdladdrs[i] = labels[COL[i].Model.Name]; } else { result.Align(4); tmpbyte = COL[i].Model.GetBytes(imageBase + (uint)result.Count, format == LandTableFormat.SADX, labels, new List <uint>(), out tmpaddr); colmdladdrs[i] = tmpaddr + (uint)result.Count + imageBase; result.AddRange(tmpbyte); } } uint[] animmdladdrs = new uint[Anim.Count]; uint[] animaniaddrs = new uint[Anim.Count]; for (int i = 0; i < Anim.Count; i++) { if (labels.ContainsKey(Anim[i].Model.Name)) { animmdladdrs[i] = labels[Anim[i].Model.Name]; } else { result.Align(4); tmpbyte = Anim[i].Model.GetBytes(imageBase + (uint)result.Count, format == LandTableFormat.SADX, labels, new List <uint>(), out tmpaddr); animmdladdrs[i] = tmpaddr + (uint)result.Count + imageBase; result.AddRange(tmpbyte); } uint mtnaddr; if (labels.ContainsKey(Anim[i].Animation.Name)) { mtnaddr = labels[Anim[i].Animation.Name]; } else { result.Align(4); tmpbyte = Anim[i].Animation.GetBytes(imageBase + (uint)result.Count, labels, out tmpaddr); mtnaddr = tmpaddr + (uint)result.Count + imageBase; result.AddRange(tmpbyte); } result.Align(4); animaniaddrs[i] = (uint)result.Count + imageBase; result.AddRange(ByteConverter.GetBytes(animmdladdrs[i])); result.AddRange(ByteConverter.GetBytes(mtnaddr)); } uint coladdr; if (COL.Count > 0) { if (labels.ContainsKey(COLName)) { coladdr = labels[COLName]; } else { coladdr = imageBase + (uint)result.Count; labels.Add(COLName, coladdr); for (int i = 0; i < COL.Count; i++) { result.Align(4); result.AddRange(COL[i].GetBytes(imageBase + (uint)result.Count, colmdladdrs[i], format)); } } } else { coladdr = 0; } uint animaddr; if (Anim.Count > 0) { if (labels.ContainsKey(AnimName)) { animaddr = labels[AnimName]; } else { animaddr = imageBase + (uint)result.Count; if (!labels.ContainsKey(AnimName)) { labels.Add(AnimName, animaddr); } for (int i = 0; i < Anim.Count; i++) { if (!labels.ContainsValue(animaniaddrs[i])) { labels.Add(Anim[i].Animation.ActionName, animaniaddrs[i]); } result.Align(4); result.AddRange(Anim[i].GetBytes(imageBase + (uint)result.Count, animmdladdrs[i], animaniaddrs[i])); } } } else { animaddr = 0; } result.Align(4); uint texnameaddr = 0; if (TextureFileName != null) { texnameaddr = imageBase + (uint)result.Count; result.AddRange(Encoding.ASCII.GetBytes(TextureFileName)); result.Add(0); } result.Align(4); address = (uint)result.Count; result.AddRange(ByteConverter.GetBytes((ushort)COL.Count)); switch (format) { case LandTableFormat.SA1: case LandTableFormat.SADX: result.AddRange(ByteConverter.GetBytes((ushort)Anim.Count)); result.AddRange(ByteConverter.GetBytes((short)Attributes)); result.AddRange(ByteConverter.GetBytes(Flags)); result.AddRange(ByteConverter.GetBytes(FarClipping)); result.AddRange(ByteConverter.GetBytes(coladdr)); result.AddRange(ByteConverter.GetBytes(animaddr)); result.AddRange(ByteConverter.GetBytes(texnameaddr)); result.AddRange(ByteConverter.GetBytes(TextureList)); result.AddRange(ByteConverter.GetBytes(BinaryFilename)); result.AddRange(ByteConverter.GetBytes(BinaryLoadFunction)); break; case LandTableFormat.SA2: case LandTableFormat.SA2B: result.AddRange(ByteConverter.GetBytes((ushort)cnk.Count)); result.AddRange(new byte[8]); // TODO: figure out what these do result.AddRange(ByteConverter.GetBytes(FarClipping)); result.AddRange(ByteConverter.GetBytes(coladdr)); result.AddRange(ByteConverter.GetBytes(animaddr)); result.AddRange(ByteConverter.GetBytes(texnameaddr)); result.AddRange(ByteConverter.GetBytes(TextureList)); break; } labels.Add(Name, address + imageBase); return(result.ToArray()); }
public static LandTable LoadFromFile(string filename) { bool be = ByteConverter.BigEndian; ByteConverter.BigEndian = false; byte[] file = File.ReadAllBytes(filename); ulong magic = ByteConverter.ToUInt64(file, 0) & FormatMask; byte version = file[7]; if (version > CurrentVersion) { throw new FormatException("Not a valid SA1LVL/SA2LVL file."); } Dictionary <int, string> labels = new Dictionary <int, string>(); string author = null, description = null; Dictionary <uint, byte[]> meta = new Dictionary <uint, byte[]>(); if (version < 2) { if (version == 1) { int tmpaddr = ByteConverter.ToInt32(file, 0xC); if (tmpaddr != 0) { int addr = ByteConverter.ToInt32(file, tmpaddr); while (addr != -1) { labels.Add(addr, file.GetCString(ByteConverter.ToInt32(file, tmpaddr + 4))); tmpaddr += 8; addr = ByteConverter.ToInt32(file, tmpaddr); } } } } else { int tmpaddr = ByteConverter.ToInt32(file, 0xC); if (tmpaddr != 0) { bool finished = false; while (!finished) { ChunkTypes type = (ChunkTypes)ByteConverter.ToUInt32(file, tmpaddr); int chunksz = ByteConverter.ToInt32(file, tmpaddr + 4); int nextchunk = tmpaddr + 8 + chunksz; tmpaddr += 8; if (version == 2) { switch (type) { case ChunkTypes.Label: while (ByteConverter.ToInt64(file, tmpaddr) != -1) { labels.Add(ByteConverter.ToInt32(file, tmpaddr), file.GetCString(ByteConverter.ToInt32(file, tmpaddr + 4))); tmpaddr += 8; } break; case ChunkTypes.Author: author = file.GetCString(tmpaddr); break; case ChunkTypes.Tool: break; case ChunkTypes.Description: description = file.GetCString(tmpaddr); break; case ChunkTypes.End: finished = true; break; } } else { byte[] chunk = new byte[chunksz]; Array.Copy(file, tmpaddr, chunk, 0, chunksz); int chunkaddr = 0; switch (type) { case ChunkTypes.Label: while (ByteConverter.ToInt64(chunk, chunkaddr) != -1) { labels.Add(ByteConverter.ToInt32(chunk, chunkaddr), chunk.GetCString(ByteConverter.ToInt32(chunk, chunkaddr + 4))); chunkaddr += 8; } break; case ChunkTypes.Author: author = chunk.GetCString(0); break; case ChunkTypes.Tool: break; case ChunkTypes.Description: description = chunk.GetCString(0); break; case ChunkTypes.End: finished = true; break; default: meta.Add((uint)type, chunk); break; } } tmpaddr = nextchunk; } } } if (magic == SA1LVL) { LandTable table = new LandTable(file, ByteConverter.ToInt32(file, 8), 0, LandTableFormat.SA1, labels) { Author = author, Description = description, Metadata = meta }; ByteConverter.BigEndian = be; return(table); } if (magic == SA2LVL) { LandTable table = new LandTable(file, ByteConverter.ToInt32(file, 8), 0, LandTableFormat.SA2, labels) { Author = author, Description = description, Metadata = meta }; ByteConverter.BigEndian = be; return(table); } if (magic == SA2BLVL) { LandTable table = new LandTable(file, ByteConverter.ToInt32(file, 8), 0, LandTableFormat.SA2B, labels) { Author = author, Description = description, Metadata = meta }; ByteConverter.BigEndian = be; return(table); } ByteConverter.BigEndian = be; throw new FormatException("Not a valid SA1LVL/SA2LVL file."); }
public BasicAttach(byte[] file, int address, uint imageBase, bool DX, Dictionary <int, string> labels) : this() { if (labels.ContainsKey(address)) { Name = labels[address]; } else { Name = "attach_" + address.ToString("X8"); } Vertex = new Vertex[ByteConverter.ToInt32(file, address + 8)]; Normal = new Vertex[Vertex.Length]; int tmpaddr = (int)(ByteConverter.ToUInt32(file, address) - imageBase); if (labels.ContainsKey(tmpaddr)) { VertexName = labels[tmpaddr]; } else { VertexName = "vertex_" + tmpaddr.ToString("X8"); } for (int i = 0; i < Vertex.Length; i++) { Vertex[i] = new Vertex(file, tmpaddr); tmpaddr += SAModel.Vertex.Size; } tmpaddr = ByteConverter.ToInt32(file, address + 4); if (tmpaddr != 0) { tmpaddr = (int)((uint)tmpaddr - imageBase); if (labels.ContainsKey(tmpaddr)) { NormalName = labels[tmpaddr]; } else { NormalName = "normal_" + tmpaddr.ToString("X8"); } for (int i = 0; i < Vertex.Length; i++) { Normal[i] = new Vertex(file, tmpaddr); tmpaddr += SAModel.Vertex.Size; } } else { for (int i = 0; i < Vertex.Length; i++) { Normal[i] = new Vertex(0, 1, 0); } } int maxmat = -1; int meshcnt = ByteConverter.ToInt16(file, address + 0x14); tmpaddr = ByteConverter.ToInt32(file, address + 0xC); if (tmpaddr != 0) { tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase); if (labels.ContainsKey(tmpaddr)) { MeshName = labels[tmpaddr]; } else { MeshName = "meshlist_" + tmpaddr.ToString("X8"); } for (int i = 0; i < meshcnt; i++) { Mesh.Add(new NJS_MESHSET(file, tmpaddr, imageBase, labels)); maxmat = Math.Max(maxmat, Mesh[i].MaterialID); tmpaddr += NJS_MESHSET.Size(DX); } } // fixes case where model declares material array as shorter than it really is int matcnt = Math.Max(ByteConverter.ToInt16(file, address + 0x16), maxmat + 1); tmpaddr = ByteConverter.ToInt32(file, address + 0x10); if (tmpaddr != 0) { tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase); if (labels.ContainsKey(tmpaddr)) { MaterialName = labels[tmpaddr]; } else { MaterialName = "matlist_" + tmpaddr.ToString("X8"); } for (int i = 0; i < matcnt; i++) { Material.Add(new NJS_MATERIAL(file, tmpaddr, labels)); tmpaddr += NJS_MATERIAL.Size; } } Bounds = new BoundingSphere(file, address + 0x18); }
public override byte[] GetBytes(uint imageBase, bool DX, Dictionary <string, uint> labels, List <uint> njOffsets, out uint address) { List <byte> result = new List <byte>(); uint materialAddress = 0; if (Material != null && Material.Count > 0) { if (labels.ContainsKey(MaterialName)) { materialAddress = labels[MaterialName]; } else { materialAddress = imageBase; labels.Add(MaterialName, materialAddress); foreach (NJS_MATERIAL item in Material) { result.AddRange(item.GetBytes()); } } } uint meshAddress; if (labels.ContainsKey(MeshName)) { meshAddress = labels[MeshName]; } else { uint[] polyAddrs = new uint[Mesh.Count]; uint[] polyNormalAddrs = new uint[Mesh.Count]; uint[] vColorAddrs = new uint[Mesh.Count]; uint[] uVAddrs = new uint[Mesh.Count]; for (int i = 0; i < Mesh.Count; i++) { if (labels.ContainsKey(Mesh[i].PolyName)) { polyAddrs[i] = labels[Mesh[i].PolyName]; } else { result.Align(4); polyAddrs[i] = (uint)result.Count + imageBase; labels.Add(Mesh[i].PolyName, polyAddrs[i]); for (int j = 0; j < Mesh[i].Poly.Count; j++) { result.AddRange(Mesh[i].Poly[j].GetBytes()); } } } for (int i = 0; i < Mesh.Count; i++) { if (Mesh[i].PolyNormal != null && Mesh[i].PolyNormal.Length > 0) { if (labels.ContainsKey(Mesh[i].PolyNormalName)) { polyNormalAddrs[i] = labels[Mesh[i].PolyNormalName]; } else { result.Align(4); polyNormalAddrs[i] = (uint)result.Count + imageBase; labels.Add(Mesh[i].PolyNormalName, polyNormalAddrs[i]); for (int j = 0; j < Mesh[i].PolyNormal.Length; j++) { result.AddRange(Mesh[i].PolyNormal[j].GetBytes()); } } } } for (int i = 0; i < Mesh.Count; i++) { if (Mesh[i].VColor != null && Mesh[i].VColor.Length > 0) { if (labels.ContainsKey(Mesh[i].VColorName)) { vColorAddrs[i] = labels[Mesh[i].VColorName]; } else { result.Align(4); vColorAddrs[i] = (uint)result.Count + imageBase; labels.Add(Mesh[i].VColorName, vColorAddrs[i]); for (int j = 0; j < Mesh[i].VColor.Length; j++) { result.AddRange(VColor.GetBytes(Mesh[i].VColor[j])); } } } } for (int i = 0; i < Mesh.Count; i++) { if (Mesh[i].UV != null && Mesh[i].UV.Length > 0) { if (labels.ContainsKey(Mesh[i].UVName)) { uVAddrs[i] = labels[Mesh[i].UVName]; } else { result.Align(4); uVAddrs[i] = (uint)result.Count + imageBase; labels.Add(Mesh[i].UVName, uVAddrs[i]); for (int j = 0; j < Mesh[i].UV.Length; j++) { result.AddRange(Mesh[i].UV[j].GetBytes()); } } } } result.Align(4); meshAddress = (uint)result.Count + imageBase; labels.Add(MeshName, meshAddress); for (int i = 0; i < Mesh.Count; i++) { //POF0 if (polyAddrs[i] != 0) { njOffsets.Add((uint)(result.Count + imageBase + 0x4)); } if (polyNormalAddrs[i] != 0) { njOffsets.Add((uint)(result.Count + imageBase + 0xC)); } if (vColorAddrs[i] != 0) { njOffsets.Add((uint)(result.Count + imageBase + 0x10)); } if (uVAddrs[i] != 0) { njOffsets.Add((uint)(result.Count + imageBase + 0x14)); } result.AddRange(Mesh[i].GetBytes(polyAddrs[i], polyNormalAddrs[i], vColorAddrs[i], uVAddrs[i], DX)); } } result.Align(4); uint vertexAddress; if (labels.ContainsKey(VertexName)) { vertexAddress = labels[VertexName]; } else { vertexAddress = (uint)result.Count + imageBase; labels.Add(VertexName, vertexAddress); foreach (Vertex item in Vertex) { if (item == null) { result.AddRange(new byte[SAModel.Vertex.Size]); } else { result.AddRange(item.GetBytes()); } } } result.Align(4); uint normalAddress; if (labels.ContainsKey(NormalName)) { normalAddress = labels[NormalName]; } else { normalAddress = (uint)result.Count + imageBase; labels.Add(NormalName, normalAddress); foreach (Vertex item in Normal) { if (item == null) { result.AddRange(new byte[SAModel.Vertex.Size]); } else { result.AddRange(item.GetBytes()); } } } result.Align(4); address = (uint)result.Count; //POF0 if (vertexAddress != 0) { njOffsets.Add((uint)(result.Count + imageBase)); } if (normalAddress != 0) { njOffsets.Add((uint)(result.Count + imageBase + 0x4)); } if (meshAddress != 0) { njOffsets.Add((uint)(result.Count + imageBase + 0xC)); } if (materialAddress != 0) { njOffsets.Add((uint)(result.Count + imageBase + 0x10)); } result.AddRange(ByteConverter.GetBytes(vertexAddress)); result.AddRange(ByteConverter.GetBytes(normalAddress)); result.AddRange(ByteConverter.GetBytes(Vertex.Length)); result.AddRange(ByteConverter.GetBytes(meshAddress)); result.AddRange(ByteConverter.GetBytes(materialAddress)); result.AddRange(ByteConverter.GetBytes((short)Mesh.Count)); result.AddRange(ByteConverter.GetBytes((short)Material.Count)); result.AddRange(Bounds.GetBytes()); if (DX) { result.AddRange(new byte[4]); } labels.Add(Name, address + imageBase); return(result.ToArray()); }
public override byte[] GetBytes() { return(ByteConverter.GetBytes(Header)); }
// Scan for Motions static void ScanMotions() { CurrentStep++; CurrentScanData = "Motions" + (ModelParts > 0 ? " with " + ModelParts.ToString() + " or more nodes" : ""); Console.WriteLine("Step {0}: Scanning for motions with at least {1} model parts... ", CurrentStep, ModelParts); if (ShortRot) { Console.WriteLine("Using short rotations"); } ByteConverter.BigEndian = BigEndian; if (!SingleOutputFolder) { Directory.CreateDirectory(Path.Combine(OutputFolder, "actions")); } for (uint address = StartAddress; address < EndAddress; address += 1) { if (CancelScan) { break; } if (ConsoleMode && address % 1000 == 0) { Console.Write("\r{0} ", address.ToString("X8")); } CurrentAddress = address; // Check for a valid MDATA pointer uint mdatap = ByteConverter.ToUInt32(datafile, (int)address); if (mdatap < ImageBase || mdatap >= datafile.Length - 12 + ImageBase || mdatap == 0) { //Console.WriteLine("Mdatap {0} fail", mdatap.ToString("X8")); continue; } uint frames = ByteConverter.ToUInt32(datafile, (int)address + 4); if (frames > 2000 || frames < 1) { //Console.WriteLine("Frames {0} fail", frames.ToString()); continue; } AnimFlags animtype = (AnimFlags)ByteConverter.ToUInt16(datafile, (int)address + 8); if (animtype == 0) { continue; } int mdata = 0; //Console.WriteLine("Flags: {0}", animtype.ToString()); if (animtype.HasFlag(AnimFlags.Position)) { mdata++; } if (animtype.HasFlag(AnimFlags.Rotation)) { mdata++; } if (animtype.HasFlag(AnimFlags.Scale)) { mdata++; } if (animtype.HasFlag(AnimFlags.Vector)) { mdata++; } if (animtype.HasFlag(AnimFlags.Vertex)) { mdata++; } if (animtype.HasFlag(AnimFlags.Normal)) { mdata++; } if (animtype.HasFlag(AnimFlags.Color)) { continue; } if (animtype.HasFlag(AnimFlags.Intensity)) { continue; } if (animtype.HasFlag(AnimFlags.Target)) { continue; } if (animtype.HasFlag(AnimFlags.Spot)) { continue; } if (animtype.HasFlag(AnimFlags.Point)) { continue; } if (animtype.HasFlag(AnimFlags.Roll)) { continue; } int mdatasize = 0; bool lost = false; switch (mdata) { case 1: case 2: mdatasize = 16; break; case 3: mdatasize = 24; break; case 4: mdatasize = 32; break; case 5: mdatasize = 40; break; default: lost = true; break; } if (lost) { continue; } // Check MKEY pointers int mdatas = 0; for (int u = 0; u < 255; u++) { for (int m = 0; m < mdata; m++) { if (lost) { continue; } uint pointer = ByteConverter.ToUInt32(datafile, (int)(mdatap - ImageBase) + mdatasize * u + 4 * m); if (pointer < ImageBase || pointer >= datafile.Length - 8 + ImageBase) { if (pointer != 0) { lost = true; //Console.WriteLine("Mkey pointer {0} lost", pointer.ToString("X8")); } } if (!lost) { // Read frame count int framecount = ByteConverter.ToInt32(datafile, (int)(mdatap - ImageBase) + mdatasize * u + 4 * mdata + 4 * m); if (framecount < 0 || framecount > 2000) { //Console.WriteLine("Framecount lost: {0}", framecount.ToString("X8")); lost = true; } if (pointer == 0 && framecount != 0) { //Console.WriteLine("Framecount non zero"); lost = true; } //if (!lost) Console.WriteLine("Mdata size: {0}, MkeyP: {1}, Frames: {2}", mdatasize, pointer.ToString("X8"), framecount.ToString()); } } if (!lost) { mdatas++; //Console.WriteLine("Mdata {0}, total {1}", u, mdatas); } } if (mdatas > 0 && mdatas >= ModelParts) { try { Console.WriteLine("\rAdding motion at {0}: {1} nodes", address.ToString("X8"), mdatas); //Console.WriteLine("trying Address: {0}, MdataP: {1}, mdatas: {2}", address.ToString("X8"), mdatap.ToString("X8"), mdata); NJS_MOTION mot = NJS_MOTION.ReadDirect(datafile, mdatas, (int)address, ImageBase, new Dictionary <int, Attach>(), ShortRot); if (mot.ModelParts <= 0) { continue; } if (mot.Frames <= 0) { continue; } if (mot.Models.Count == 0) { continue; } string fileOutputPath = Path.Combine(OutputFolder, "actions", address.ToString("X8") + ".saanim"); if (SingleOutputFolder) { fileOutputPath = Path.Combine(OutputFolder, address.ToString("X8") + ".saanim"); } mot.Save(fileOutputPath, NoMeta); FoundMotions++; addresslist.Add(address, "NJS_MOTION"); uint[] arr = new uint[2]; arr[0] = address; arr[1] = (uint)mot.ModelParts; actionlist.Add(address, arr); } catch (Exception ex) { Console.WriteLine("\rError adding motion at {0}: {1}", address.ToString("X8"), ex.Message); } } } Console.WriteLine("\rFound {0} motions", FoundMotions); }
public static PolyChunk Load(byte[] file, int address) { ChunkType type = (ChunkType)(ByteConverter.ToUInt16(file, address) & 0xFF); switch (type) { case ChunkType.Null: return(new PolyChunkNull(file, address)); case ChunkType.Bits_BlendAlpha: return(new PolyChunkBitsBlendAlpha(file, address)); case ChunkType.Bits_MipmapDAdjust: return(new PolyChunkBitsMipmapDAdjust(file, address)); case ChunkType.Bits_SpecularExponent: return(new PolyChunkBitsSpecularExponent(file, address)); case ChunkType.Bits_CachePolygonList: return(new PolyChunkBitsCachePolygonList(file, address)); case ChunkType.Bits_DrawPolygonList: return(new PolyChunkBitsDrawPolygonList(file, address)); case ChunkType.Tiny_TextureID: case ChunkType.Tiny_TextureID2: return(new PolyChunkTinyTextureID(file, address)); case ChunkType.Material_Diffuse: case ChunkType.Material_Ambient: case ChunkType.Material_DiffuseAmbient: case ChunkType.Material_Specular: case ChunkType.Material_DiffuseSpecular: case ChunkType.Material_AmbientSpecular: case ChunkType.Material_DiffuseAmbientSpecular: case ChunkType.Material_Diffuse2: case ChunkType.Material_Ambient2: case ChunkType.Material_DiffuseAmbient2: case ChunkType.Material_Specular2: case ChunkType.Material_DiffuseSpecular2: case ChunkType.Material_AmbientSpecular2: case ChunkType.Material_DiffuseAmbientSpecular2: return(new PolyChunkMaterial(file, address)); case ChunkType.Material_Bump: return(new PolyChunkMaterialBump(file, address)); case ChunkType.Volume_Polygon3: case ChunkType.Volume_Polygon4: case ChunkType.Volume_Strip: return(new PolyChunkVolume(file, address)); case ChunkType.Strip_Strip: case ChunkType.Strip_StripUVN: case ChunkType.Strip_StripUVH: case ChunkType.Strip_StripColor: case ChunkType.Strip_StripUVNColor: case ChunkType.Strip_StripUVHColor: case ChunkType.Strip_Strip2: case ChunkType.Strip_StripUVN2: case ChunkType.Strip_StripUVH2: return(new PolyChunkStrip(file, address)); case ChunkType.End: return(new PolyChunkEnd(file, address)); default: throw new NotSupportedException("Unsupported chunk type " + type + " at " + address.ToString("X8") + "."); } }
public PolyChunkTinyTextureID(byte[] file, int address) { Header = ByteConverter.ToUInt16(file, address); Second = Type == ChunkType.Tiny_TextureID2; Data = ByteConverter.ToUInt16(file, address + 2); }
public PolyChunkBitsSpecularExponent(byte[] file, int address) { Header = ByteConverter.ToUInt16(file, address); }
public PolyChunkBitsDrawPolygonList(byte[] file, int address) { Header = ByteConverter.ToUInt16(file, address); }
public PolyChunkBitsMipmapDAdjust(byte[] file, int address) { Header = ByteConverter.ToUInt16(file, address); }
public PolyChunkBitsBlendAlpha(byte[] file, int address) { Header = ByteConverter.ToUInt16(file, address); }
public PolyChunkEnd(byte[] file, int address) { Header = ByteConverter.ToUInt16(file, address); }
public void SaveToFile(string filename, LandTableFormat format, bool nometa = false) { bool be = ByteConverter.BigEndian; ByteConverter.BigEndian = false; if (format == LandTableFormat.SADX) { format = LandTableFormat.SA1; } List <byte> file = new List <byte>(); ulong magic; switch (format) { case LandTableFormat.SA1: magic = SA1LVLVer; break; case LandTableFormat.SA2: magic = SA2LVLVer; break; case LandTableFormat.SA2B: magic = SA2BLVLVer; break; default: throw new ArgumentException("Cannot save " + format + " format levels to file!", "format"); } file.AddRange(ByteConverter.GetBytes(magic)); Dictionary <string, uint> labels = new Dictionary <string, uint>(); if (nometa) { TextureList = 0; TextureFileName = ""; } byte[] lvl = GetBytes(0x10, format, labels, out uint addr); file.AddRange(ByteConverter.GetBytes(addr + 0x10)); file.AddRange(ByteConverter.GetBytes(lvl.Length + 0x10)); file.AddRange(lvl); if (!nometa) { if (labels.Count > 0) { List <byte> chunk = new List <byte>(labels.Count * 8); int straddr = (labels.Count * 8) + 8; List <byte> strbytes = new List <byte>(); foreach (KeyValuePair <string, uint> label in labels) { chunk.AddRange(ByteConverter.GetBytes(label.Value)); chunk.AddRange(ByteConverter.GetBytes(straddr + strbytes.Count)); strbytes.AddRange(Encoding.UTF8.GetBytes(label.Key)); strbytes.Add(0); strbytes.Align(4); } chunk.AddRange(ByteConverter.GetBytes(-1L)); chunk.AddRange(strbytes); file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Label)); file.AddRange(ByteConverter.GetBytes(chunk.Count)); file.AddRange(chunk); } if (!string.IsNullOrEmpty(Author)) { List <byte> chunk = new List <byte>(Author.Length + 1); chunk.AddRange(Encoding.UTF8.GetBytes(Author)); chunk.Add(0); chunk.Align(4); file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Author)); file.AddRange(ByteConverter.GetBytes(chunk.Count)); file.AddRange(chunk); } if (!string.IsNullOrEmpty(Description)) { List <byte> chunk = new List <byte>(Description.Length + 1); chunk.AddRange(Encoding.UTF8.GetBytes(Description)); chunk.Add(0); chunk.Align(4); file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Description)); file.AddRange(ByteConverter.GetBytes(chunk.Count)); file.AddRange(chunk); } foreach (KeyValuePair <uint, byte[]> item in Metadata) { file.AddRange(ByteConverter.GetBytes(item.Key)); file.AddRange(ByteConverter.GetBytes(item.Value.Length)); file.AddRange(item.Value); } } file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.End)); file.AddRange(new byte[4]); File.WriteAllBytes(filename, file.ToArray()); ByteConverter.BigEndian = be; }
public Event(string filename) { byte[] fc; if (Path.GetExtension(filename).Equals(".prs", StringComparison.OrdinalIgnoreCase)) { fc = Prs.Decompress(filename); } else { fc = File.ReadAllBytes(filename); } bool battle = false; bool dcbeta = false; uint key; if (fc[0] == 0x81) { if (fc[0x2B] <= 0x01 && fc[0x2A] == 0) { ByteConverter.BigEndian = true; key = 0x8125FE60; battle = true; } else { ByteConverter.BigEndian = true; key = 0x812FFE60; } } else { if ((fc[37] == 0x25) || (fc[38] == 0x22) || ((fc[36] == 0) && ((fc[1] == 0xFE) || (fc[1] == 0xF2) || ((fc[1] == 0x27) && fc[2] == 0x9F)))) { ByteConverter.BigEndian = false; key = 0xC600000; dcbeta = true; } else { ByteConverter.BigEndian = false; key = 0xC600000; } } List <NJS_MOTION> motions = null; if (battle) { motions = ReadMotionFile(Path.ChangeExtension(filename, null) + "motion.bin"); } Dictionary <string, NJS_OBJECT> models = new Dictionary <string, NJS_OBJECT>(); int ptr = fc.GetPointer(0x20, key); if (ptr != 0) { if (!dcbeta) { int cnt = battle ? 18 : 16; Upgrades = new EventUpgrade[cnt]; for (int i = 0; i < cnt; i++) { Upgrades[i] = new EventUpgrade(fc, ptr, key, models); ptr += EventUpgrade.Size; } } else { int cnt = 14; Upgrades = new EventUpgrade[cnt]; for (int i = 0; i < cnt; i++) { Upgrades[i] = new EventUpgrade(fc, ptr, key, models); ptr += EventUpgrade.Size; } } } int gcnt = ByteConverter.ToInt32(fc, 8); ptr = fc.GetPointer(0, key); if (ptr != 0) { Scenes = new List <EventScene>(); for (int gn = 0; gn <= gcnt; gn++) { Scenes.Add(new EventScene(fc, ptr, key, battle, models, motions)); ptr += EventScene.Size; } } }
public LandTable(byte[] file, int address, uint imageBase, LandTableFormat format, Dictionary <int, string> labels) { Format = format; if (labels.ContainsKey(address)) { Name = labels[address]; } else { Name = "landtable_" + address.ToString("X8"); } short colcnt = ByteConverter.ToInt16(file, address); Dictionary <int, Attach> attaches = new Dictionary <int, Attach>(); switch (format) { case LandTableFormat.SA1: case LandTableFormat.SADX: short anicnt = ByteConverter.ToInt16(file, address + 2); Attributes = (SA1LandtableAttributes)ByteConverter.ToInt16(file, address + 4); Flags = ByteConverter.ToInt16(file, address + 6); FarClipping = ByteConverter.ToSingle(file, address + 8); COL = new List <COL>(); int tmpaddr = ByteConverter.ToInt32(file, address + 0xC); if (tmpaddr != 0) { tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase); if (labels.ContainsKey(tmpaddr)) { COLName = labels[tmpaddr]; } else { COLName = "collist_" + tmpaddr.ToString("X8"); } for (int i = 0; i < colcnt; i++) { COL.Add(new COL(file, tmpaddr, imageBase, format, labels, attaches)); tmpaddr += SAModel.COL.Size(format); } } else { COLName = "collist_" + Extensions.GenerateIdentifier(); } Anim = new List <GeoAnimData>(); tmpaddr = ByteConverter.ToInt32(file, address + 0x10); if (tmpaddr != 0) { tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase); if (labels.ContainsKey(tmpaddr)) { AnimName = labels[tmpaddr]; } else { AnimName = "animlist_" + tmpaddr.ToString("X8"); } for (int i = 0; i < anicnt; i++) { Anim.Add(new GeoAnimData(file, tmpaddr, imageBase, format, labels, attaches)); tmpaddr += GeoAnimData.Size; } } else { AnimName = "animlist_" + Extensions.GenerateIdentifier(); } tmpaddr = ByteConverter.ToInt32(file, address + 0x14); if (tmpaddr != 0) { tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase); TextureFileName = file.GetCString(tmpaddr, Encoding.ASCII); } TextureList = ByteConverter.ToUInt32(file, address + 0x18); BinaryFilename = ByteConverter.ToInt32(file, address + 0x1C); BinaryLoadFunction = ByteConverter.ToInt32(file, address + 0x20); break; case LandTableFormat.SA2: case LandTableFormat.SA2B: short cnkcnt = ByteConverter.ToInt16(file, address + 2); FarClipping = ByteConverter.ToSingle(file, address + 0xC); COL = new List <COL>(); tmpaddr = ByteConverter.ToInt32(file, address + 0x10); if (tmpaddr != 0) { tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase); if (labels.ContainsKey(tmpaddr)) { COLName = labels[tmpaddr]; } else { COLName = "collist_" + tmpaddr.ToString("X8"); } for (int i = 0; i < colcnt; i++) { COL.Add(new COL(file, tmpaddr, imageBase, format, labels, cnkcnt < 0 ? null : (bool?)(i >= cnkcnt), attaches)); tmpaddr += SAModel.COL.Size(format); } } else { COLName = "collist_" + Extensions.GenerateIdentifier(); } Anim = new List <GeoAnimData>(); AnimName = "animlist_" + Extensions.GenerateIdentifier(); tmpaddr = ByteConverter.ToInt32(file, address + 0x18); if (tmpaddr != 0) { tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase); TextureFileName = file.GetCString(tmpaddr, Encoding.ASCII); } TextureList = ByteConverter.ToUInt32(file, address + 0x1C); break; } Metadata = new Dictionary <uint, byte[]>(); }
public byte[] NJGetBytes(uint imageBase, bool DX, Dictionary <string, uint> labels, List <uint> njOffsets, out uint address) { List <byte> result = new List <byte>(); ObjectFlags flags = GetFlags(); FixSiblings(); int attachAddressAddress = result.Count + 0x4; int childAddressAddress = result.Count + 0x2C; int siblingAddressAddress = result.Count + 0x30; address = 0; result.AddRange(ByteConverter.GetBytes((int)flags)); result.AddRange(ByteConverter.GetBytes(0)); //Attach placeholder result.AddRange(Position.GetBytes()); result.AddRange(Rotation.GetBytes()); result.AddRange(Scale.GetBytes()); result.AddRange(ByteConverter.GetBytes(0)); //Child placeholder result.AddRange(ByteConverter.GetBytes(0)); //Sibling placeholder result.Align(4); int currentEnd = result.Count; if (Attach != null) { if (labels.ContainsKey(Attach.Name)) { int attachAddress = (int)labels[Attach.Name]; result.SetByteListInt(attachAddressAddress, attachAddress); } else { result.AddRange(Attach.GetBytes((uint)(imageBase + result.Count), DX, labels, njOffsets, out uint attachAddress)); result.SetByteListInt(attachAddressAddress, (int)(imageBase + currentEnd + attachAddress)); njOffsets.Add((uint)(imageBase + attachAddressAddress)); result.Align(4); currentEnd = result.Count; } } if (Children.Count > 0) { if (labels.ContainsKey(Children[0].Name)) { int childAddress = (int)labels[Children[0].Name]; result.SetByteListInt(childAddressAddress, childAddress); } else { result.AddRange(Children[0].NJGetBytes((uint)(imageBase + result.Count), DX, labels, njOffsets, out uint childAddress)); result.SetByteListInt(childAddressAddress, (int)(imageBase + currentEnd + childAddress)); njOffsets.Add((uint)(imageBase + childAddressAddress)); result.Align(4); currentEnd = result.Count; } } if (Sibling != null) { if (labels.ContainsKey(Sibling.Name)) { int siblingAddress = (int)labels[Sibling.Name]; result.SetByteListInt(siblingAddressAddress, siblingAddress); } else { result.AddRange(Sibling.NJGetBytes((uint)(imageBase + result.Count), DX, labels, njOffsets, out uint siblingAddress)); result.SetByteListInt(siblingAddressAddress, (int)(imageBase + currentEnd + siblingAddress)); njOffsets.Add((uint)(imageBase + siblingAddressAddress)); result.Align(4); } } labels.Add(Name, address + imageBase); return(result.ToArray()); }
public byte[] GetBytes(uint imageBase, bool DX, Dictionary <string, uint> labels, List <uint> njOffsets, out uint address, bool isFirst = false) { List <byte> result = new List <byte>(); if (isFirst) { result.AddRange(new byte[0x34]); //Add size of NGS_OBJECT if first since we're inserting later } FixSiblings(); uint childaddr = 0; uint siblingaddr = 0; uint attachaddr = 0; byte[] tmpbyte; if (Children.Count > 0) { if (labels.ContainsKey(Children[0].Name)) { childaddr = labels[Children[0].Name]; } else { result.Align(4); tmpbyte = Children[0].GetBytes(imageBase + (uint)result.Count, DX, labels, njOffsets, out childaddr); childaddr += imageBase + (uint)result.Count; result.AddRange(tmpbyte); } } if (Sibling != null) { if (labels.ContainsKey(Sibling.Name)) { siblingaddr = labels[Sibling.Name]; } else { result.Align(4); tmpbyte = Sibling.GetBytes(imageBase + (uint)result.Count, DX, labels, njOffsets, out siblingaddr); siblingaddr += imageBase + (uint)result.Count; result.AddRange(tmpbyte); } } if (Attach != null) { if (labels.ContainsKey(Attach.Name)) { attachaddr = labels[Attach.Name]; } else { result.Align(4); tmpbyte = Attach.GetBytes(imageBase + (uint)result.Count, DX, labels, njOffsets, out attachaddr); attachaddr += imageBase + (uint)result.Count; result.AddRange(tmpbyte); } } result.Align(4); address = isFirst ? 0 : (uint)result.Count; ObjectFlags flags = GetFlags(); List <byte> objBytes = new List <byte>(); objBytes.AddRange(ByteConverter.GetBytes((int)flags)); objBytes.AddRange(ByteConverter.GetBytes(attachaddr)); objBytes.AddRange(Position.GetBytes()); objBytes.AddRange(Rotation.GetBytes()); objBytes.AddRange(Scale.GetBytes()); objBytes.AddRange(ByteConverter.GetBytes(childaddr)); objBytes.AddRange(ByteConverter.GetBytes(siblingaddr)); if (isFirst) //Formal ninja requires the initial object first since there's not a pointer to it { //POF0 if (attachaddr != 0) { njOffsets.Add(0x4); } if (childaddr != 0) { njOffsets.Add(0x2C); } if (siblingaddr != 0) { njOffsets.Add(0x30); } result.RemoveRange(0, 0x34); result.InsertRange(0, objBytes); } else { //POF0 if (attachaddr != 0) { njOffsets.Add((uint)(imageBase + result.Count)); } if (childaddr != 0) { njOffsets.Add((uint)(imageBase + result.Count)); } if (siblingaddr != 0) { njOffsets.Add((uint)(imageBase + result.Count)); } result.AddRange(objBytes); } labels.Add(Name, address + imageBase); return(result.ToArray()); }
public byte[] GetBytes() { VertexChunk next = null; int vertlimit; int vertcount = Vertices.Count; switch (Type) { case ChunkType.Vertex_VertexSH: vertlimit = 65535 / 4; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexNormalSH: vertlimit = 65535 / 8; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), Normals = Normals.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_Vertex: vertlimit = 65535 / 3; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexDiffuse8: vertlimit = 65535 / 4; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), Diffuse = Diffuse.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexUserFlags: vertlimit = 65535 / 4; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), UserFlags = UserFlags.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexNinjaFlags: vertlimit = 65535 / 4; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), NinjaFlags = NinjaFlags.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexDiffuseSpecular5: case ChunkType.Vertex_VertexDiffuseSpecular4: vertlimit = 65535 / 4; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), Diffuse = Diffuse.Skip(vertlimit).ToList(), Specular = Specular.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexNormal: vertlimit = 65535 / 6; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), Normals = Normals.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexNormalDiffuse8: vertlimit = 65535 / 7; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), Normals = Normals.Skip(vertlimit).ToList(), Diffuse = Diffuse.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexNormalUserFlags: vertlimit = 65535 / 7; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), Normals = Normals.Skip(vertlimit).ToList(), UserFlags = UserFlags.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexNormalNinjaFlags: vertlimit = 65535 / 7; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), Normals = Normals.Skip(vertlimit).ToList(), NinjaFlags = NinjaFlags.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.Vertex_VertexNormalDiffuseSpecular5: case ChunkType.Vertex_VertexNormalDiffuseSpecular4: vertlimit = 65535 / 7; if (Vertices.Count > vertlimit) { next = new VertexChunk(Type) { Vertices = Vertices.Skip(vertlimit).ToList(), Normals = Normals.Skip(vertlimit).ToList(), Diffuse = Diffuse.Skip(vertlimit).ToList(), Specular = Specular.Skip(vertlimit).ToList() }; vertcount = vertlimit; } break; case ChunkType.End: break; default: throw new NotSupportedException("Unsupported chunk type " + Type + "."); } SetVertCount(vertcount); switch (Type) { case ChunkType.Vertex_Vertex: Size = (ushort)(vertcount * 3 + 1); break; case ChunkType.Vertex_VertexSH: case ChunkType.Vertex_VertexDiffuse8: case ChunkType.Vertex_VertexUserFlags: case ChunkType.Vertex_VertexNinjaFlags: case ChunkType.Vertex_VertexDiffuseSpecular5: case ChunkType.Vertex_VertexDiffuseSpecular4: Size = (ushort)(vertcount * 4 + 1); break; case ChunkType.Vertex_VertexNormal: Size = (ushort)(vertcount * 6 + 1); break; case ChunkType.Vertex_VertexNormalDiffuse8: case ChunkType.Vertex_VertexNormalUserFlags: case ChunkType.Vertex_VertexNormalNinjaFlags: case ChunkType.Vertex_VertexNormalDiffuseSpecular5: case ChunkType.Vertex_VertexNormalDiffuseSpecular4: Size = (ushort)(vertcount * 7 + 1); break; case ChunkType.Vertex_VertexNormalSH: Size = (ushort)(vertcount * 8 + 1); break; } List <byte> result = new List <byte>((Size * 4) + 4); result.AddRange(ByteConverter.GetBytes(Header1)); result.AddRange(ByteConverter.GetBytes(Header2)); for (int i = 0; i < vertcount; i++) { switch (Type) { case ChunkType.Vertex_VertexSH: result.AddRange(Vertices[i].GetBytes()); result.AddRange(ByteConverter.GetBytes(1.0f)); break; case ChunkType.Vertex_VertexNormalSH: result.AddRange(Vertices[i].GetBytes()); result.AddRange(ByteConverter.GetBytes(1.0f)); result.AddRange(Normals[i].GetBytes()); result.AddRange(ByteConverter.GetBytes(1.0f)); break; case ChunkType.Vertex_Vertex: result.AddRange(Vertices[i].GetBytes()); break; case ChunkType.Vertex_VertexDiffuse8: result.AddRange(Vertices[i].GetBytes()); result.AddRange(VColor.GetBytes(Diffuse[i], ColorType.ARGB8888_32)); break; case ChunkType.Vertex_VertexUserFlags: result.AddRange(Vertices[i].GetBytes()); result.AddRange(ByteConverter.GetBytes(UserFlags[i])); break; case ChunkType.Vertex_VertexNinjaFlags: result.AddRange(Vertices[i].GetBytes()); result.AddRange(ByteConverter.GetBytes(NinjaFlags[i])); break; case ChunkType.Vertex_VertexDiffuseSpecular5: result.AddRange(Vertices[i].GetBytes()); result.AddRange(ByteConverter.GetBytes( ByteConverter.ToUInt16(VColor.GetBytes(Diffuse[i], ColorType.RGB565), 0) | (ByteConverter.ToUInt16(VColor.GetBytes(Specular[i], ColorType.RGB565), 0) << 16))); break; case ChunkType.Vertex_VertexDiffuseSpecular4: result.AddRange(Vertices[i].GetBytes()); result.AddRange(ByteConverter.GetBytes( ByteConverter.ToUInt16(VColor.GetBytes(Diffuse[i], ColorType.ARGB4444), 0) | (ByteConverter.ToUInt16(VColor.GetBytes(Specular[i], ColorType.RGB565), 0) << 16))); break; case ChunkType.Vertex_VertexNormal: result.AddRange(Vertices[i].GetBytes()); result.AddRange(Normals[i].GetBytes()); break; case ChunkType.Vertex_VertexNormalDiffuse8: result.AddRange(Vertices[i].GetBytes()); result.AddRange(Normals[i].GetBytes()); result.AddRange(VColor.GetBytes(Diffuse[i], ColorType.ARGB8888_32)); break; case ChunkType.Vertex_VertexNormalUserFlags: result.AddRange(Vertices[i].GetBytes()); result.AddRange(Normals[i].GetBytes()); result.AddRange(ByteConverter.GetBytes(UserFlags[i])); break; case ChunkType.Vertex_VertexNormalNinjaFlags: result.AddRange(Vertices[i].GetBytes()); result.AddRange(Normals[i].GetBytes()); result.AddRange(ByteConverter.GetBytes(NinjaFlags[i])); break; case ChunkType.Vertex_VertexNormalDiffuseSpecular5: result.AddRange(Vertices[i].GetBytes()); result.AddRange(Normals[i].GetBytes()); result.AddRange(ByteConverter.GetBytes( ByteConverter.ToUInt16(VColor.GetBytes(Diffuse[i], ColorType.RGB565), 0) | (ByteConverter.ToUInt16(VColor.GetBytes(Specular[i], ColorType.RGB565), 0) << 16))); break; case ChunkType.Vertex_VertexNormalDiffuseSpecular4: result.AddRange(Vertices[i].GetBytes()); result.AddRange(Normals[i].GetBytes()); result.AddRange(ByteConverter.GetBytes( ByteConverter.ToUInt16(VColor.GetBytes(Diffuse[i], ColorType.ARGB4444), 0) | (ByteConverter.ToUInt16(VColor.GetBytes(Specular[i], ColorType.RGB565), 0) << 16))); break; } } if (next != null) { result.AddRange(next.GetBytes()); } return(result.ToArray()); }
public PolyChunkMaterial(byte[] file, int address) { Header = ByteConverter.ToUInt16(file, address); address += sizeof(ushort); Size = ByteConverter.ToUInt16(file, address); address += sizeof(ushort); switch (Type) { case ChunkType.Material_Diffuse: case ChunkType.Material_DiffuseAmbient: case ChunkType.Material_DiffuseSpecular: case ChunkType.Material_DiffuseAmbientSpecular: case ChunkType.Material_Diffuse2: case ChunkType.Material_DiffuseAmbient2: case ChunkType.Material_DiffuseSpecular2: case ChunkType.Material_DiffuseAmbientSpecular2: Diffuse = VColor.FromBytes(file, address, ColorType.ARGB8888_16); address += VColor.Size(ColorType.ARGB8888_16); break; } switch (Type) { case ChunkType.Material_Ambient: case ChunkType.Material_DiffuseAmbient: case ChunkType.Material_AmbientSpecular: case ChunkType.Material_DiffuseAmbientSpecular: case ChunkType.Material_Ambient2: case ChunkType.Material_DiffuseAmbient2: case ChunkType.Material_AmbientSpecular2: case ChunkType.Material_DiffuseAmbientSpecular2: Ambient = VColor.FromBytes(file, address, ColorType.XRGB8888_16); address += VColor.Size(ColorType.XRGB8888_16); break; } switch (Type) { case ChunkType.Material_Specular: case ChunkType.Material_DiffuseSpecular: case ChunkType.Material_AmbientSpecular: case ChunkType.Material_DiffuseAmbientSpecular: case ChunkType.Material_Specular2: case ChunkType.Material_DiffuseSpecular2: case ChunkType.Material_AmbientSpecular2: case ChunkType.Material_DiffuseAmbientSpecular2: Specular = VColor.FromBytes(file, address, ColorType.XRGB8888_16); SpecularExponent = (byte)(ByteConverter.ToUInt16(file, address + 2) >> 8); address += VColor.Size(ColorType.XRGB8888_16); break; } switch (Type) { case ChunkType.Material_Diffuse2: case ChunkType.Material_Ambient2: case ChunkType.Material_DiffuseAmbient2: case ChunkType.Material_Specular2: case ChunkType.Material_DiffuseSpecular2: case ChunkType.Material_AmbientSpecular2: case ChunkType.Material_DiffuseAmbientSpecular2: Second = true; break; } }
public Strip(byte[] file, int address, ChunkType type, byte userFlags) { Indexes = new ushort[Math.Abs(ByteConverter.ToInt16(file, address))]; Reversed = (ByteConverter.ToUInt16(file, address) & 0x8000) == 0x8000; address += 2; switch (type) { case ChunkType.Strip_StripUVN: case ChunkType.Strip_StripUVH: case ChunkType.Strip_StripUVN2: case ChunkType.Strip_StripUVH2: UVs = new UV[Indexes.Length]; break; case ChunkType.Strip_StripColor: VColors = new Color[Indexes.Length]; break; case ChunkType.Strip_StripUVNColor: case ChunkType.Strip_StripUVHColor: UVs = new UV[Indexes.Length]; VColors = new Color[Indexes.Length]; break; } if (userFlags > 0) { UserFlags1 = new ushort[Indexes.Length - 2]; } if (userFlags > 1) { UserFlags2 = new ushort[Indexes.Length - 2]; } if (userFlags > 2) { UserFlags3 = new ushort[Indexes.Length - 2]; } for (int i = 0; i < Indexes.Length; i++) { Indexes[i] = ByteConverter.ToUInt16(file, address); address += 2; switch (type) { case ChunkType.Strip_StripUVN: case ChunkType.Strip_StripUVNColor: case ChunkType.Strip_StripUVN2: UVs[i] = new UV(file, address, false, true); address += UV.Size; break; case ChunkType.Strip_StripUVH: case ChunkType.Strip_StripUVHColor: case ChunkType.Strip_StripUVH2: UVs[i] = new UV(file, address, true, true); address += UV.Size; break; } switch (type) { case ChunkType.Strip_StripColor: case ChunkType.Strip_StripUVNColor: case ChunkType.Strip_StripUVHColor: VColors[i] = VColor.FromBytes(file, address, ColorType.ARGB8888_16); address += VColor.Size(ColorType.ARGB8888_16); break; } if (i > 1) { if (userFlags > 0) { UserFlags1[i - 2] = ByteConverter.ToUInt16(file, address); address += 2; if (userFlags > 1) { UserFlags2[i - 2] = ByteConverter.ToUInt16(file, address); address += 2; if (userFlags > 2) { UserFlags3[i - 2] = ByteConverter.ToUInt16(file, address); address += 2; } } } } } }
public VertexChunk(byte[] file, int address) : this() { Header1 = ByteConverter.ToUInt32(file, address); Header2 = ByteConverter.ToUInt32(file, address + 4); address += 8; for (int i = 0; i < GetVertCount(); i++) { switch (Type) { case ChunkType.Vertex_VertexSH: Vertices.Add(new Vertex(file, address)); address += Vertex.Size + sizeof(float); break; case ChunkType.Vertex_VertexNormalSH: Vertices.Add(new Vertex(file, address)); address += Vertex.Size + sizeof(float); Normals.Add(new Vertex(file, address)); address += Vertex.Size + sizeof(float); break; case ChunkType.Vertex_Vertex: Vertices.Add(new Vertex(file, address)); address += Vertex.Size; break; case ChunkType.Vertex_VertexDiffuse8: Vertices.Add(new Vertex(file, address)); address += Vertex.Size; Diffuse.Add(VColor.FromBytes(file, address, ColorType.ARGB8888_32)); address += VColor.Size(ColorType.ARGB8888_32); break; case ChunkType.Vertex_VertexUserFlags: Vertices.Add(new Vertex(file, address)); address += Vertex.Size; UserFlags.Add(ByteConverter.ToUInt32(file, address)); address += sizeof(uint); break; case ChunkType.Vertex_VertexNinjaFlags: Vertices.Add(new Vertex(file, address)); address += Vertex.Size; NinjaFlags.Add(ByteConverter.ToUInt32(file, address)); address += sizeof(uint); break; case ChunkType.Vertex_VertexDiffuseSpecular5: Vertices.Add(new Vertex(file, address)); address += Vertex.Size; uint tmpcolor = ByteConverter.ToUInt32(file, address); address += sizeof(uint); Diffuse.Add(VColor.FromBytes(ByteConverter.GetBytes((ushort)(tmpcolor & 0xFFFF)), 0, ColorType.RGB565)); Specular.Add(VColor.FromBytes(ByteConverter.GetBytes((ushort)(tmpcolor >> 16)), 0, ColorType.RGB565)); break; case ChunkType.Vertex_VertexDiffuseSpecular4: Vertices.Add(new Vertex(file, address)); address += Vertex.Size; tmpcolor = ByteConverter.ToUInt32(file, address); address += sizeof(uint); Diffuse.Add(VColor.FromBytes(ByteConverter.GetBytes((ushort)(tmpcolor & 0xFFFF)), 0, ColorType.ARGB4444)); Specular.Add(VColor.FromBytes(ByteConverter.GetBytes((ushort)(tmpcolor >> 16)), 0, ColorType.RGB565)); break; case ChunkType.Vertex_VertexNormal: Vertices.Add(new Vertex(file, address)); address += Vertex.Size; Normals.Add(new Vertex(file, address)); address += Vertex.Size; break; case ChunkType.Vertex_VertexNormalDiffuse8: Vertices.Add(new Vertex(file, address)); address += Vertex.Size; Normals.Add(new Vertex(file, address)); address += Vertex.Size; Diffuse.Add(VColor.FromBytes(file, address, ColorType.ARGB8888_32)); address += VColor.Size(ColorType.ARGB8888_32); break; case ChunkType.Vertex_VertexNormalUserFlags: Vertices.Add(new Vertex(file, address)); address += Vertex.Size; Normals.Add(new Vertex(file, address)); address += Vertex.Size; UserFlags.Add(ByteConverter.ToUInt32(file, address)); address += sizeof(uint); break; case ChunkType.Vertex_VertexNormalNinjaFlags: Vertices.Add(new Vertex(file, address)); address += Vertex.Size; Normals.Add(new Vertex(file, address)); address += Vertex.Size; NinjaFlags.Add(ByteConverter.ToUInt32(file, address)); address += sizeof(uint); break; case ChunkType.Vertex_VertexNormalDiffuseSpecular5: Vertices.Add(new Vertex(file, address)); address += Vertex.Size; Normals.Add(new Vertex(file, address)); address += Vertex.Size; tmpcolor = ByteConverter.ToUInt32(file, address); address += sizeof(uint); Diffuse.Add(VColor.FromBytes(ByteConverter.GetBytes((ushort)(tmpcolor & 0xFFFF)), 0, ColorType.RGB565)); Specular.Add(VColor.FromBytes(ByteConverter.GetBytes((ushort)(tmpcolor >> 16)), 0, ColorType.RGB565)); break; case ChunkType.Vertex_VertexNormalDiffuseSpecular4: Vertices.Add(new Vertex(file, address)); address += Vertex.Size; Normals.Add(new Vertex(file, address)); address += Vertex.Size; tmpcolor = ByteConverter.ToUInt32(file, address); address += sizeof(uint); Diffuse.Add(VColor.FromBytes(ByteConverter.GetBytes((ushort)(tmpcolor & 0xFFFF)), 0, ColorType.ARGB4444)); Specular.Add(VColor.FromBytes(ByteConverter.GetBytes((ushort)(tmpcolor >> 16)), 0, ColorType.RGB565)); break; default: throw new NotSupportedException("Unsupported chunk type " + Type + " at " + address.ToString("X8") + "."); } } }
private NJS_OBJECT(byte[] file, int address, uint imageBase, ModelFormat format, NJS_OBJECT parent, Dictionary <int, string> labels, Dictionary <int, Attach> attaches) { if (labels.ContainsKey(address)) { Name = labels[address]; } else { Name = "object_" + address.ToString("X8"); } if (address > file.Length - 52) { Position = new Vertex(); Rotation = new Rotation(); Scale = new Vertex(1, 1, 1); children = new List <NJS_OBJECT>(); Children = new ReadOnlyCollection <NJS_OBJECT>(children); return; } ObjectFlags flags = (ObjectFlags)ByteConverter.ToInt32(file, address); RotateZYX = (flags & ObjectFlags.RotateZYX) == ObjectFlags.RotateZYX; SkipDraw = (flags & ObjectFlags.NoDisplay) == ObjectFlags.NoDisplay; SkipChildren = (flags & ObjectFlags.NoChildren) == ObjectFlags.NoChildren; IgnorePosition = (flags & ObjectFlags.NoPosition) == ObjectFlags.NoPosition; IgnoreRotation = (flags & ObjectFlags.NoRotate) == ObjectFlags.NoRotate; IgnoreScale = (flags & ObjectFlags.NoScale) == ObjectFlags.NoScale; Animate = (flags & ObjectFlags.NoAnimate) == 0; Morph = (flags & ObjectFlags.NoMorph) == 0; int tmpaddr = ByteConverter.ToInt32(file, address + 4); if (tmpaddr != 0) { tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase); if (attaches != null && attaches.ContainsKey(tmpaddr)) { Attach = attaches[tmpaddr]; } else { Attach = Attach.Load(file, tmpaddr, imageBase, format, labels); if (attaches != null) { attaches.Add(tmpaddr, Attach); } } } Position = new Vertex(file, address + 8); Rotation = new Rotation(file, address + 0x14); Scale = new Vertex(file, address + 0x20); Parent = parent; children = new List <NJS_OBJECT>(); Children = new ReadOnlyCollection <NJS_OBJECT>(children); NJS_OBJECT child = null; tmpaddr = ByteConverter.ToInt32(file, address + 0x2C); if (tmpaddr != 0) { tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase); child = new NJS_OBJECT(file, tmpaddr, imageBase, format, this, labels, attaches); } while (child != null) { children.Add(child); child = child.Sibling; } tmpaddr = ByteConverter.ToInt32(file, address + 0x30); if (tmpaddr != 0) { tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase); Sibling = new NJS_OBJECT(file, tmpaddr, imageBase, format, parent, labels, attaches); } //Assimp.AssimpContext context = new AssimpContext(); //Scene scene = context.ImportFile("F:\\untitled.obj", PostProcessSteps.Triangulate); //AssimpLoad(scene, scene.RootNode); }