├── .gitattributes ├── .gitignore ├── LICENSE.md ├── N3DSCmbViewer.sln ├── N3DSCmbViewer ├── ArchiveFile.cs ├── BaseCTRChunk.cs ├── Cmb │ ├── CmbChunk.cs │ ├── Constants.cs │ ├── ExportCollada.cs │ ├── MatsChunk.cs │ ├── ModelHandler.cs │ ├── MshsChunk.cs │ ├── PrmChunk.cs │ ├── PrmsChunk.cs │ ├── SepdChunk.cs │ ├── ShpChunk.cs │ ├── SklChunk.cs │ ├── SklmChunk.cs │ ├── TexChunk.cs │ └── VatrChunk.cs ├── Csab │ ├── AnimHandler.cs │ ├── AnimNode.cs │ ├── Animation.cs │ └── CsabChunk.cs ├── ETC1Lib.dll ├── Extensions.cs ├── LZSS.cs ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── N3DSCmbViewer.csproj ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Resources │ └── dummytexture.png ├── Shaders │ ├── DVLB.cs │ ├── DVLE.cs │ └── DVLP.cs ├── TreeViewEx.cs ├── Win32.cs ├── ZSI │ ├── Actor.cs │ ├── Setup.cs │ └── ZSIHandler.cs ├── app.config ├── general-fs.glsl └── general-vs.glsl └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 xdaniel (Daniel R.) / DigitalZero Domain 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /N3DSCmbViewer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C# Express 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "N3DSCmbViewer", "N3DSCmbViewer\N3DSCmbViewer.csproj", "{BA569D8C-09D3-4BFC-B49F-7432A5FC7139}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aglex", "..\Aglex\Aglex\Aglex.csproj", "{A3F8E581-B021-48CE-934F-79F070D64821}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|Mixed Platforms = Debug|Mixed Platforms 12 | Debug|x86 = Debug|x86 13 | Release|Any CPU = Release|Any CPU 14 | Release|Mixed Platforms = Release|Mixed Platforms 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {BA569D8C-09D3-4BFC-B49F-7432A5FC7139}.Debug|Any CPU.ActiveCfg = Debug|x86 19 | {BA569D8C-09D3-4BFC-B49F-7432A5FC7139}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 20 | {BA569D8C-09D3-4BFC-B49F-7432A5FC7139}.Debug|Mixed Platforms.Build.0 = Debug|x86 21 | {BA569D8C-09D3-4BFC-B49F-7432A5FC7139}.Debug|x86.ActiveCfg = Debug|x86 22 | {BA569D8C-09D3-4BFC-B49F-7432A5FC7139}.Debug|x86.Build.0 = Debug|x86 23 | {BA569D8C-09D3-4BFC-B49F-7432A5FC7139}.Release|Any CPU.ActiveCfg = Release|x86 24 | {BA569D8C-09D3-4BFC-B49F-7432A5FC7139}.Release|Mixed Platforms.ActiveCfg = Release|x86 25 | {BA569D8C-09D3-4BFC-B49F-7432A5FC7139}.Release|Mixed Platforms.Build.0 = Release|x86 26 | {BA569D8C-09D3-4BFC-B49F-7432A5FC7139}.Release|x86.ActiveCfg = Release|x86 27 | {BA569D8C-09D3-4BFC-B49F-7432A5FC7139}.Release|x86.Build.0 = Release|x86 28 | {A3F8E581-B021-48CE-934F-79F070D64821}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {A3F8E581-B021-48CE-934F-79F070D64821}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {A3F8E581-B021-48CE-934F-79F070D64821}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 31 | {A3F8E581-B021-48CE-934F-79F070D64821}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 32 | {A3F8E581-B021-48CE-934F-79F070D64821}.Debug|x86.ActiveCfg = Debug|Any CPU 33 | {A3F8E581-B021-48CE-934F-79F070D64821}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {A3F8E581-B021-48CE-934F-79F070D64821}.Release|Any CPU.Build.0 = Release|Any CPU 35 | {A3F8E581-B021-48CE-934F-79F070D64821}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 36 | {A3F8E581-B021-48CE-934F-79F070D64821}.Release|Mixed Platforms.Build.0 = Release|Any CPU 37 | {A3F8E581-B021-48CE-934F-79F070D64821}.Release|x86.ActiveCfg = Release|Any CPU 38 | EndGlobalSection 39 | GlobalSection(SolutionProperties) = preSolution 40 | HideSolutionNode = FALSE 41 | EndGlobalSection 42 | EndGlobal 43 | -------------------------------------------------------------------------------- /N3DSCmbViewer/ArchiveFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.IO; 6 | 7 | namespace N3DSCmbViewer 8 | { 9 | class ArchiveFile 10 | { 11 | // http://pastebin.com/Dw7KRdSE by Twili 12 | // https://github.com/lue/MM3D/blob/master/src/gar.cpp by lue 13 | 14 | const uint magicWordZAR = 0x0152415A; //"ZAR\x01" swapped 15 | const uint magicWordGAR = 0x02524147; //"GAR\x02" swapped 16 | 17 | public uint MagicWord { get; private set; } 18 | public uint ArchiveSize { get; private set; } 19 | public ushort NumberOfFileTypes { get; private set; } 20 | public ushort NumberOfFiles { get; private set; } 21 | public uint FileTypesOffset { get; private set; } 22 | public uint FileInfoIndexOffset { get; private set; } 23 | public uint FileIndexOffset { get; private set; } 24 | public string CodenameString { get; private set; } 25 | 26 | public FileType[] FileTypes { get; private set; } 27 | public FileInfo[] FileInfos { get; private set; } 28 | public uint[] FileOffsets { get; private set; } 29 | 30 | byte[] archiveData; 31 | 32 | public ArchiveFile(byte[] data) 33 | { 34 | archiveData = data; 35 | Load(); 36 | } 37 | 38 | public ArchiveFile(string fn) 39 | { 40 | BinaryReader br = new BinaryReader(File.Open(fn, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)); 41 | archiveData = new byte[br.BaseStream.Length]; 42 | br.Read(archiveData, 0, archiveData.Length); 43 | br.Close(); 44 | 45 | Load(); 46 | } 47 | 48 | private void Load() 49 | { 50 | MagicWord = BitConverter.ToUInt32(archiveData, 0); 51 | if (MagicWord != magicWordZAR && MagicWord != magicWordGAR) 52 | throw new Exception(string.Format("Trying to read ZAR or GAR with magic word 0x{0:X8}, expected 0x{1:X8} or 0x{2:X8}.", MagicWord, magicWordZAR, magicWordGAR)); 53 | 54 | ArchiveSize = BitConverter.ToUInt32(archiveData, 0x04); 55 | NumberOfFileTypes = BitConverter.ToUInt16(archiveData, 0x08); 56 | NumberOfFiles = BitConverter.ToUInt16(archiveData, 0x0A); 57 | FileTypesOffset = BitConverter.ToUInt32(archiveData, 0x0C); 58 | FileInfoIndexOffset = BitConverter.ToUInt32(archiveData, 0x10); 59 | FileIndexOffset = BitConverter.ToUInt32(archiveData, 0x14); 60 | CodenameString = Encoding.ASCII.GetString(archiveData, 0x18, 8).TrimEnd('\0'); 61 | 62 | FileTypes = new FileType[NumberOfFileTypes]; 63 | for (int i = 0; i < FileTypes.Length; i++) FileTypes[i] = new FileType(this, archiveData, (int)FileTypesOffset + (i * FileType.SectionSize)); 64 | 65 | FileInfos = new FileInfo[NumberOfFiles]; 66 | for (int i = 0; i < FileInfos.Length; i++) FileInfos[i] = new FileInfo(this, archiveData, (int)FileInfoIndexOffset + (i * (MagicWord == magicWordZAR ? FileInfo.SectionSizeZAR : FileInfo.SectionSizeGAR))); 67 | 68 | FileOffsets = new uint[NumberOfFiles]; 69 | Buffer.BlockCopy(archiveData, (int)FileIndexOffset, FileOffsets, 0, NumberOfFiles * sizeof(uint)); 70 | } 71 | 72 | public byte[] GetFile(uint fileNo) 73 | { 74 | byte[] data = new byte[FileInfos[fileNo].FileSize]; 75 | Buffer.BlockCopy(archiveData, (int)FileOffsets[fileNo], data, 0, data.Length); 76 | return data; 77 | } 78 | 79 | public class FileType 80 | { 81 | public const int SectionSize = 0x10; 82 | 83 | public ArchiveFile ParentArchive { get; private set; } 84 | 85 | public uint NumberOfFilesWithType { get; private set; } 86 | public uint FileNumberIndexOffset { get; private set; } 87 | public uint FileTypeNameOffset { get; private set; } 88 | public uint AssumedConstant { get; private set; } 89 | 90 | public string FileTypeName { get; private set; } 91 | public uint[] FileNumberIndex { get; private set; } 92 | 93 | public FileType(ArchiveFile parent, byte[] data, int offset) 94 | { 95 | ParentArchive = parent; 96 | 97 | NumberOfFilesWithType = BitConverter.ToUInt32(data, offset); 98 | FileNumberIndexOffset = BitConverter.ToUInt32(data, offset + 0x04); 99 | FileTypeNameOffset = BitConverter.ToUInt32(data, offset + 0x08); 100 | AssumedConstant = BitConverter.ToUInt32(data, offset + 0x0C); 101 | 102 | int nameLength = (int)(Array.IndexOf(data, (byte)'\0', (int)FileTypeNameOffset) - FileTypeNameOffset); 103 | if (nameLength > 0) FileTypeName = Encoding.ASCII.GetString(data, (int)FileTypeNameOffset, nameLength).TrimEnd('\0'); 104 | 105 | FileNumberIndex = new uint[NumberOfFilesWithType]; 106 | for (int i = 0; i < FileNumberIndex.Length; i++) FileNumberIndex[i] = BitConverter.ToUInt32(data, (int)(FileNumberIndexOffset + (i * 4))); 107 | } 108 | } 109 | 110 | public class FileInfo 111 | { 112 | public const int SectionSizeZAR = 0x08; 113 | public const int SectionSizeGAR = 0x0C; 114 | 115 | public ArchiveFile ParentArchive { get; private set; } 116 | 117 | public uint FileSize { get; private set; } 118 | public uint FileNameOffset { get; private set; } 119 | public uint FullPathOffset { get; private set; } 120 | 121 | public string FilePath { get; private set; } 122 | 123 | public FileInfo(ArchiveFile parent, byte[] data, int offset) 124 | { 125 | ParentArchive = parent; 126 | 127 | FileSize = BitConverter.ToUInt32(data, offset); 128 | FileNameOffset = BitConverter.ToUInt32(data, offset + 0x04); 129 | 130 | if (ParentArchive.MagicWord == ArchiveFile.magicWordGAR) 131 | { 132 | FullPathOffset = BitConverter.ToUInt32(data, offset + 0x08); 133 | 134 | int nameLength = (int)(Array.IndexOf(data, (byte)'\0', (int)FullPathOffset) - FullPathOffset); 135 | if (nameLength > 0) FilePath = Encoding.ASCII.GetString(data, (int)FullPathOffset, nameLength).TrimEnd('\0'); 136 | } 137 | else 138 | { 139 | int nameLength = (int)(Array.IndexOf(data, (byte)'\0', (int)FileNameOffset) - FileNameOffset); 140 | if (nameLength > 0) FilePath = Encoding.ASCII.GetString(data, (int)FileNameOffset, nameLength).TrimEnd('\0'); 141 | } 142 | } 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /N3DSCmbViewer/BaseCTRChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace N3DSCmbViewer 7 | { 8 | class BaseCTRChunk 9 | { 10 | /* TODO: MAKE THIS NOT STATIC IN HERE, MAKE IT CLEANER, THIS IS A STUPID WORKAROUND */ 11 | public static bool IsMajora3D { get; set; } 12 | 13 | public virtual string ChunkTag { get { return default(string); } } 14 | 15 | public string Tag { get; private set; } 16 | public uint Length { get; private set; } 17 | public byte[] ChunkData { get; private set; } 18 | public BaseCTRChunk Parent { get; private set; } 19 | 20 | public int Offset { get; private set; } 21 | 22 | public BaseCTRChunk(byte[] data, int offset, BaseCTRChunk parent) 23 | { 24 | Offset = (parent != null ? parent.Offset : 0) + offset; 25 | 26 | Tag = Encoding.ASCII.GetString(data, offset, 4).TrimEnd(' '); 27 | CheckTag(); 28 | 29 | /* TODO: CHECK THIS CRAP, MM3D CHUNK LENGTHS ARE TOO SHORT?!? CRAPPY WORKAROUND: MULTIPLY W/ 4 TO TRY AND LOAD MORE DATA */ 30 | Length = (uint)Math.Min(data.Length - offset, BitConverter.ToUInt32(data, offset + 4) * 4); 31 | 32 | ChunkData = new byte[Length]; 33 | Buffer.BlockCopy(data, offset, ChunkData, 0, ChunkData.Length); 34 | 35 | Parent = parent; 36 | } 37 | 38 | public void CheckTag() 39 | { 40 | if (Tag != ChunkTag) throw new Exception(string.Format("Trying to read chunk with tag '{0}' as {1}, expected tag '{2}'", Tag, this.GetType().Name, ChunkTag)); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Cmb/CmbChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | using System.Drawing.Imaging; 7 | 8 | namespace N3DSCmbViewer.Cmb 9 | { 10 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 11 | class CmbChunk : BaseCTRChunk 12 | { 13 | // "CTR Model Binary"? 14 | public override string ChunkTag { get { return "cmb"; } } 15 | 16 | // OoT3D 17 | public const int SklChunkPointer_OoT = 0x24; 18 | public const int MatsChunkPointer_OoT = 0x28; 19 | public const int TexChunkPointer_OoT = 0x2C; 20 | public const int SklmChunkPointer_OoT = 0x30; 21 | public const int LutsChunkPointer_OoT = 0x34; 22 | public const int VatrChunkPointer_OoT = 0x38; 23 | public const int VertexIndicesPointer_OoT = 0x3C; 24 | public const int TextureDataPointer_OoT = 0x40; 25 | 26 | // MM3D 27 | public const int SklChunkPointer_MM = 0x24; 28 | public const int QtrsChunkPointer_MM = 0x28; 29 | public const int MatsChunkPointer_MM = 0x2C; 30 | public const int TexChunkPointer_MM = 0x30; 31 | public const int SklmChunkPointer_MM = 0x34; 32 | public const int LutsChunkPointer_MM = 0x38; 33 | public const int VatrChunkPointer_MM = 0x3C; 34 | public const int VertexIndicesPointer_MM = 0x40; 35 | public const int TextureDataPointer_MM = 0x44; 36 | 37 | public uint FileSize { get; private set; } 38 | public uint NumberOfChunks { get; private set; } 39 | public uint Unknown2 { get; private set; } 40 | public string CmbName { get; private set; } 41 | public uint NumberOfIndices { get; private set; } 42 | 43 | public SklChunk SklChunk { get; private set; } 44 | public MatsChunk MatsChunk { get; private set; } 45 | public TexChunk TexChunk { get; private set; } 46 | public SklmChunk SklmChunk { get; private set; } 47 | public VatrChunk VatrChunk { get; private set; } 48 | public byte[] Indices { get; private set; } 49 | public byte[] TextureData { get; private set; } 50 | 51 | int vtxIdxOffset, texDataOffset; 52 | 53 | public int TotalPrimitives { get; private set; } 54 | public int TotalVertices { get; private set; } 55 | public int TotalTexCoords { get; private set; } 56 | public int TotalColors { get; private set; } 57 | public int TotalNormals { get; private set; } 58 | 59 | public CmbChunk(byte[] data, int offset, BaseCTRChunk parent) 60 | : base(data, offset, parent) 61 | { 62 | FileSize = BitConverter.ToUInt32(ChunkData, 0x4); 63 | NumberOfChunks = BitConverter.ToUInt32(ChunkData, 0x8); 64 | Unknown2 = BitConverter.ToUInt32(ChunkData, 0xC); 65 | CmbName = Encoding.ASCII.GetString(ChunkData, 0x10, 16).TrimEnd('\0'); 66 | NumberOfIndices = BitConverter.ToUInt32(ChunkData, 0x20); 67 | 68 | BaseCTRChunk.IsMajora3D = (NumberOfChunks == 0x0A); 69 | 70 | if (!BaseCTRChunk.IsMajora3D) 71 | { 72 | SklChunk = new SklChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, SklChunkPointer_OoT), this); 73 | MatsChunk = new MatsChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, MatsChunkPointer_OoT), this); 74 | TexChunk = new TexChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, TexChunkPointer_OoT), this); 75 | SklmChunk = new SklmChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, SklmChunkPointer_OoT), this); 76 | VatrChunk = new VatrChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, VatrChunkPointer_OoT), this); 77 | 78 | vtxIdxOffset = (int)BitConverter.ToUInt32(ChunkData, VertexIndicesPointer_OoT); 79 | texDataOffset = (int)BitConverter.ToUInt32(ChunkData, TextureDataPointer_OoT); 80 | } 81 | else 82 | { 83 | SklChunk = new SklChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, SklChunkPointer_MM), this); 84 | MatsChunk = new MatsChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, MatsChunkPointer_MM), this); 85 | TexChunk = new TexChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, TexChunkPointer_MM), this); 86 | SklmChunk = new SklmChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, SklmChunkPointer_MM), this); 87 | VatrChunk = new VatrChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, VatrChunkPointer_MM), this); 88 | 89 | vtxIdxOffset = (int)BitConverter.ToUInt32(ChunkData, VertexIndicesPointer_MM); 90 | texDataOffset = (int)BitConverter.ToUInt32(ChunkData, TextureDataPointer_MM); 91 | } 92 | 93 | Indices = new byte[NumberOfIndices * sizeof(ushort)]; 94 | Buffer.BlockCopy(ChunkData, vtxIdxOffset, Indices, 0, Indices.Length); 95 | 96 | TextureData = new byte[ChunkData.Length - texDataOffset]; 97 | Buffer.BlockCopy(ChunkData, texDataOffset, TextureData, 0, TextureData.Length); 98 | 99 | /* For information purposes, tho inexact if (probably) one array type isn't used by sepd (or smth) */ 100 | TotalPrimitives = 0; 101 | foreach (SepdChunk sepd in SklmChunk.ShpChunk.SepdChunks) TotalPrimitives += sepd.TotalPrimitives; 102 | 103 | TotalVertices = TotalTexCoords = TotalColors = TotalNormals = 0; 104 | for (int i = 0; i < SklmChunk.ShpChunk.SepdChunks.Length; i++) 105 | { 106 | if (i == SklmChunk.ShpChunk.SepdChunks.Length - 1) 107 | { 108 | SepdChunk sepdCurrent = SklmChunk.ShpChunk.SepdChunks[i]; 109 | 110 | if (VatrChunk.Sizes[VatrChunk.VertexArray_OoT] != 0) TotalVertices += (int)((VatrChunk.Sizes[VatrChunk.VertexArray_OoT] - sepdCurrent.VertexArrayOffset) / sepdCurrent.VertexSize); 111 | if (VatrChunk.Sizes[VatrChunk.TextureCoordArray_OoT] != 0) TotalTexCoords += (int)((VatrChunk.Sizes[VatrChunk.TextureCoordArray_OoT] - sepdCurrent.TextureCoordArrayOffset) / sepdCurrent.TexCoordSize); 112 | if (VatrChunk.Sizes[VatrChunk.ColorArray_OoT] != 0) TotalColors += (int)((VatrChunk.Sizes[VatrChunk.ColorArray_OoT] - sepdCurrent.ColorArrayOffset) / sepdCurrent.ColorSize); 113 | if (VatrChunk.Sizes[VatrChunk.NormalArray_OoT] != 0) TotalNormals += (int)((VatrChunk.Sizes[VatrChunk.NormalArray_OoT] - sepdCurrent.NormalArrayOffset) / sepdCurrent.NormalSize); 114 | } 115 | else 116 | { 117 | SepdChunk sepdCurrent = SklmChunk.ShpChunk.SepdChunks[i]; 118 | SepdChunk sepdNext = SklmChunk.ShpChunk.SepdChunks[i + 1]; 119 | 120 | if (VatrChunk.Sizes[VatrChunk.VertexArray_OoT] != 0) TotalVertices += (int)((sepdNext.VertexArrayOffset - sepdCurrent.VertexArrayOffset) / sepdCurrent.VertexSize); 121 | if (VatrChunk.Sizes[VatrChunk.TextureCoordArray_OoT] != 0) TotalTexCoords += (int)((sepdNext.TextureCoordArrayOffset - sepdCurrent.TextureCoordArrayOffset) / sepdCurrent.TexCoordSize); 122 | if (VatrChunk.Sizes[VatrChunk.ColorArray_OoT] != 0) TotalColors += (int)((sepdNext.ColorArrayOffset - sepdCurrent.ColorArrayOffset) / sepdCurrent.ColorSize); 123 | if (VatrChunk.Sizes[VatrChunk.NormalArray_OoT] != 0) TotalNormals += (int)((sepdNext.NormalArrayOffset - sepdCurrent.NormalArrayOffset) / sepdCurrent.NormalSize); 124 | } 125 | } 126 | } 127 | 128 | public override string ToString() 129 | { 130 | StringBuilder sb = new StringBuilder(); 131 | 132 | sb.AppendFormat("-- {0} --\n", this.GetType().Name); 133 | sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, 134 | "Filesize: 0x{0:X}\nNumber of chunks: 0x{1:X}, Unknown: 0x{2:X}\nCmb name: {3}\nNumber of indices: 0x{4:X}\nIndices offset: 0x{5:X}, Texture offset: 0x{6:X}\n", 135 | FileSize, NumberOfChunks, Unknown2, CmbName, NumberOfIndices, vtxIdxOffset, texDataOffset); 136 | sb.AppendLine(); 137 | 138 | sb.Append(SklChunk.ToString()); 139 | sb.Append(MatsChunk.ToString()); 140 | sb.Append(TexChunk.ToString()); 141 | sb.Append(SklmChunk.ToString()); 142 | sb.Append(VatrChunk.ToString()); 143 | 144 | return sb.ToString(); 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Cmb/Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using OpenTK; 7 | using OpenTK.Graphics; 8 | using OpenTK.Graphics.OpenGL; 9 | 10 | namespace N3DSCmbViewer.Cmb 11 | { 12 | static class Constants 13 | { 14 | public enum PicaDataType : ushort 15 | { 16 | Byte = 0x1400, 17 | UnsignedByte = 0x1401, 18 | Short = 0x1402, 19 | UnsignedShort = 0x1403, 20 | Int = 0x1404, 21 | UnsignedInt = 0x1405, 22 | Float = 0x1406, 23 | 24 | UnsignedByte44DMP = 0x6760, 25 | Unsigned4BitsDMP = 0x6761, 26 | 27 | UnsignedShort4444 = 0x8033, 28 | UnsignedShort5551 = 0x8034, 29 | UnsignedShort565 = 0x8363 30 | }; 31 | 32 | public enum PicaTextureFormat : ushort 33 | { 34 | RGBANativeDMP = 0x6752, 35 | RGBNativeDMP = 0x6754, 36 | AlphaNativeDMP = 0x6756, 37 | LuminanceNativeDMP = 0x6757, 38 | LuminanceAlphaNativeDMP = 0x6758, 39 | ETC1RGB8NativeDMP = 0x675A, 40 | ETC1AlphaRGB8A4NativeDMP = 0x675B 41 | }; 42 | 43 | public enum PicaTextureEnvModeCombine : ushort 44 | { 45 | Replace = TextureEnvModeCombine.Replace, 46 | Modulate = TextureEnvModeCombine.Modulate, 47 | Add = TextureEnvModeCombine.Add, 48 | AddSigned = TextureEnvModeCombine.AddSigned, 49 | Interpolate = TextureEnvModeCombine.Interpolate, 50 | Subtract = TextureEnvModeCombine.Subtract, 51 | Dot3Rgb = TextureEnvModeCombine.Dot3Rgb, 52 | Dot3Rgba = TextureEnvModeCombine.Dot3Rgba, 53 | MultAdd = 0x6401, 54 | AddMult = 0x6402 55 | }; 56 | 57 | public enum PicaTextureEnvModeSource : ushort 58 | { 59 | PrimaryColor = TextureEnvModeSource.PrimaryColor, 60 | FragmentPrimaryColorDMP = 0x6210, 61 | FragmentSecondaryColorDMP = 0x6211, 62 | Texture0 = TextureEnvModeSource.Texture0, 63 | Texture1 = TextureEnvModeSource.Texture1, 64 | Texture2 = TextureEnvModeSource.Texture2, 65 | Texture3 = TextureEnvModeSource.Texture3, 66 | PreviousBufferDMP = 0x8579, 67 | Constant = TextureEnvModeSource.Constant, 68 | Previous = TextureEnvModeSource.Previous 69 | }; 70 | 71 | public enum PicaTextureEnvModeOperandRgb : ushort 72 | { 73 | SrcColor = TextureEnvModeOperandRgb.SrcColor, 74 | OneMinusSrcColor = TextureEnvModeOperandRgb.OneMinusSrcColor, 75 | SrcAlpha = TextureEnvModeOperandRgb.SrcAlpha, 76 | OneMinusSrcAlpha = TextureEnvModeOperandRgb.OneMinusSrcAlpha, 77 | SrcRDMP = 0x8580, 78 | OneMinusSrcRDMP = 0x8583, 79 | SrcGDMP = 0x8581, 80 | OneMinusSrcGDMP = 0x8584, 81 | SrcBDMP = 0x8582, 82 | OneMinusSrcBDMP = 0x8585, 83 | }; 84 | 85 | public enum PicaTextureEnvModeOperandAlpha : ushort 86 | { 87 | SrcAlpha = TextureEnvModeOperandAlpha.SrcAlpha, 88 | OneMinusSrcAlpha = TextureEnvModeOperandAlpha.OneMinusSrcAlpha, 89 | SrcRDMP = 0x8580, 90 | OneMinusSrcRDMP = 0x8583, 91 | SrcGDMP = 0x8581, 92 | OneMinusSrcGDMP = 0x8584, 93 | SrcBDMP = 0x8582, 94 | OneMinusSrcBDMP = 0x8585, 95 | }; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Cmb/MatsChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using OpenTK.Graphics.OpenGL; 7 | 8 | namespace N3DSCmbViewer.Cmb 9 | { 10 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 11 | class MatsChunk : BaseCTRChunk 12 | { 13 | // "Materials"? 14 | public override string ChunkTag { get { return "mats"; } } 15 | 16 | public uint MaterialCount { get; private set; } 17 | 18 | public Material[] Materials { get; private set; } 19 | public TextureEnvSetting[] TextureEnvSettings { get; private set; } 20 | 21 | public MatsChunk(byte[] data, int offset, BaseCTRChunk parent) 22 | : base(data, offset, parent) 23 | { 24 | MaterialCount = BitConverter.ToUInt32(ChunkData, 0x8); 25 | 26 | int matDataSize = (BaseCTRChunk.IsMajora3D ? Material.DataSize_MM : Material.DataSize_OoT); 27 | 28 | Materials = new Material[MaterialCount]; 29 | for (int i = 0; i < Materials.Length; i++) Materials[i] = new Material(ChunkData, 0xC + (i * matDataSize)); 30 | 31 | TextureEnvSettings = new TextureEnvSetting[MaterialCount]; 32 | for (int i = 0; i < TextureEnvSettings.Length; i++) TextureEnvSettings[i] = new TextureEnvSetting(ChunkData, 0xC + (int)(MaterialCount * matDataSize) + (i * TextureEnvSetting.DataSize)); 33 | } 34 | 35 | public override string ToString() 36 | { 37 | StringBuilder sb = new StringBuilder(); 38 | 39 | sb.AppendFormat("-- {0} --\n", this.GetType().Name); 40 | sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "Number of materials: 0x{0:X}\n", MaterialCount); 41 | sb.AppendLine(); 42 | 43 | for (int i = 0; i < MaterialCount; i++) 44 | { 45 | sb.Append(Materials[i].ToString()); 46 | sb.Append(TextureEnvSettings[i].ToString()); 47 | } 48 | 49 | return sb.ToString(); 50 | } 51 | 52 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 53 | public class Material 54 | { 55 | public const int DataSize_OoT = 0x15C; 56 | public const int DataSize_MM = 0x16C; 57 | 58 | public short[] TextureIDs { get; private set; } 59 | public TextureMinFilter[] TextureMinFilters { get; private set; } 60 | public TextureMagFilter[] TextureMagFilters { get; private set; } 61 | public TextureWrapMode[] TextureWrapModeSs { get; private set; } 62 | public TextureWrapMode[] TextureWrapModeTs { get; private set; } 63 | 64 | public uint Unknown000 { get; private set; } 65 | public uint Unknown004 { get; private set; } 66 | public uint Unknown008 { get; private set; } 67 | public uint Unknown00C { get; private set; } 68 | //Texture ID 0 69 | public ushort Unknown012 { get; private set; } 70 | //MinFilter 0 71 | //MagFilter 0 72 | //WrapModeS 0 73 | //WrapModeT 0 74 | public uint Unknown01C { get; private set; } 75 | public uint Unknown020 { get; private set; } 76 | public uint Unknown024 { get; private set; } 77 | //Texture ID 1 78 | public ushort Unknown02A { get; private set; } 79 | //MinFilter 1 80 | //MagFilter 1 81 | //WrapModeS 1 82 | //WrapModeT 1 83 | public uint Unknown034 { get; private set; } 84 | public uint Unknown038 { get; private set; } 85 | public uint Unknown03C { get; private set; } 86 | //Texture ID 2 87 | public ushort Unknown042 { get; private set; } 88 | //MinFilter 2 89 | //MagFilter 2 90 | //WrapModeS 2 91 | //WrapModeT 2 92 | public uint Unknown04C { get; private set; } 93 | public uint Unknown050 { get; private set; } 94 | public uint Unknown054 { get; private set; } 95 | public uint Unknown058 { get; private set; } 96 | public float Float05C { get; private set; } 97 | public float Float060 { get; private set; } 98 | public uint Unknown064 { get; private set; } 99 | public uint Unknown068 { get; private set; } 100 | public uint Unknown06C { get; private set; } 101 | public uint Unknown070 { get; private set; } 102 | public float Float074 { get; private set; } 103 | public float Float078 { get; private set; } 104 | public uint Unknown07C { get; private set; } 105 | public uint Unknown080 { get; private set; } 106 | public uint Unknown084 { get; private set; } 107 | public uint Unknown088 { get; private set; } 108 | public float Float08C { get; private set; } 109 | public float Float090 { get; private set; } 110 | public uint Unknown094 { get; private set; } 111 | public uint Unknown098 { get; private set; } 112 | public uint Unknown09C { get; private set; } 113 | public uint Unknown0A0 { get; private set; } 114 | public uint Unknown0A4 { get; private set; } //00FFFFFF 115 | public uint Unknown0A8 { get; private set; } //FFFFFFFF 116 | public uint Unknown0AC { get; private set; } //007F7F7F 117 | public uint Unknown0B0 { get; private set; } 118 | public uint Unknown0B4 { get; private set; } //FF000000 119 | public uint Unknown0B8 { get; private set; } //FF000000 120 | public uint Unknown0BC { get; private set; } //FF000000 121 | public uint Unknown0C0 { get; private set; } //FF000000 122 | public uint Unknown0C4 { get; private set; } //FF000000 123 | public uint Unknown0C8 { get; private set; } //FF000000 124 | public uint Unknown0CC { get; private set; } 125 | public uint Unknown0D0 { get; private set; } 126 | public uint Unknown0D4 { get; private set; } 127 | public float Float0D8 { get; private set; } 128 | public uint Unknown0DC { get; private set; } //62C884C0 129 | public uint Unknown0E0 { get; private set; } 130 | public uint Unknown0E4 { get; private set; } //000062B0 131 | public uint Unknown0E8 { get; private set; } //000062C0 132 | public uint Unknown0EC { get; private set; } 133 | public uint Unknown0F0 { get; private set; } //62A0FF01 134 | public float Float0F4 { get; private set; } 135 | public uint Unknown0F8 { get; private set; } //62A0FF01 136 | public float Float0FC { get; private set; } 137 | public uint Unknown100 { get; private set; } //62A0FF01 138 | public float Float104 { get; private set; } 139 | public uint Unknown108 { get; private set; } //62A0FF01 140 | public float Float10C { get; private set; } 141 | public uint Unknown110 { get; private set; } //62A0FF01 142 | public float Float114 { get; private set; } 143 | public uint Unknown118 { get; private set; } //62A0FF01 144 | public float Float11C { get; private set; } 145 | public uint NumberOfIndicesToUnknown { get; private set; } //00000001 146 | public ushort[] IndicesToUnknown { get; private set; } 147 | public bool AlphaTestEnable { get; private set; } 148 | public float AlphaReference { get; private set; } //0000 149 | public AlphaFunction AlphaFunction { get; private set; } //0207 150 | public ushort MaybeStencilUnknown134 { get; private set; } //0101 151 | public StencilFunction MaybeStencilFunction { get; private set; } //0201 152 | public uint Unknown138 { get; private set; } 153 | public BlendingFactorSrc BlendingFactorSrc { get; private set; } //0303 154 | public BlendingFactorDest BlendingFactorDest { get; private set; } //0302 155 | public uint Unknown140 { get; private set; } //00008006 156 | public uint Unknown144 { get; private set; } //00000001 157 | public uint Unknown148 { get; private set; } //00008006 158 | public uint Unknown14C { get; private set; } 159 | public uint Unknown150 { get; private set; } 160 | public uint Unknown154 { get; private set; } 161 | public float BlendColorA { get; private set; } 162 | 163 | //MM3D 164 | public ushort Unknown15C { get; private set; } 165 | public ushort Unknown15E { get; private set; } 166 | public ushort Unknown160 { get; private set; } 167 | public ushort Unknown162 { get; private set; } 168 | public ushort Unknown164 { get; private set; } 169 | public ushort Unknown166 { get; private set; } 170 | public uint Unknown168 { get; private set; } 171 | 172 | public Material(byte[] data, int offset) 173 | { 174 | TextureIDs = new short[3]; 175 | TextureMinFilters = new TextureMinFilter[3]; 176 | TextureMagFilters = new TextureMagFilter[3]; 177 | TextureWrapModeSs = new TextureWrapMode[3]; 178 | TextureWrapModeTs = new TextureWrapMode[3]; 179 | 180 | Unknown000 = BitConverter.ToUInt32(data, offset); 181 | Unknown004 = BitConverter.ToUInt32(data, offset + 0x004); 182 | Unknown008 = BitConverter.ToUInt32(data, offset + 0x008); 183 | Unknown00C = BitConverter.ToUInt32(data, offset + 0x00C); 184 | TextureIDs[0] = BitConverter.ToInt16(data, offset + 0x010); 185 | Unknown012 = BitConverter.ToUInt16(data, offset + 0x012); 186 | TextureMinFilters[0] = (TextureMinFilter)BitConverter.ToUInt16(data, offset + 0x014); 187 | TextureMagFilters[0] = (TextureMagFilter)BitConverter.ToUInt16(data, offset + 0x016); 188 | TextureWrapModeSs[0] = (TextureWrapMode)BitConverter.ToUInt16(data, offset + 0x018); 189 | TextureWrapModeTs[0] = (TextureWrapMode)BitConverter.ToUInt16(data, offset + 0x01A); 190 | Unknown01C = BitConverter.ToUInt32(data, offset + 0x01C); 191 | Unknown020 = BitConverter.ToUInt32(data, offset + 0x020); 192 | Unknown024 = BitConverter.ToUInt32(data, offset + 0x024); 193 | TextureIDs[1] = BitConverter.ToInt16(data, offset + 0x028); 194 | Unknown02A = BitConverter.ToUInt16(data, offset + 0x02A); 195 | TextureMinFilters[1] = (TextureMinFilter)BitConverter.ToUInt16(data, offset + 0x02C); 196 | TextureMagFilters[1] = (TextureMagFilter)BitConverter.ToUInt16(data, offset + 0x02E); 197 | TextureWrapModeSs[1] = (TextureWrapMode)BitConverter.ToUInt16(data, offset + 0x030); 198 | TextureWrapModeTs[1] = (TextureWrapMode)BitConverter.ToUInt16(data, offset + 0x032); 199 | Unknown034 = BitConverter.ToUInt32(data, offset + 0x034); 200 | Unknown038 = BitConverter.ToUInt32(data, offset + 0x038); 201 | Unknown03C = BitConverter.ToUInt32(data, offset + 0x03C); 202 | TextureIDs[2] = BitConverter.ToInt16(data, offset + 0x040); 203 | Unknown042 = BitConverter.ToUInt16(data, offset + 0x042); 204 | TextureMinFilters[2] = (TextureMinFilter)BitConverter.ToUInt16(data, offset + 0x044); 205 | TextureMagFilters[2] = (TextureMagFilter)BitConverter.ToUInt16(data, offset + 0x046); 206 | TextureWrapModeSs[2] = (TextureWrapMode)BitConverter.ToUInt16(data, offset + 0x048); 207 | TextureWrapModeTs[2] = (TextureWrapMode)BitConverter.ToUInt16(data, offset + 0x04A); 208 | Unknown04C = BitConverter.ToUInt32(data, offset + 0x04C); 209 | Unknown050 = BitConverter.ToUInt32(data, offset + 0x050); 210 | Unknown054 = BitConverter.ToUInt32(data, offset + 0x054); 211 | Unknown058 = BitConverter.ToUInt32(data, offset + 0x058); 212 | Float05C = BitConverter.ToSingle(data, offset + 0x05C); 213 | Float060 = BitConverter.ToSingle(data, offset + 0x060); 214 | Unknown064 = BitConverter.ToUInt32(data, offset + 0x064); 215 | Unknown068 = BitConverter.ToUInt32(data, offset + 0x068); 216 | Unknown06C = BitConverter.ToUInt32(data, offset + 0x06C); 217 | Unknown070 = BitConverter.ToUInt32(data, offset + 0x070); 218 | Float074 = BitConverter.ToSingle(data, offset + 0x074); 219 | Float078 = BitConverter.ToSingle(data, offset + 0x078); 220 | Unknown07C = BitConverter.ToUInt32(data, offset + 0x07C); 221 | Unknown080 = BitConverter.ToUInt32(data, offset + 0x080); 222 | Unknown084 = BitConverter.ToUInt32(data, offset + 0x084); 223 | Unknown088 = BitConverter.ToUInt32(data, offset + 0x088); 224 | Float08C = BitConverter.ToSingle(data, offset + 0x08C); 225 | Float090 = BitConverter.ToSingle(data, offset + 0x090); 226 | Unknown094 = BitConverter.ToUInt32(data, offset + 0x094); 227 | Unknown098 = BitConverter.ToUInt32(data, offset + 0x098); 228 | Unknown09C = BitConverter.ToUInt32(data, offset + 0x09C); 229 | Unknown0A0 = BitConverter.ToUInt32(data, offset + 0x0A0); 230 | Unknown0A4 = BitConverter.ToUInt32(data, offset + 0x0A4); 231 | Unknown0A8 = BitConverter.ToUInt32(data, offset + 0x0A8); 232 | Unknown0AC = BitConverter.ToUInt32(data, offset + 0x0AC); 233 | Unknown0B0 = BitConverter.ToUInt32(data, offset + 0x0B0); 234 | Unknown0B4 = BitConverter.ToUInt32(data, offset + 0x0B4); 235 | Unknown0B8 = BitConverter.ToUInt32(data, offset + 0x0B8); 236 | Unknown0BC = BitConverter.ToUInt32(data, offset + 0x0BC); 237 | Unknown0C0 = BitConverter.ToUInt32(data, offset + 0x0C0); 238 | Unknown0C4 = BitConverter.ToUInt32(data, offset + 0x0C4); 239 | Unknown0C8 = BitConverter.ToUInt32(data, offset + 0x0C8); 240 | Unknown0CC = BitConverter.ToUInt32(data, offset + 0x0CC); 241 | Unknown0D0 = BitConverter.ToUInt32(data, offset + 0x0D0); 242 | Unknown0D4 = BitConverter.ToUInt32(data, offset + 0x0D4); 243 | Float0D8 = BitConverter.ToSingle(data, offset + 0x0D8); 244 | Unknown0F0 = BitConverter.ToUInt32(data, offset + 0x0F0); 245 | Float0F4 = BitConverter.ToSingle(data, offset + 0x0F4); 246 | Unknown0F8 = BitConverter.ToUInt32(data, offset + 0x0F8); 247 | Float0FC = BitConverter.ToSingle(data, offset + 0x0FC); 248 | Unknown100 = BitConverter.ToUInt32(data, offset + 0x100); 249 | Float104 = BitConverter.ToSingle(data, offset + 0x104); 250 | Unknown108 = BitConverter.ToUInt32(data, offset + 0x108); 251 | Float10C = BitConverter.ToSingle(data, offset + 0x10C); 252 | Unknown110 = BitConverter.ToUInt32(data, offset + 0x110); 253 | Float114 = BitConverter.ToSingle(data, offset + 0x114); 254 | Unknown118 = BitConverter.ToUInt32(data, offset + 0x118); 255 | Float11C = BitConverter.ToSingle(data, offset + 0x11C); 256 | NumberOfIndicesToUnknown = BitConverter.ToUInt32(data, offset + 0x120); 257 | IndicesToUnknown = new ushort[NumberOfIndicesToUnknown]; 258 | for (int i = 0; i < IndicesToUnknown.Length; i++) IndicesToUnknown[i] = BitConverter.ToUInt16(data, offset + 0x124 + (i * sizeof(ushort))); 259 | AlphaTestEnable = Convert.ToBoolean(data[offset + 0x130]); 260 | AlphaReference = (Convert.ToSingle(data[offset + 0x131]) / 256.0f); 261 | AlphaFunction = (AlphaFunction)BitConverter.ToUInt16(data, offset + 0x132); 262 | MaybeStencilUnknown134 = BitConverter.ToUInt16(data, offset + 0x134); 263 | MaybeStencilFunction = (StencilFunction)BitConverter.ToUInt16(data, offset + 0x136); 264 | Unknown138 = BitConverter.ToUInt32(data, offset + 0x138); 265 | BlendingFactorSrc = (BlendingFactorSrc)BitConverter.ToUInt16(data, offset + 0x13C); 266 | BlendingFactorDest = (BlendingFactorDest)BitConverter.ToUInt16(data, offset + 0x13E); 267 | Unknown140 = BitConverter.ToUInt32(data, offset + 0x140); 268 | Unknown144 = BitConverter.ToUInt32(data, offset + 0x144); 269 | Unknown148 = BitConverter.ToUInt32(data, offset + 0x148); 270 | Unknown150 = BitConverter.ToUInt32(data, offset + 0x150); 271 | Unknown154 = BitConverter.ToUInt32(data, offset + 0x154); 272 | BlendColorA = BitConverter.ToSingle(data, offset + 0x158); 273 | 274 | if (BaseCTRChunk.IsMajora3D) 275 | { 276 | Unknown15C = BitConverter.ToUInt16(data, offset + 0x15C); 277 | Unknown15E = BitConverter.ToUInt16(data, offset + 0x15E); 278 | Unknown160 = BitConverter.ToUInt16(data, offset + 0x160); 279 | Unknown162 = BitConverter.ToUInt16(data, offset + 0x162); 280 | Unknown164 = BitConverter.ToUInt16(data, offset + 0x164); 281 | Unknown166 = BitConverter.ToUInt16(data, offset + 0x166); 282 | Unknown168 = BitConverter.ToUInt32(data, offset + 0x168); 283 | } 284 | } 285 | 286 | public override string ToString() 287 | { 288 | StringBuilder sb = new StringBuilder(); 289 | 290 | sb.AppendFormat("-- {0} --\n", this.GetType().Name); 291 | sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, 292 | "WARNING: Too many unknowns for me to bother dumping everything...\n" + 293 | "Texture 0 -> ID: {0}, Min/Mag filter: {1}/{2}, Wrap mode S/T: {3}/{4}\n" + 294 | "Texture 1 -> ID: {5}, Min/Mag filter: {6}/{7}, Wrap mode S/T: {8}/{9}\n" + 295 | "Texture 2 -> ID: {10}, Min/Mag filter: {11}/{12}, Wrap mode S/T: {13}/{14}\n" + 296 | "Blend factor source/destination: {15}/{16}\n" + 297 | "Alpha test: {17} {18} {19}\n" + 298 | "Stencil: {20} {21:X}\n", 299 | TextureIDs[0], TextureMinFilters[0], TextureMagFilters[0], TextureWrapModeSs[0], TextureWrapModeTs[0], 300 | TextureIDs[1], TextureMinFilters[1], TextureMagFilters[1], TextureWrapModeSs[1], TextureWrapModeTs[1], 301 | TextureIDs[2], TextureMinFilters[2], TextureMagFilters[2], TextureWrapModeSs[2], TextureWrapModeTs[2], 302 | BlendingFactorSrc, BlendingFactorDest, 303 | AlphaTestEnable, AlphaFunction, AlphaReference, 304 | MaybeStencilFunction, MaybeStencilUnknown134); 305 | sb.AppendLine(); 306 | 307 | return sb.ToString(); 308 | } 309 | } 310 | 311 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 312 | public class TextureEnvSetting 313 | { 314 | public const int DataSize = 0x28; 315 | 316 | public Constants.PicaTextureEnvModeCombine CombineRgb { get; private set; } 317 | public Constants.PicaTextureEnvModeCombine CombineAlpha { get; private set; } 318 | public ushort[] UnknownUshort1 { get; private set; } 319 | public ushort[] UnknownGLConstant { get; private set; } 320 | public Constants.PicaTextureEnvModeSource[] SourceRgb { get; private set; } 321 | public Constants.PicaTextureEnvModeOperandRgb[] OperandRgb { get; private set; } 322 | public Constants.PicaTextureEnvModeSource[] SourceAlpha { get; private set; } 323 | public Constants.PicaTextureEnvModeOperandAlpha[] OperandAlpha { get; private set; } 324 | public ushort[] UnknownUshort2 { get; private set; } 325 | 326 | public TextureEnvSetting(byte[] data, int offset) 327 | { 328 | CombineRgb = (Constants.PicaTextureEnvModeCombine)BitConverter.ToUInt16(data, offset); 329 | CombineAlpha = (Constants.PicaTextureEnvModeCombine)BitConverter.ToUInt16(data, offset + 0x02); 330 | UnknownUshort1 = new ushort[2]; 331 | UnknownUshort1[0] = BitConverter.ToUInt16(data, offset + 0x04); 332 | UnknownUshort1[1] = BitConverter.ToUInt16(data, offset + 0x06); 333 | UnknownGLConstant = new ushort[2]; 334 | UnknownGLConstant[0] = BitConverter.ToUInt16(data, offset + 0x08); 335 | UnknownGLConstant[1] = BitConverter.ToUInt16(data, offset + 0x0A); 336 | SourceRgb = new Constants.PicaTextureEnvModeSource[3]; 337 | SourceRgb[0] = (Constants.PicaTextureEnvModeSource)BitConverter.ToUInt16(data, offset + 0x0C); 338 | SourceRgb[1] = (Constants.PicaTextureEnvModeSource)BitConverter.ToUInt16(data, offset + 0x0E); 339 | SourceRgb[2] = (Constants.PicaTextureEnvModeSource)BitConverter.ToUInt16(data, offset + 0x10); 340 | OperandRgb = new Constants.PicaTextureEnvModeOperandRgb[3]; 341 | OperandRgb[0] = (Constants.PicaTextureEnvModeOperandRgb)BitConverter.ToUInt16(data, offset + 0x12); 342 | OperandRgb[1] = (Constants.PicaTextureEnvModeOperandRgb)BitConverter.ToUInt16(data, offset + 0x14); 343 | OperandRgb[2] = (Constants.PicaTextureEnvModeOperandRgb)BitConverter.ToUInt16(data, offset + 0x16); 344 | SourceAlpha = new Constants.PicaTextureEnvModeSource[3]; 345 | SourceAlpha[0] = (Constants.PicaTextureEnvModeSource)BitConverter.ToUInt16(data, offset + 0x18); 346 | SourceAlpha[1] = (Constants.PicaTextureEnvModeSource)BitConverter.ToUInt16(data, offset + 0x1A); 347 | SourceAlpha[2] = (Constants.PicaTextureEnvModeSource)BitConverter.ToUInt16(data, offset + 0x1C); 348 | OperandAlpha = new Constants.PicaTextureEnvModeOperandAlpha[3]; 349 | OperandAlpha[0] = (Constants.PicaTextureEnvModeOperandAlpha)BitConverter.ToUInt16(data, offset + 0x1E); 350 | OperandAlpha[1] = (Constants.PicaTextureEnvModeOperandAlpha)BitConverter.ToUInt16(data, offset + 0x20); 351 | OperandAlpha[2] = (Constants.PicaTextureEnvModeOperandAlpha)BitConverter.ToUInt16(data, offset + 0x22); 352 | UnknownUshort2 = new ushort[2]; 353 | UnknownUshort2[0] = BitConverter.ToUInt16(data, offset + 0x24); 354 | UnknownUshort2[1] = BitConverter.ToUInt16(data, offset + 0x26); 355 | } 356 | 357 | public override string ToString() 358 | { 359 | StringBuilder sb = new StringBuilder(); 360 | 361 | sb.AppendFormat("-- {0} --\n", this.GetType().Name); 362 | sb.Append("WARNING: Untested, might be incorrect, I have no idea...\n"); 363 | sb.AppendFormat("CombineRgb: {0}, CombineAlpha: {1}\n", CombineRgb, CombineAlpha); 364 | sb.AppendFormat("Unknown Ushort 1 [0,1]: 0x{0:X}, 0x{1:X}\n", UnknownUshort1[0], UnknownUshort1[1]); 365 | sb.AppendFormat("Unknown GL constant [0,1]: 0x{0:X}, 0x{1:X}\n", UnknownGLConstant[0], UnknownGLConstant[1]); 366 | sb.AppendFormat("SourceRgb [0,1,2]: {0}, {1}, {2}\n", SourceRgb[0], SourceRgb[1], SourceRgb[2]); 367 | sb.AppendFormat("OperandRgb [0,1,2]: {0}, {1}, {2}\n", OperandRgb[0], OperandRgb[1], OperandRgb[2]); 368 | sb.AppendFormat("SourceAlpha [0,1,2]: {0}, {1}, {2}\n", SourceAlpha[0], SourceAlpha[1], SourceAlpha[2]); 369 | sb.AppendFormat("OperandAlpha [0,1,2]: {0}, {1}, {2}\n", OperandAlpha[0], OperandAlpha[1], OperandAlpha[2]); 370 | sb.AppendFormat("Unknown Ushort 2 [0,1]: 0x{0:X}, 0x{1:X}\n", UnknownUshort2[0], UnknownUshort2[1]); 371 | 372 | sb.AppendLine(); 373 | 374 | return sb.ToString(); 375 | } 376 | } 377 | } 378 | } 379 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Cmb/MshsChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace N3DSCmbViewer.Cmb 7 | { 8 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 9 | class MshsChunk : BaseCTRChunk 10 | { 11 | // "Meshes"? 12 | public override string ChunkTag { get { return "mshs"; } } 13 | 14 | public uint MeshCount { get; private set; } 15 | public ushort Unknown1 { get; private set; } 16 | public ushort Unknown2 { get; private set; } 17 | 18 | public Mesh[] Meshes { get; private set; } 19 | 20 | public MshsChunk(byte[] data, int offset, BaseCTRChunk parent) 21 | : base(data, offset, parent) 22 | { 23 | MeshCount = BitConverter.ToUInt32(ChunkData, 0x8); 24 | Unknown1 = BitConverter.ToUInt16(ChunkData, 0x0C); 25 | Unknown2 = BitConverter.ToUInt16(ChunkData, 0x0E); 26 | 27 | int meshDataSize = (BaseCTRChunk.IsMajora3D ? Mesh.DataSize_MM : Mesh.DataSize_OoT); 28 | 29 | Meshes = new Mesh[MeshCount]; 30 | for (int i = 0; i < Meshes.Length; i++) Meshes[i] = new Mesh(ChunkData, 0x10 + (i * meshDataSize)); 31 | } 32 | 33 | public override string ToString() 34 | { 35 | StringBuilder sb = new StringBuilder(); 36 | 37 | sb.AppendFormat("-- {0} --\n", this.GetType().Name); 38 | sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "Number of meshes: 0x{0:X}, Unknown (1): 0x{1:X}, Unknown (2): 0x{2:X}\n", MeshCount, Unknown1, Unknown2); 39 | sb.AppendLine(); 40 | 41 | foreach (Mesh mesh in Meshes) sb.Append(mesh.ToString()); 42 | 43 | return sb.ToString(); 44 | } 45 | 46 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 47 | public class Mesh 48 | { 49 | public const int DataSize_OoT = 0x04; 50 | public const int DataSize_MM = 0x0C; 51 | 52 | public ushort SepdID { get; private set; } 53 | public byte MaterialID { get; private set; } 54 | public byte Unknown { get; private set; } 55 | 56 | // MM3D only 57 | public uint Unknown2 { get; private set; } 58 | public uint Unknown3 { get; private set; } 59 | 60 | public Mesh(byte[] data, int offset) 61 | { 62 | SepdID = BitConverter.ToUInt16(data, offset); 63 | MaterialID = data[offset + 2]; 64 | Unknown = data[offset + 3]; 65 | 66 | if (BaseCTRChunk.IsMajora3D) 67 | { 68 | Unknown2 = BitConverter.ToUInt32(data, offset + 4); 69 | Unknown3 = BitConverter.ToUInt32(data, offset + 8); 70 | } 71 | } 72 | 73 | public override string ToString() 74 | { 75 | StringBuilder sb = new StringBuilder(); 76 | 77 | sb.AppendFormat("-- {0} --\n", this.GetType().Name); 78 | sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "Sepd ID: 0x{0:X}, Material ID: 0x{1:X}, Unknown: 0x{2:X}\n", SepdID, MaterialID, Unknown); 79 | sb.AppendLine(); 80 | 81 | return sb.ToString(); 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Cmb/PrmChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using OpenTK; 7 | using OpenTK.Graphics; 8 | using OpenTK.Graphics.OpenGL; 9 | 10 | namespace N3DSCmbViewer.Cmb 11 | { 12 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 13 | class PrmChunk : BaseCTRChunk 14 | { 15 | // "Primitive"? 16 | public override string ChunkTag { get { return "prm"; } } 17 | 18 | public uint Unknown1 { get; private set; } 19 | public uint Unknown2 { get; private set; } 20 | public Constants.PicaDataType DataType { get; private set; } 21 | public ushort NumberOfIndices { get; private set; } 22 | public ushort FirstIndex { get; private set; } 23 | 24 | public DrawElementsType DrawElementsType { get; private set; } 25 | public int ElementSize { get; private set; } 26 | 27 | public PrmChunk(byte[] data, int offset, BaseCTRChunk parent) 28 | : base(data, offset, parent) 29 | { 30 | Unknown1 = BitConverter.ToUInt32(ChunkData, 0x8); 31 | Unknown2 = BitConverter.ToUInt32(ChunkData, 0xC); 32 | DataType = (Constants.PicaDataType)BitConverter.ToUInt32(ChunkData, 0x10); 33 | NumberOfIndices = BitConverter.ToUInt16(ChunkData, 0x14); 34 | FirstIndex = BitConverter.ToUInt16(ChunkData, 0x16); 35 | 36 | DrawElementsType = DrawElementsType.UnsignedShort; 37 | ElementSize = sizeof(ushort); 38 | 39 | switch (DataType) 40 | { 41 | case Constants.PicaDataType.UnsignedByte: 42 | DrawElementsType = DrawElementsType.UnsignedByte; 43 | ElementSize = sizeof(byte); 44 | break; 45 | case Constants.PicaDataType.UnsignedShort: 46 | DrawElementsType = DrawElementsType.UnsignedShort; 47 | ElementSize = sizeof(short); 48 | break; 49 | case Constants.PicaDataType.UnsignedInt: 50 | DrawElementsType = DrawElementsType.UnsignedInt; 51 | ElementSize = sizeof(int); 52 | break; 53 | } 54 | } 55 | 56 | public override string ToString() 57 | { 58 | StringBuilder sb = new StringBuilder(); 59 | 60 | sb.AppendFormat("-- {0} --\n", this.GetType().Name); 61 | sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, 62 | "Unknown (1): 0x{0:X}, Unknown (2): 0x{1:X}, Index datatype: {2}\nNumber of indices: 0x{3:X}, First index: 0x{4:X}\n", 63 | Unknown1, Unknown2, DataType, NumberOfIndices, FirstIndex); 64 | sb.AppendLine(); 65 | 66 | return sb.ToString(); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Cmb/PrmsChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace N3DSCmbViewer.Cmb 7 | { 8 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 9 | class PrmsChunk : BaseCTRChunk 10 | { 11 | // "Primitives"? 12 | public override string ChunkTag { get { return "prms"; } } 13 | 14 | public enum SkinningModes : ushort 15 | { 16 | SingleBone = 0x0000, 17 | PerVertex = 0x0001, 18 | PerVertexNoTrans = 0x0002 19 | }; 20 | 21 | public uint Unknown1 { get; private set; } 22 | public SkinningModes SkinningMode { get; private set; } 23 | public ushort BoneIndexCount { get; private set; } 24 | public uint BoneIndexOffset { get; private set; } 25 | public uint PrmOffset { get; private set; } 26 | 27 | public ushort[] BoneIndices { get; private set; } 28 | 29 | public PrmChunk PrmChunk { get; private set; } 30 | 31 | public PrmsChunk(byte[] data, int offset, BaseCTRChunk parent) 32 | : base(data, offset, parent) 33 | { 34 | Unknown1 = BitConverter.ToUInt32(ChunkData, 0x8); 35 | SkinningMode = (SkinningModes)BitConverter.ToUInt16(ChunkData, 0xC); 36 | BoneIndexCount = BitConverter.ToUInt16(ChunkData, 0xE); 37 | BoneIndexOffset = BitConverter.ToUInt32(ChunkData, 0x10); 38 | PrmOffset = BitConverter.ToUInt32(ChunkData, 0x14); 39 | 40 | BoneIndices = new ushort[BoneIndexCount]; 41 | for (int i = 0; i < BoneIndices.Length; i++) BoneIndices[i] = BitConverter.ToUInt16(ChunkData, (int)(BoneIndexOffset + (i * 2))); 42 | 43 | PrmChunk = new PrmChunk(ChunkData, (int)PrmOffset, this); 44 | } 45 | 46 | public override string ToString() 47 | { 48 | StringBuilder sb = new StringBuilder(); 49 | 50 | sb.AppendFormat("-- {0} --\n", this.GetType().Name); 51 | sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, 52 | "Unknown (1): 0x{0:X}, Skinning mode: {1}\nBone index count: 0x{2:X}, Bone index offset: 0x{3:X}\nPrm chunk offset: 0x{4:X}\n", 53 | Unknown1, SkinningMode, BoneIndexCount, BoneIndexOffset, PrmOffset); 54 | sb.AppendLine(); 55 | 56 | for (int i = 0; i < BoneIndices.Length; i++) 57 | { 58 | sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "Bone index #{0}: 0x{1:X}\n", i, BoneIndices[i]); 59 | } 60 | 61 | sb.AppendLine(); 62 | 63 | sb.Append(PrmChunk.ToString()); 64 | 65 | return sb.ToString(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Cmb/SepdChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using OpenTK; 7 | using OpenTK.Graphics; 8 | using OpenTK.Graphics.OpenGL; 9 | 10 | namespace N3DSCmbViewer.Cmb 11 | { 12 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 13 | class SepdChunk : BaseCTRChunk 14 | { 15 | // ???? 16 | public override string ChunkTag { get { return "sepd"; } } 17 | 18 | // ?? 19 | public ushort PrmsCount { get; private set; } 20 | public ushort Unknown0A { get; private set; } 21 | public float UnknownFloat0C { get; private set; } 22 | public float UnknownFloat10 { get; private set; } 23 | public float UnknownFloat14 { get; private set; } 24 | public uint Unknown18 { get; private set; } 25 | public uint Unknown1C { get; private set; } 26 | public uint Unknown20 { get; private set; } 27 | 28 | public uint[] ArrayOffsets { get; private set; } 29 | public float[] ArrayScales { get; private set; } 30 | public Constants.PicaDataType[] ArrayDataTypes { get; private set; } 31 | public ushort[] ArrayUnknown1 { get; private set; } 32 | public uint[] ArrayUnknown2 { get; private set; } 33 | public uint[] ArrayUnknown3 { get; private set; } 34 | public uint[] ArrayUnknown4 { get; private set; } 35 | public uint[] ArrayUnknown5 { get; private set; } 36 | 37 | public uint VertexArrayOffset { get { return ArrayOffsets[BaseCTRChunk.IsMajora3D ? VatrChunk.VertexArray_MM : VatrChunk.VertexArray_OoT]; } } 38 | public float VertexArrayScale { get { return ArrayScales[BaseCTRChunk.IsMajora3D ? VatrChunk.VertexArray_MM : VatrChunk.VertexArray_OoT]; } } 39 | public Constants.PicaDataType VertexArrayDataType { get { return ArrayDataTypes[BaseCTRChunk.IsMajora3D ? VatrChunk.VertexArray_MM : VatrChunk.VertexArray_OoT]; } } 40 | 41 | public uint NormalArrayOffset { get { return ArrayOffsets[BaseCTRChunk.IsMajora3D ? VatrChunk.NormalArray_MM : VatrChunk.NormalArray_OoT]; } } 42 | public float NormalArrayScale { get { return ArrayScales[BaseCTRChunk.IsMajora3D ? VatrChunk.NormalArray_MM : VatrChunk.NormalArray_OoT]; } } 43 | public Constants.PicaDataType NormalArrayDataType { get { return ArrayDataTypes[BaseCTRChunk.IsMajora3D ? VatrChunk.NormalArray_MM : VatrChunk.NormalArray_OoT]; } } 44 | 45 | public uint ColorArrayOffset { get { return ArrayOffsets[BaseCTRChunk.IsMajora3D ? VatrChunk.ColorArray_MM : VatrChunk.ColorArray_OoT]; } } 46 | public float ColorArrayScale { get { return ArrayScales[BaseCTRChunk.IsMajora3D ? VatrChunk.ColorArray_MM : VatrChunk.ColorArray_OoT]; } } 47 | public Constants.PicaDataType ColorArrayDataType { get { return ArrayDataTypes[BaseCTRChunk.IsMajora3D ? VatrChunk.ColorArray_MM : VatrChunk.ColorArray_OoT]; } } 48 | 49 | public uint TextureCoordArrayOffset { get { return ArrayOffsets[BaseCTRChunk.IsMajora3D ? VatrChunk.TextureCoordArray_MM : VatrChunk.TextureCoordArray_OoT]; } } 50 | public float TextureCoordArrayScale { get { return ArrayScales[BaseCTRChunk.IsMajora3D ? VatrChunk.TextureCoordArray_MM : VatrChunk.TextureCoordArray_OoT]; } } 51 | public Constants.PicaDataType TextureCoordArrayDataType { get { return ArrayDataTypes[BaseCTRChunk.IsMajora3D ? VatrChunk.TextureCoordArray_MM : VatrChunk.TextureCoordArray_OoT]; } } 52 | 53 | public uint BoneIndexLookupArrayOffset { get { return ArrayOffsets[BaseCTRChunk.IsMajora3D ? VatrChunk.BoneIndexLookupArray_MM : VatrChunk.BoneIndexLookupArray_OoT]; } } 54 | public float BoneIndexLookupArrayScale { get { return ArrayScales[BaseCTRChunk.IsMajora3D ? VatrChunk.BoneIndexLookupArray_MM : VatrChunk.BoneIndexLookupArray_OoT]; } } 55 | public Constants.PicaDataType BoneIndexLookupArrayDataType { get { return ArrayDataTypes[BaseCTRChunk.IsMajora3D ? VatrChunk.BoneIndexLookupArray_MM : VatrChunk.BoneIndexLookupArray_OoT]; } } 56 | 57 | public uint BoneWeightArrayOffset { get { return ArrayOffsets[BaseCTRChunk.IsMajora3D ? VatrChunk.BoneWeightArray_MM : VatrChunk.BoneWeightArray_OoT]; } } 58 | public float BoneWeightArrayScale { get { return ArrayScales[BaseCTRChunk.IsMajora3D ? VatrChunk.BoneWeightArray_MM : VatrChunk.BoneWeightArray_OoT]; } } 59 | public Constants.PicaDataType BoneWeightArrayDataType { get { return ArrayDataTypes[BaseCTRChunk.IsMajora3D ? VatrChunk.BoneWeightArray_MM : VatrChunk.BoneWeightArray_OoT]; } } 60 | 61 | public uint Unknown_104OoT_120MM { get; private set; } 62 | 63 | public PrmsChunk[] PrmsChunks { get; private set; } 64 | 65 | public VertexPointerType VertexPointerType { get; private set; } 66 | public int VertexSize { get; private set; } 67 | public NormalPointerType NormalPointerType { get; private set; } 68 | public int NormalSize { get; private set; } 69 | public ColorPointerType ColorPointerType { get; private set; } 70 | public int ColorSize { get; private set; } 71 | public TexCoordPointerType TexCoordPointerType { get; private set; } 72 | public int TexCoordSize { get; private set; } 73 | 74 | public int BoneIndexLookupSize { get; private set; } 75 | 76 | public int TotalPrimitives { get; private set; } 77 | 78 | public SepdChunk(byte[] data, int offset, BaseCTRChunk parent) 79 | : base(data, offset, parent) 80 | { 81 | PrmsCount = BitConverter.ToUInt16(ChunkData, 0x08); 82 | Unknown0A = BitConverter.ToUInt16(ChunkData, 0x0A); 83 | UnknownFloat0C = BitConverter.ToSingle(ChunkData, 0x0C); 84 | UnknownFloat10 = BitConverter.ToSingle(ChunkData, 0x10); 85 | UnknownFloat14 = BitConverter.ToSingle(ChunkData, 0x14); 86 | Unknown18 = BitConverter.ToUInt32(ChunkData, 0x18); 87 | Unknown1C = BitConverter.ToUInt32(ChunkData, 0x1C); 88 | Unknown20 = BitConverter.ToUInt32(ChunkData, 0x20); 89 | 90 | int arrayCount = (BaseCTRChunk.IsMajora3D ? 9 : 8); 91 | 92 | ArrayOffsets = new uint[arrayCount]; 93 | ArrayScales = new float[arrayCount]; 94 | ArrayDataTypes = new Constants.PicaDataType[arrayCount]; 95 | ArrayUnknown1 = new ushort[arrayCount]; 96 | ArrayUnknown2 = new uint[arrayCount]; 97 | ArrayUnknown3 = new uint[arrayCount]; 98 | ArrayUnknown4 = new uint[arrayCount]; 99 | ArrayUnknown5 = new uint[arrayCount]; 100 | 101 | for (int i = 0; i < arrayCount; i++) 102 | { 103 | ArrayOffsets[i] = BitConverter.ToUInt32(ChunkData, 0x24 + (i * 0x1C)); 104 | ArrayScales[i] = BitConverter.ToSingle(ChunkData, 0x28 + (i * 0x1C)); 105 | ArrayDataTypes[i] = (Constants.PicaDataType)BitConverter.ToUInt16(ChunkData, 0x2C + (i * 0x1C)); 106 | ArrayUnknown1[i] = BitConverter.ToUInt16(ChunkData, 0x2E + (i * 0x1C)); 107 | ArrayUnknown2[i] = BitConverter.ToUInt32(ChunkData, 0x30 + (i * 0x1C)); 108 | ArrayUnknown3[i] = BitConverter.ToUInt32(ChunkData, 0x34 + (i * 0x1C)); 109 | ArrayUnknown4[i] = BitConverter.ToUInt32(ChunkData, 0x38 + (i * 0x1C)); 110 | ArrayUnknown5[i] = BitConverter.ToUInt32(ChunkData, 0x3C + (i * 0x1C)); 111 | } 112 | 113 | Unknown_104OoT_120MM = BitConverter.ToUInt32(ChunkData, !BaseCTRChunk.IsMajora3D ? 0x104 : 0x120); 114 | 115 | int prmsDataOffset = (!BaseCTRChunk.IsMajora3D ? 0x108 : 0x124); 116 | 117 | PrmsChunks = new PrmsChunk[PrmsCount]; 118 | for (int i = 0; i < PrmsChunks.Length; i++) PrmsChunks[i] = new PrmsChunk(ChunkData, (int)BitConverter.ToUInt16(ChunkData, prmsDataOffset + (i * 2)), this); 119 | 120 | switch (NormalArrayDataType) 121 | { 122 | case Constants.PicaDataType.Byte: 123 | case Constants.PicaDataType.UnsignedByte: 124 | NormalPointerType = NormalPointerType.Byte; 125 | NormalSize = (sizeof(byte) * 3); 126 | break; 127 | case Constants.PicaDataType.Short: 128 | case Constants.PicaDataType.UnsignedShort: 129 | NormalPointerType = NormalPointerType.Short; 130 | NormalSize = (sizeof(ushort) * 3); 131 | break; 132 | case Constants.PicaDataType.Int: 133 | case Constants.PicaDataType.UnsignedInt: 134 | NormalPointerType = NormalPointerType.Int; 135 | NormalSize = (sizeof(uint) * 3); 136 | break; 137 | case Constants.PicaDataType.Float: 138 | NormalPointerType = NormalPointerType.Float; 139 | NormalSize = (sizeof(float) * 3); 140 | break; 141 | } 142 | 143 | switch (ColorArrayDataType) 144 | { 145 | case Constants.PicaDataType.Byte: 146 | ColorPointerType = ColorPointerType.Byte; 147 | ColorSize = (sizeof(sbyte) * 4); 148 | break; 149 | case Constants.PicaDataType.UnsignedByte: 150 | ColorPointerType = ColorPointerType.UnsignedByte; 151 | ColorSize = (sizeof(byte) * 4); 152 | break; 153 | case Constants.PicaDataType.Short: 154 | ColorPointerType = ColorPointerType.Short; 155 | ColorSize = (sizeof(short) * 4); 156 | break; 157 | case Constants.PicaDataType.UnsignedShort: 158 | ColorPointerType = ColorPointerType.UnsignedShort; 159 | ColorSize = (sizeof(ushort) * 4); 160 | break; 161 | case Constants.PicaDataType.Int: 162 | ColorPointerType = ColorPointerType.Int; 163 | ColorSize = (sizeof(int) * 4); 164 | break; 165 | case Constants.PicaDataType.UnsignedInt: 166 | ColorPointerType = ColorPointerType.UnsignedInt; 167 | ColorSize = (sizeof(uint) * 4); 168 | break; 169 | case Constants.PicaDataType.Float: 170 | ColorPointerType = ColorPointerType.Float; 171 | ColorSize = (sizeof(float) * 4); 172 | break; 173 | } 174 | 175 | switch (TextureCoordArrayDataType) 176 | { 177 | case Constants.PicaDataType.Byte: 178 | case Constants.PicaDataType.UnsignedByte: 179 | /* Needs conversion to short during rendering! */ 180 | TexCoordPointerType = TexCoordPointerType.Short; 181 | TexCoordSize = (sizeof(byte) * 2); 182 | break; 183 | case Constants.PicaDataType.Short: 184 | case Constants.PicaDataType.UnsignedShort: 185 | TexCoordPointerType = TexCoordPointerType.Short; 186 | TexCoordSize = (sizeof(ushort) * 2); 187 | break; 188 | case Constants.PicaDataType.Int: 189 | case Constants.PicaDataType.UnsignedInt: 190 | TexCoordPointerType = TexCoordPointerType.Int; 191 | TexCoordSize = (sizeof(uint) * 2); 192 | break; 193 | case Constants.PicaDataType.Float: 194 | TexCoordPointerType = TexCoordPointerType.Float; 195 | TexCoordSize = (sizeof(float) * 2); 196 | break; 197 | } 198 | 199 | switch (VertexArrayDataType) 200 | { 201 | case Constants.PicaDataType.Byte: 202 | case Constants.PicaDataType.UnsignedByte: 203 | /* Needs conversion to short during rendering! */ 204 | VertexPointerType = VertexPointerType.Short; 205 | VertexSize = (sizeof(byte) * 3); 206 | break; 207 | case Constants.PicaDataType.Short: 208 | case Constants.PicaDataType.UnsignedShort: 209 | VertexPointerType = VertexPointerType.Short; 210 | VertexSize = (sizeof(ushort) * 3); 211 | break; 212 | case Constants.PicaDataType.Int: 213 | case Constants.PicaDataType.UnsignedInt: 214 | VertexPointerType = VertexPointerType.Int; 215 | VertexSize = (sizeof(uint) * 3); 216 | break; 217 | case Constants.PicaDataType.Float: 218 | VertexPointerType = VertexPointerType.Float; 219 | VertexSize = (sizeof(float) * 3); 220 | break; 221 | } 222 | 223 | switch (BoneIndexLookupArrayDataType) 224 | { 225 | case Constants.PicaDataType.Byte: 226 | case Constants.PicaDataType.UnsignedByte: 227 | BoneIndexLookupSize = sizeof(byte); 228 | break; 229 | case Constants.PicaDataType.Short: 230 | case Constants.PicaDataType.UnsignedShort: 231 | BoneIndexLookupSize = sizeof(ushort); 232 | break; 233 | case Constants.PicaDataType.Int: 234 | case Constants.PicaDataType.UnsignedInt: 235 | BoneIndexLookupSize = sizeof(uint); 236 | break; 237 | case Constants.PicaDataType.Float: 238 | BoneIndexLookupSize = sizeof(float); 239 | break; 240 | } 241 | 242 | /* For information purposes */ 243 | TotalPrimitives = 0; 244 | foreach (PrmsChunk prms in PrmsChunks) TotalPrimitives += (prms.PrmChunk.NumberOfIndices / 3); 245 | } 246 | 247 | public override string ToString() 248 | { 249 | StringBuilder sb = new StringBuilder(); 250 | 251 | sb.AppendFormat("-- {0} --\n", this.GetType().Name); 252 | sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, 253 | "WARNING: Bunch of unknowns here too...\nNumber of Prms: 0x{0:X}\n" + 254 | "Vertex array data -> Offset: 0x{1:X}, Scale: {2}, Datatype: {3}\n" + 255 | "Normal array data -> Offset: 0x{4:X}, Scale: {5}, Datatype: {6}\n" + 256 | "Color array data -> Offset: 0x{7:X}, Scale: {8}, Datatype: {9}\n" + 257 | "Tex coord array data -> Offset: 0x{10:X}, Scale: {11}, Datatype: {12}\n" + 258 | "Bone lookup array data -> Offset: 0x{13:X}, Scale: {14}, Datatype: {15}\n" + 259 | "Bone weight array data -> Offset: 0x{16:X}, Scale: {17}, Datatype: {18}\n" + 260 | "(data for other arrays here, don't know them...)\n", 261 | PrmsCount, VertexArrayOffset, VertexArrayScale, VertexArrayDataType, 262 | NormalArrayOffset, NormalArrayScale, NormalArrayDataType, 263 | ColorArrayOffset, ColorArrayScale, ColorArrayDataType, 264 | TextureCoordArrayOffset, TextureCoordArrayScale, TextureCoordArrayDataType, 265 | BoneIndexLookupArrayOffset, BoneIndexLookupArrayScale, BoneIndexLookupArrayDataType, 266 | BoneWeightArrayOffset, BoneWeightArrayScale, BoneWeightArrayDataType); 267 | sb.AppendLine(); 268 | 269 | foreach (PrmsChunk prms in PrmsChunks) sb.Append(prms.ToString()); 270 | 271 | return sb.ToString(); 272 | } 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Cmb/ShpChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace N3DSCmbViewer.Cmb 7 | { 8 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 9 | class ShpChunk : BaseCTRChunk 10 | { 11 | // "Shapes"? 12 | public override string ChunkTag { get { return "shp"; } } 13 | 14 | public uint SepdCount { get; private set; } 15 | public uint Unknown1 { get; private set; } 16 | public ushort[] SepdOffsets { get; private set; } 17 | 18 | public SepdChunk[] SepdChunks { get; private set; } 19 | 20 | public ShpChunk(byte[] data, int offset, BaseCTRChunk parent) 21 | : base(data, offset, parent) 22 | { 23 | SepdCount = BitConverter.ToUInt32(ChunkData, 0x8); 24 | Unknown1 = BitConverter.ToUInt32(ChunkData, 0xC); 25 | 26 | SepdOffsets = new ushort[SepdCount]; 27 | for (int i = 0; i < SepdOffsets.Length; i++) SepdOffsets[i] = BitConverter.ToUInt16(ChunkData, 0x10 + (i * 2)); 28 | 29 | SepdChunks = new SepdChunk[SepdCount]; 30 | for (int i = 0; i < SepdChunks.Length; i++) SepdChunks[i] = new SepdChunk(ChunkData, SepdOffsets[i], this); 31 | } 32 | 33 | public override string ToString() 34 | { 35 | StringBuilder sb = new StringBuilder(); 36 | 37 | sb.AppendFormat("-- {0} --\n", this.GetType().Name); 38 | sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "Number of Sepds: 0x{0:X}, Unknown: 0x{1:X}\n", SepdCount, Unknown1); 39 | sb.AppendLine(); 40 | 41 | foreach (SepdChunk sepd in SepdChunks) sb.Append(sepd.ToString()); 42 | 43 | return sb.ToString(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Cmb/SklChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using OpenTK; 7 | 8 | namespace N3DSCmbViewer.Cmb 9 | { 10 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 11 | class SklChunk : BaseCTRChunk 12 | { 13 | // "Skeleton"? 14 | public override string ChunkTag { get { return "skl"; } } 15 | 16 | public uint BoneCount { get; private set; } 17 | public uint Unknown2 { get; private set; } 18 | 19 | public Bone[] Bones { get; private set; } 20 | 21 | public SklChunk(byte[] data, int offset, BaseCTRChunk parent) 22 | : base(data, offset, parent) 23 | { 24 | BoneCount = BitConverter.ToUInt32(ChunkData, 0x8); 25 | Unknown2 = BitConverter.ToUInt32(ChunkData, 0xC); 26 | 27 | Bones = new Bone[BoneCount]; 28 | for (int i = 0; i < Bones.Length; i++) Bones[i] = new Bone(ChunkData, 0x10 + (i * (BaseCTRChunk.IsMajora3D ? Bone.DataSize_MM : Bone.DataSize_OoT))); 29 | 30 | foreach (Bone bone in Bones.Where(x => x.ParentBoneID != -1)) bone.ParentBone = Bones.FirstOrDefault(x => x.BoneID == bone.ParentBoneID); 31 | } 32 | 33 | public override string ToString() 34 | { 35 | StringBuilder sb = new StringBuilder(); 36 | 37 | sb.AppendFormat("-- {0} --\n", this.GetType().Name); 38 | sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "Number of bones: 0x{0:X}, Unknown: 0x{1:X}\n", BoneCount, Unknown2); 39 | sb.AppendLine(); 40 | 41 | foreach (Bone bone in Bones) sb.Append(bone.ToString()); 42 | 43 | return sb.ToString(); 44 | } 45 | 46 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 47 | public class Bone 48 | { 49 | public const int DataSize_OoT = 0x28; 50 | public const int DataSize_MM = 0x2C; 51 | 52 | public sbyte BoneID { get; private set; } 53 | public byte Unknown1 { get; private set; } 54 | public sbyte ParentBoneID { get; private set; } 55 | public byte Unknown2 { get; private set; } 56 | public Vector3 Scale { get; set; } 57 | public Vector3 Rotation { get; set; } 58 | public Vector3 Translation { get; set; } 59 | 60 | public uint UnknownMM { get; set; } 61 | 62 | public Bone ParentBone { get; set; } 63 | 64 | public Bone(byte[] data, int offset) 65 | { 66 | BoneID = (sbyte)data[offset + 0x0]; 67 | Unknown1 = data[offset + 0x1]; 68 | ParentBoneID = (sbyte)data[offset + 0x2]; 69 | Unknown2 = data[offset + 0x3]; 70 | Scale = new Vector3( 71 | BitConverter.ToSingle(data, offset + 0x4), 72 | BitConverter.ToSingle(data, offset + 0x8), 73 | BitConverter.ToSingle(data, offset + 0xC)); 74 | Rotation = new Vector3( 75 | BitConverter.ToSingle(data, offset + 0x10), 76 | BitConverter.ToSingle(data, offset + 0x14), 77 | BitConverter.ToSingle(data, offset + 0x18)); 78 | Translation = new Vector3( 79 | BitConverter.ToSingle(data, offset + 0x1C), 80 | BitConverter.ToSingle(data, offset + 0x20), 81 | BitConverter.ToSingle(data, offset + 0x24)); 82 | 83 | if (BaseCTRChunk.IsMajora3D) 84 | UnknownMM = BitConverter.ToUInt32(data, offset + 0x28); 85 | } 86 | 87 | public override string ToString() 88 | { 89 | StringBuilder sb = new StringBuilder(); 90 | 91 | sb.AppendFormat("-- {0} --\n", this.GetType().Name); 92 | sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, 93 | "Bone ID: {0}, Parent bone ID: {1}\nScale XYZ: {2}, {3}, {4}\nRotation XYZ: {5}, {6}, {7}\nTranslation XYZ: {8}, {9}, {10}\n", 94 | BoneID, ParentBoneID, Scale.X, Scale.Y, Scale.Z, Rotation.X, Rotation.Y, Rotation.Z, Translation.X, Translation.Y, Translation.Z); 95 | sb.AppendLine(); 96 | 97 | return sb.ToString(); 98 | } 99 | 100 | public Matrix4 GetMatrix(bool useTrans) 101 | { 102 | Matrix4 matrix = Matrix4.Identity; 103 | matrix *= Matrix4.CreateScale(Scale); 104 | matrix *= Matrix4.CreateRotationX(Rotation.X); 105 | matrix *= Matrix4.CreateRotationY(Rotation.Y); 106 | matrix *= Matrix4.CreateRotationZ(Rotation.Z); 107 | if (useTrans) matrix *= Matrix4.CreateTranslation(Translation); 108 | 109 | if (ParentBone != null) matrix *= ParentBone.GetMatrix(useTrans); 110 | 111 | return matrix; 112 | } 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Cmb/SklmChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace N3DSCmbViewer.Cmb 7 | { 8 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 9 | class SklmChunk : BaseCTRChunk 10 | { 11 | // "Skeletal Meshes"? 12 | public override string ChunkTag { get { return "sklm"; } } 13 | 14 | public const int MshsChunkPointer = 0x08; 15 | public const int ShpChunkPointer = 0x0C; 16 | 17 | public MshsChunk MshsChunk { get; private set; } 18 | public ShpChunk ShpChunk { get; private set; } 19 | 20 | public SklmChunk(byte[] data, int offset, BaseCTRChunk parent) 21 | : base(data, offset, parent) 22 | { 23 | MshsChunk = new MshsChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, MshsChunkPointer), this); 24 | ShpChunk = new ShpChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, ShpChunkPointer), this); 25 | } 26 | 27 | public override string ToString() 28 | { 29 | StringBuilder sb = new StringBuilder(); 30 | 31 | sb.AppendFormat("-- {0} --\n", this.GetType().Name); 32 | sb.AppendLine(); 33 | 34 | sb.Append(MshsChunk.ToString()); 35 | sb.Append(ShpChunk.ToString()); 36 | 37 | return sb.ToString(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Cmb/TexChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | using System.Drawing.Imaging; 7 | using System.Runtime.InteropServices; 8 | using System.IO; 9 | 10 | using OpenTK; 11 | using OpenTK.Graphics.OpenGL; 12 | 13 | namespace N3DSCmbViewer.Cmb 14 | { 15 | /* Bunch of code taken from Tharsis, makes unevenly sized textures finally correct, for example */ 16 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 17 | class TexChunk : BaseCTRChunk, IDisposable 18 | { 19 | // "Texture"? 20 | public override string ChunkTag { get { return "tex"; } } 21 | 22 | public enum Formats : uint 23 | { 24 | ETC1 = Constants.PicaTextureFormat.ETC1RGB8NativeDMP, 25 | ETC1A4 = Constants.PicaTextureFormat.ETC1AlphaRGB8A4NativeDMP, 26 | RGBA8 = ((uint)Constants.PicaDataType.UnsignedByte << 16 | Constants.PicaTextureFormat.RGBANativeDMP), 27 | RGB8 = ((uint)Constants.PicaDataType.UnsignedByte << 16 | Constants.PicaTextureFormat.RGBNativeDMP), 28 | RGBA4 = ((uint)Constants.PicaDataType.UnsignedShort4444 << 16 | Constants.PicaTextureFormat.RGBANativeDMP), 29 | RGBA5551 = ((uint)Constants.PicaDataType.UnsignedShort5551 << 16 | Constants.PicaTextureFormat.RGBANativeDMP), 30 | RGB565 = ((uint)Constants.PicaDataType.UnsignedShort565 << 16 | Constants.PicaTextureFormat.RGBNativeDMP), 31 | LA4 = ((uint)Constants.PicaDataType.UnsignedByte44DMP << 16 | Constants.PicaTextureFormat.LuminanceAlphaNativeDMP), 32 | LA8 = ((uint)Constants.PicaDataType.UnsignedByte << 16 | Constants.PicaTextureFormat.LuminanceAlphaNativeDMP), 33 | A8 = ((uint)Constants.PicaDataType.UnsignedByte << 16 | Constants.PicaTextureFormat.AlphaNativeDMP), 34 | L8 = ((uint)Constants.PicaDataType.UnsignedByte << 16 | Constants.PicaTextureFormat.LuminanceNativeDMP), 35 | 36 | /* Needs rewrite to support formats w/ <1byte per pixel */ 37 | L4 = ((uint)Constants.PicaDataType.Unsigned4BitsDMP << 16 | Constants.PicaTextureFormat.LuminanceNativeDMP) 38 | }; 39 | 40 | public uint TextureCount { get; private set; } 41 | 42 | public Texture[] Textures { get; private set; } 43 | public bool AreTexturesLoaded { get; private set; } 44 | 45 | static Aglex.Texture dummyTexture; 46 | 47 | bool disposed; 48 | 49 | static TexChunk() 50 | { 51 | dummyTexture = new Aglex.Texture(Properties.Resources.DummyTexture); 52 | } 53 | 54 | public TexChunk(byte[] data, int offset, BaseCTRChunk parent) 55 | : base(data, offset, parent) 56 | { 57 | TextureCount = BitConverter.ToUInt32(ChunkData, 0x8); 58 | 59 | Textures = new Texture[TextureCount]; 60 | for (int i = 0; i < Textures.Length; i++) Textures[i] = new Texture(ChunkData, 0xC + (i * 0x24)); 61 | 62 | AreTexturesLoaded = false; 63 | } 64 | 65 | public override string ToString() 66 | { 67 | StringBuilder sb = new StringBuilder(); 68 | 69 | sb.AppendFormat("-- {0} --\n", this.GetType().Name); 70 | sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "Number of textures: 0x{0:X}\n", TextureCount); 71 | sb.AppendLine(); 72 | 73 | foreach (Texture texture in Textures) sb.Append(texture.ToString()); 74 | 75 | return sb.ToString(); 76 | } 77 | 78 | ~TexChunk() 79 | { 80 | Dispose(false); 81 | } 82 | 83 | public void Dispose() 84 | { 85 | Dispose(true); 86 | GC.SuppressFinalize(this); 87 | } 88 | 89 | protected virtual void Dispose(bool disposing) 90 | { 91 | if (!disposed) 92 | { 93 | if (disposing) 94 | { 95 | foreach (Texture tex in Textures) if (GL.IsTexture(tex.GLID) && tex.GLID != dummyTexture.GetTextureID()) GL.DeleteTexture(tex.GLID); 96 | dummyTexture.Dispose(); 97 | } 98 | 99 | disposed = true; 100 | } 101 | } 102 | 103 | public void LoadTextures() 104 | { 105 | foreach (Texture tex in Textures) tex.Convert((Parent as CmbChunk).TextureData); 106 | 107 | AreTexturesLoaded = true; 108 | } 109 | 110 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 111 | public class Texture 112 | { 113 | [DllImport("ETC1Lib.dll", EntryPoint = "ConvertETC1", CallingConvention = CallingConvention.Cdecl)] 114 | private static extern void ConvertETC1(IntPtr dataOut, ref UInt32 dataOutSize, IntPtr dataIn, UInt16 width, UInt16 height, bool alpha); 115 | 116 | Dictionary bytesPerPixel = new Dictionary() 117 | { 118 | { Formats.ETC1, 4 }, 119 | { Formats.ETC1A4, 4 }, 120 | { Formats.RGBA8, 4 }, 121 | { Formats.RGB8, 3 }, 122 | { Formats.RGBA5551, 2 }, 123 | { Formats.RGB565, 2 }, 124 | { Formats.RGBA4, 2 }, 125 | { Formats.LA8, 2 }, 126 | { Formats.LA4, 1 }, 127 | { Formats.L8, 1 }, 128 | { Formats.A8, 1 }, 129 | }; 130 | 131 | static readonly int[] Convert5To8 = 132 | { 133 | 0x00, 0x08, 0x10, 0x18, 0x20, 0x29, 0x31, 0x39, 134 | 0x41, 0x4A, 0x52, 0x5A, 0x62, 0x6A, 0x73, 0x7B, 135 | 0x83, 0x8B, 0x94, 0x9C, 0xA4, 0xAC, 0xB4, 0xBD, 136 | 0xC5, 0xCD, 0xD5, 0xDE, 0xE6, 0xEE, 0xF6, 0xFF 137 | }; 138 | 139 | public uint DataLength { get; private set; } 140 | public ushort Unknown04 { get; private set; } 141 | public ushort Unknown06 { get; private set; } 142 | public ushort Width { get; private set; } 143 | public ushort Height { get; private set; } 144 | public Formats Format { get; private set; } 145 | public uint DataOffset { get; private set; } 146 | public string Name { get; private set; } 147 | 148 | public int GLID { get; private set; } 149 | 150 | public Bitmap TexImage { get; private set; } 151 | 152 | public Texture(byte[] data, int offset) 153 | { 154 | DataLength = BitConverter.ToUInt32(data, offset); 155 | Unknown04 = BitConverter.ToUInt16(data, offset + 0x4); 156 | Unknown06 = BitConverter.ToUInt16(data, offset + 0x6); 157 | Width = BitConverter.ToUInt16(data, offset + 0x8); 158 | Height = BitConverter.ToUInt16(data, offset + 0xA); 159 | Format = (Formats)BitConverter.ToUInt32(data, offset + 0xC); 160 | DataOffset = BitConverter.ToUInt32(data, offset + 0x10); 161 | Name = Encoding.ASCII.GetString(data, offset + 0x14, 16).TrimEnd('\0'); 162 | } 163 | 164 | public override string ToString() 165 | { 166 | StringBuilder sb = new StringBuilder(); 167 | 168 | sb.AppendFormat("-- {0} --\n", this.GetType().Name); 169 | sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, 170 | "Data length: 0x{0:X}, Unknown (1): 0x{1:X}, Unknown (2): 0x{2:X}\nDimensions: {3}*{4} px\nFormat: {5}, Offset: 0x{6:X}\nName: {7}\n", 171 | DataLength, Unknown04, Unknown06, Width, Height, Format, DataOffset, Name); 172 | sb.AppendLine(); 173 | 174 | return sb.ToString(); 175 | } 176 | 177 | public void Convert(byte[] originalTexData) 178 | { 179 | TexImage = new Bitmap(Width, Height); 180 | 181 | byte[] textureData = new byte[DataLength]; 182 | Buffer.BlockCopy(originalTexData, (int)DataOffset, textureData, 0, textureData.Length); 183 | 184 | if (!Enum.IsDefined(typeof(Formats), Format) || !bytesPerPixel.ContainsKey(Format)) 185 | { 186 | /* Unknown/unsupported */ 187 | GLID = dummyTexture.GetTextureID(); 188 | return; 189 | } 190 | 191 | MemoryStream ms = new MemoryStream(originalTexData, (int)DataOffset, (int)DataLength); 192 | BinaryReader reader = new BinaryReader(ms); 193 | 194 | if (Format == Formats.ETC1 || Format == Formats.ETC1A4) 195 | { 196 | try 197 | { 198 | /* Get compressed data & handle to it */ 199 | ushort[] input = new ushort[textureData.Length / sizeof(ushort)]; 200 | Buffer.BlockCopy(textureData, 0, input, 0, textureData.Length); 201 | GCHandle pInput = GCHandle.Alloc(input, GCHandleType.Pinned); 202 | 203 | /* Marshal data around, invoke ETC1Lib.dll for conversion, etc */ 204 | UInt32 dataSize = 0; 205 | UInt16 marshalWidth = (ushort)Width, marshalHeight = (ushort)Height; 206 | ConvertETC1(IntPtr.Zero, ref dataSize, IntPtr.Zero, marshalWidth, marshalHeight, (Format == Formats.ETC1A4)); 207 | uint[] output = new uint[dataSize]; 208 | GCHandle pOutput = GCHandle.Alloc(output, GCHandleType.Pinned); 209 | ConvertETC1(pOutput.AddrOfPinnedObject(), ref dataSize, pInput.AddrOfPinnedObject(), marshalWidth, marshalHeight, (Format == Formats.ETC1A4)); 210 | pOutput.Free(); 211 | pInput.Free(); 212 | 213 | /* Unscramble if needed // could probably be done in ETC1Lib.dll, it's probably pretty damn ugly, but whatever... */ 214 | /* Non-square code blocks could need some cleanup, verification, etc. as well... */ 215 | uint[] finalized = new uint[output.Length]; 216 | 217 | if (marshalWidth == marshalHeight) 218 | { 219 | /* Perfect square, just copy over */ 220 | Buffer.BlockCopy(output, 0, finalized, 0, finalized.Length); 221 | } 222 | else if (marshalWidth > marshalHeight) 223 | { 224 | /* Wider than tall */ 225 | int numBlocks = (Math.Max(marshalWidth, marshalHeight) / Math.Min(marshalWidth, marshalHeight)); 226 | int rowNumBytes = (marshalWidth << 5); 227 | int blockNumBytes = (rowNumBytes / numBlocks); 228 | int lineNumBytes = (blockNumBytes / 8); 229 | int source = 0, target = 0; 230 | 231 | for (int y = 0; y < marshalHeight / 8; y++) 232 | { 233 | for (int b = 0; b < numBlocks; b++) 234 | { 235 | for (int y2 = 0; y2 < 8; y2++) 236 | { 237 | source = (y * rowNumBytes) + (b * blockNumBytes) + (y2 * lineNumBytes); 238 | target = (y * rowNumBytes) + (y2 * lineNumBytes * numBlocks) + (b * lineNumBytes); 239 | Buffer.BlockCopy(output, source, finalized, target, lineNumBytes); 240 | } 241 | } 242 | } 243 | } 244 | else 245 | { 246 | /* Taller than wide */ 247 | int factor = (marshalHeight / marshalWidth); 248 | int lineSize = (marshalWidth * 4); 249 | int readOffset = 0, writeOffset = 0; 250 | 251 | while (readOffset < output.Length) 252 | { 253 | for (int t = 0; t < 8; t++) 254 | { 255 | for (int i = 0; i < factor; i++) 256 | { 257 | Buffer.BlockCopy(output, readOffset, finalized, writeOffset + (lineSize * 8 * i) + (t * lineSize), lineSize); 258 | readOffset += lineSize; 259 | } 260 | } 261 | writeOffset += (lineSize * factor * 8); 262 | } 263 | } 264 | 265 | /* Finally create texture bitmap from decompressed/unscrambled data */ 266 | BitmapData bmpData = TexImage.LockBits(new Rectangle(0, 0, TexImage.Width, TexImage.Height), ImageLockMode.ReadWrite, TexImage.PixelFormat); 267 | byte[] pixelData = new byte[bmpData.Height * bmpData.Stride]; 268 | Marshal.Copy(bmpData.Scan0, pixelData, 0, pixelData.Length); 269 | 270 | Buffer.BlockCopy(finalized, 0, pixelData, 0, pixelData.Length); 271 | for (int i = 0; i < pixelData.Length; i += 4) 272 | { 273 | byte tmp = pixelData[i]; 274 | pixelData[i] = pixelData[i + 2]; 275 | pixelData[i + 2] = tmp; 276 | } 277 | 278 | Marshal.Copy(pixelData, 0, bmpData.Scan0, pixelData.Length); 279 | TexImage.UnlockBits(bmpData); 280 | } 281 | catch (System.IndexOutOfRangeException e) 282 | { 283 | System.Windows.Forms.MessageBox.Show(e.ToString()); 284 | } 285 | catch (System.AccessViolationException e) 286 | { 287 | System.Windows.Forms.MessageBox.Show(e.ToString()); 288 | } 289 | } 290 | else 291 | { 292 | BitmapData bmpData = TexImage.LockBits(new Rectangle(0, 0, TexImage.Width, TexImage.Height), ImageLockMode.ReadWrite, TexImage.PixelFormat); 293 | byte[] pixelData = new byte[bmpData.Height * bmpData.Stride]; 294 | Marshal.Copy(bmpData.Scan0, pixelData, 0, pixelData.Length); 295 | 296 | for (int y = 0; y < Height; y += 8) 297 | for (int x = 0; x < Width; x += 8) 298 | DecodeTile(8, 8, x, y, ref pixelData, bmpData.Stride, reader, Format); 299 | 300 | Marshal.Copy(pixelData, 0, bmpData.Scan0, pixelData.Length); 301 | TexImage.UnlockBits(bmpData); 302 | } 303 | ms.Close(); 304 | 305 | /* Make OGL texture */ 306 | System.Drawing.Imaging.BitmapData bmpDataOgl = TexImage.LockBits(new Rectangle(0, 0, TexImage.Width, TexImage.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, TexImage.PixelFormat); 307 | 308 | GLID = GL.GenTexture(); 309 | GL.BindTexture(TextureTarget.Texture2D, GLID); 310 | GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, TexImage.Width, TexImage.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmpDataOgl.Scan0); 311 | TexImage.UnlockBits(bmpDataOgl); 312 | 313 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); 314 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); 315 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); 316 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); 317 | 318 | //TexImage.Save(@"D:\temp\mm\" + this.Name + ".png", ImageFormat.Png); 319 | } 320 | 321 | private void DecodeColor(byte[] bytes, Formats format, out int alpha, out int red, out int green, out int blue) 322 | { 323 | int val = -1; 324 | 325 | alpha = red = green = blue = 0xFF; 326 | 327 | switch (format) 328 | { 329 | case Formats.RGBA8: 330 | val = BitConverter.ToInt32(bytes, 0); 331 | red = ((val >> 24) & 0xFF); 332 | green = ((val >> 16) & 0xFF); 333 | blue = ((val >> 8) & 0xFF); 334 | alpha = (val & 0xFF); 335 | break; 336 | 337 | case Formats.RGB8: 338 | red = bytes[2]; 339 | green = bytes[1]; 340 | blue = bytes[0]; 341 | break; 342 | 343 | case Formats.RGBA5551: 344 | val = BitConverter.ToInt16(bytes, 0); 345 | red = Convert5To8[(val >> 11) & 0x1F]; 346 | green = Convert5To8[(val >> 6) & 0x1F]; 347 | blue = Convert5To8[(val >> 1) & 0x1F]; 348 | alpha = (val & 0x0001) == 1 ? 0xFF : 0x00; 349 | break; 350 | 351 | case Formats.RGB565: 352 | val = BitConverter.ToInt16(bytes, 0); 353 | red = Convert5To8[(val >> 11) & 0x1F]; 354 | green = ((val >> 5) & 0x3F) * 4; 355 | blue = Convert5To8[val & 0x1F]; 356 | break; 357 | 358 | case Formats.RGBA4: 359 | val = BitConverter.ToInt16(bytes, 0); 360 | red = (((val >> 12) << 4) & 0xFF); 361 | green = (((val >> 8) << 4) & 0xFF); 362 | blue = (((val >> 4) << 4) & 0xFF); 363 | alpha = ((val << 4) & 0xFF); 364 | break; 365 | 366 | case Formats.LA8: 367 | val = BitConverter.ToInt16(bytes, 0); 368 | red = green = blue = ((val >> 8) & 0xFF); 369 | alpha = (val & 0xFF); 370 | break; 371 | 372 | case Formats.LA4: 373 | val = bytes[0]; 374 | red = green = blue = (((val >> 4) << 4) & 0xFF); 375 | alpha = (((val & 0xF) << 4) & 0xFF); 376 | break; 377 | 378 | case Formats.L8: 379 | alpha = 0xFF; 380 | red = green = blue = bytes[0]; 381 | break; 382 | 383 | case Formats.A8: 384 | alpha = bytes[0]; 385 | red = green = blue = 0xFF; 386 | break; 387 | 388 | case Formats.L4: 389 | /* Temp, not yet working & probably wrong */ 390 | val = bytes[0]; 391 | red = green = blue = (((val >> 4) << 4) & 0xFF); 392 | red = green = blue = (((val & 0xF) << 4) & 0xFF); 393 | break; 394 | } 395 | } 396 | 397 | private void DecodeTile(int iconSize, int tileSize, int ax, int ay, ref byte[] pixelData, int stride, BinaryReader reader, Formats format) 398 | { 399 | if (tileSize == 0) 400 | { 401 | byte[] bytes = new byte[bytesPerPixel[format]]; 402 | Buffer.BlockCopy(reader.ReadBytes(bytes.Length), 0, bytes, 0, bytes.Length); 403 | 404 | int alpha, red, green, blue; 405 | DecodeColor(bytes, format, out alpha, out red, out green, out blue); 406 | 407 | pixelData[(ay * stride) + (ax * (stride / Width)) + 2] = (byte)red; 408 | pixelData[(ay * stride) + (ax * (stride / Width)) + 1] = (byte)green; 409 | pixelData[(ay * stride) + (ax * (stride / Width))] = (byte)blue; 410 | pixelData[(ay * stride) + (ax * (stride / Width)) + 3] = (byte)alpha; 411 | } 412 | else 413 | for (var y = 0; y < iconSize; y += tileSize) 414 | for (var x = 0; x < iconSize; x += tileSize) 415 | DecodeTile(tileSize, tileSize / 2, x + ax, y + ay, ref pixelData, stride, reader, format); 416 | } 417 | } 418 | } 419 | } 420 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Cmb/VatrChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace N3DSCmbViewer.Cmb 7 | { 8 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 9 | class VatrChunk : BaseCTRChunk 10 | { 11 | // "Vertex Attributes"? 12 | public override string ChunkTag { get { return "vatr"; } } 13 | 14 | public const int VertexArray_OoT = 0; 15 | public const int NormalArray_OoT = 1; 16 | public const int ColorArray_OoT = 2; 17 | public const int TextureCoordArray_OoT = 3; 18 | public const int BoneIndexLookupArray_OoT = 6; 19 | public const int BoneWeightArray_OoT = 7; 20 | 21 | public const int VertexArray_MM = 0; 22 | public const int NormalArray_MM = 1; 23 | public const int ColorArray_MM = 3; 24 | public const int TextureCoordArray_MM = 4; 25 | public const int BoneIndexLookupArray_MM = 7; 26 | public const int BoneWeightArray_MM = 8; 27 | 28 | public byte[] Vertices { get { return Arrays[BaseCTRChunk.IsMajora3D ? VertexArray_MM : VertexArray_OoT]; } } 29 | public byte[] Normals { get { return Arrays[BaseCTRChunk.IsMajora3D ? NormalArray_MM : NormalArray_OoT]; } } 30 | public byte[] Colors { get { return Arrays[BaseCTRChunk.IsMajora3D ? ColorArray_MM : ColorArray_OoT]; } } 31 | public byte[] TextureCoords { get { return Arrays[BaseCTRChunk.IsMajora3D ? TextureCoordArray_MM : TextureCoordArray_OoT]; } } 32 | public byte[] BoneIndexLookup { get { return Arrays[BaseCTRChunk.IsMajora3D ? BoneIndexLookupArray_MM : BoneIndexLookupArray_OoT]; } } 33 | public byte[] BoneWeights { get { return Arrays[BaseCTRChunk.IsMajora3D ? BoneWeightArray_MM : BoneWeightArray_OoT]; } } 34 | 35 | public uint MaxVertexIndexOrSomething { get; private set; } 36 | 37 | public uint[] Sizes { get; private set; } 38 | public uint[] Offsets { get; private set; } 39 | public byte[][] Arrays { get; private set; } 40 | 41 | public VatrChunk(byte[] data, int offset, BaseCTRChunk parent) 42 | : base(data, offset, parent) 43 | { 44 | MaxVertexIndexOrSomething = BitConverter.ToUInt32(ChunkData, 0x8); 45 | 46 | int arrayCount = (BaseCTRChunk.IsMajora3D ? 9 : 8); 47 | 48 | Sizes = new uint[arrayCount]; 49 | Offsets = new uint[arrayCount]; 50 | Arrays = new byte[arrayCount][]; 51 | 52 | for (int i = 0; i < arrayCount; i++) 53 | { 54 | Sizes[i] = BitConverter.ToUInt32(ChunkData, 0xC + (i * 8)); 55 | Offsets[i] = BitConverter.ToUInt32(ChunkData, 0x10 + (i * 8)); 56 | 57 | Arrays[i] = new byte[Sizes[i]]; 58 | Buffer.BlockCopy(ChunkData, (int)Offsets[i], Arrays[i], 0, (int)Sizes[i]); 59 | } 60 | } 61 | 62 | public override string ToString() 63 | { 64 | StringBuilder sb = new StringBuilder(); 65 | 66 | sb.AppendFormat("-- {0} --\n", this.GetType().Name); 67 | sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "Unknown (max vert idx?): 0x{0:X}\n", MaxVertexIndexOrSomething); 68 | for (int i = 0; i < Sizes.Length; i++) 69 | { 70 | sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "Array #{0} -> Size: 0x{1:X}, Offset: 0x{2:X}", i, Sizes[i], Offsets[i]); 71 | if (!BaseCTRChunk.IsMajora3D) 72 | { 73 | if (i == VertexArray_OoT) sb.AppendLine(" (vertices)"); 74 | else if (i == NormalArray_OoT) sb.AppendLine(" (normals)"); 75 | else if (i == ColorArray_OoT) sb.AppendLine(" (colors)"); 76 | else if (i == TextureCoordArray_OoT) sb.AppendLine(" (tex coords)"); 77 | else if (i == BoneIndexLookupArray_OoT) sb.AppendLine(" (bone index lookup)"); 78 | else if (i == BoneWeightArray_OoT) sb.AppendLine(" (bone weights)"); 79 | else sb.AppendLine(); 80 | } 81 | else 82 | { 83 | if (i == VertexArray_MM) sb.AppendLine(" (vertices)"); 84 | else if (i == NormalArray_MM) sb.AppendLine(" (normals)"); 85 | else if (i == ColorArray_MM) sb.AppendLine(" (colors)"); 86 | else if (i == TextureCoordArray_MM) sb.AppendLine(" (tex coords)"); 87 | else if (i == BoneIndexLookupArray_MM) sb.AppendLine(" (bone index lookup)"); 88 | else if (i == BoneWeightArray_MM) sb.AppendLine(" (bone weights)"); 89 | else sb.AppendLine(); 90 | } 91 | } 92 | 93 | return sb.ToString(); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Csab/AnimHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.IO; 6 | 7 | using N3DSCmbViewer.Cmb; 8 | 9 | namespace N3DSCmbViewer.Csab 10 | { 11 | class AnimHandler : IDisposable 12 | { 13 | public bool Disposed { get; private set; } 14 | 15 | // 16 | 17 | public string Filename { get; set; } 18 | public byte[] Data { get; private set; } 19 | 20 | public CsabChunk Root { get; private set; } 21 | 22 | public AnimHandler(string filename) 23 | { 24 | Filename = filename; 25 | BinaryReader reader = new BinaryReader(File.Open(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)); 26 | Data = new byte[reader.BaseStream.Length]; 27 | reader.Read(Data, 0, Data.Length); 28 | reader.Close(); 29 | 30 | Load(); 31 | } 32 | 33 | public AnimHandler(byte[] data, int offset, int length) 34 | { 35 | Filename = string.Empty; 36 | Data = new byte[length]; 37 | Buffer.BlockCopy(data, offset, Data, 0, Data.Length); 38 | 39 | Load(); 40 | } 41 | 42 | ~AnimHandler() 43 | { 44 | Dispose(false); 45 | } 46 | 47 | public void Dispose() 48 | { 49 | Dispose(true); 50 | GC.SuppressFinalize(this); 51 | } 52 | 53 | protected virtual void Dispose(bool disposing) 54 | { 55 | if (!Disposed) 56 | { 57 | if (disposing) 58 | { 59 | // dispose all here 60 | } 61 | 62 | Disposed = true; 63 | } 64 | } 65 | 66 | public void Load() 67 | { 68 | Disposed = false; 69 | 70 | Root = new CsabChunk(Data, 0, null); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Csab/AnimNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace N3DSCmbViewer.Csab 7 | { 8 | class AnimNode 9 | { 10 | public const string AnimNodeTag = "anod"; 11 | 12 | public string Tag { get; private set; } 13 | 14 | public uint BoneID { get; private set; } 15 | // 16 | 17 | public AnimNode(CsabChunk parentCsab, int offset) 18 | { 19 | Tag = Encoding.ASCII.GetString(parentCsab.ChunkData, offset, 4).TrimEnd(' '); 20 | 21 | if (Tag != AnimNodeTag) throw new Exception(string.Format("Trying to read data with tag '{0}' as {1}, expected tag '{2}'", Tag, this.GetType().Name, AnimNodeTag)); 22 | 23 | // 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Csab/Animation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace N3DSCmbViewer.Csab 7 | { 8 | class Animation 9 | { 10 | CsabChunk parentCsab; 11 | 12 | public int Offset { get; private set; } 13 | 14 | public uint Unknown00 { get; private set; } 15 | public uint Unknown04 { get; private set; } 16 | public uint Unknown08 { get; private set; } 17 | public uint Unknown0C { get; private set; } 18 | public uint NumberOfUnknownStuffs { get; private set; } 19 | public uint Unknown14 { get; private set; } 20 | public uint NumberOfAnimNodes { get; private set; } 21 | public uint NumberOfBones { get; private set; } 22 | public ushort[] PerBoneIncides { get; private set; } 23 | public uint[] AnimNodeOffsets { get; private set; } 24 | 25 | public AnimNode[] AnimNodes { get; private set; } 26 | 27 | public Animation(CsabChunk parent, int offset) 28 | { 29 | parentCsab = parent; 30 | Offset = offset; 31 | 32 | int rofs = offset; 33 | 34 | Unknown00 = BitConverter.ToUInt32(parent.ChunkData, rofs); 35 | Unknown04 = BitConverter.ToUInt32(parent.ChunkData, rofs + 0x04); 36 | Unknown08 = BitConverter.ToUInt32(parent.ChunkData, rofs + 0x08); 37 | Unknown0C = BitConverter.ToUInt32(parent.ChunkData, rofs + 0x0C); 38 | NumberOfUnknownStuffs = BitConverter.ToUInt32(parent.ChunkData, rofs + 0x10); 39 | Unknown14 = BitConverter.ToUInt32(parent.ChunkData, rofs + 0x14); 40 | NumberOfAnimNodes = BitConverter.ToUInt32(parent.ChunkData, rofs + 0x18); 41 | NumberOfBones = BitConverter.ToUInt32(parent.ChunkData, rofs + 0x1C); 42 | 43 | rofs += 0x20; 44 | PerBoneIncides = new ushort[NumberOfBones]; 45 | for (int i = 0; i < PerBoneIncides.Length; i++) PerBoneIncides[i] = BitConverter.ToUInt16(parent.ChunkData, rofs + (i * sizeof(ushort))); 46 | 47 | rofs += PerBoneIncides.Length * sizeof(ushort); 48 | AnimNodeOffsets = new uint[NumberOfAnimNodes]; 49 | for (int i = 0; i < AnimNodeOffsets.Length; i++) AnimNodeOffsets[i] = BitConverter.ToUInt32(parent.ChunkData, rofs + (i * sizeof(uint))); 50 | 51 | AnimNodes = new AnimNode[NumberOfAnimNodes]; 52 | for (int i = 0; i < AnimNodes.Length; i++) AnimNodes[i] = new AnimNode(parent, Offset + (int)AnimNodeOffsets[i]); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Csab/CsabChunk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace N3DSCmbViewer.Csab 7 | { 8 | class CsabChunk : BaseCTRChunk 9 | { 10 | // "CTR Skeletal Animation Binary"? 11 | public override string ChunkTag { get { return "csab"; } } 12 | 13 | public uint Unknown08 { get; private set; } 14 | public uint Unknown0C { get; private set; } 15 | public uint NumberOfAnimations { get; private set; } 16 | public uint[] AnimationOffsets { get; private set; } 17 | 18 | public Animation[] Animations { get; private set; } 19 | 20 | public CsabChunk(byte[] data, int offset, BaseCTRChunk parent) 21 | : base(data, offset, parent) 22 | { 23 | Unknown08 = BitConverter.ToUInt32(ChunkData, 0x08); 24 | Unknown0C = BitConverter.ToUInt32(ChunkData, 0x0C); 25 | NumberOfAnimations = BitConverter.ToUInt32(ChunkData, 0x10); 26 | 27 | AnimationOffsets = new uint[NumberOfAnimations]; 28 | for (int i = 0; i < AnimationOffsets.Length; i++) AnimationOffsets[i] = BitConverter.ToUInt32(ChunkData, 0x14 + (i * sizeof(uint))); 29 | 30 | Animations = new Animation[NumberOfAnimations]; 31 | for (int i = 0; i < Animations.Length; i++) Animations[i] = new Animation(this, (int)AnimationOffsets[i]); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /N3DSCmbViewer/ETC1Lib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xdanieldzd/N3DSCmbViewer/3c3f66cf40d9122f8d0ebeab07c4db659b426b8b/N3DSCmbViewer/ETC1Lib.dll -------------------------------------------------------------------------------- /N3DSCmbViewer/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Reflection; 6 | using System.ComponentModel; 7 | using System.Windows.Forms; 8 | 9 | namespace N3DSCmbViewer 10 | { 11 | static class Extensions 12 | { 13 | public static string DescriptionAttr(this T source) 14 | { 15 | FieldInfo fi = source.GetType().GetField(source.ToString()); 16 | DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); 17 | if (attributes != null && attributes.Length > 0) return attributes[0].Description; 18 | else return source.ToString(); 19 | } 20 | 21 | public static object DefaultValueAttr(this T source) 22 | { 23 | FieldInfo fi = source.GetType().GetField(source.ToString()); 24 | DefaultValueAttribute[] attributes = (DefaultValueAttribute[])fi.GetCustomAttributes(typeof(DefaultValueAttribute), false); 25 | if (attributes != null && attributes.Length > 0) return attributes[0].Value; 26 | else return source; 27 | } 28 | 29 | public static uint Reverse(this uint value) 30 | { 31 | return (value & 0x000000FFU) << 24 | (value & 0x0000FF00U) << 8 | 32 | (value & 0x00FF0000U) >> 8 | (value & 0xFF000000U) >> 24; 33 | } 34 | 35 | public static ulong Reverse(this ulong value) 36 | { 37 | return ((ulong)Reverse((uint)(value & 0xFFFFFFFF)) << 32 | (ulong)Reverse((uint)(value >> 32))); 38 | } 39 | 40 | public static float[] RGBAToFloats(this uint value) 41 | { 42 | float[] vals = new float[4]; 43 | vals[0] = (float)(((value >> 24) & 0xFF) / 255.0f); 44 | vals[1] = (float)(((value >> 16) & 0xFF) / 255.0f); 45 | vals[2] = (float)(((value >> 8) & 0xFF) / 255.0f); 46 | vals[3] = (float)(((value >> 0) & 0xFF) / 255.0f); 47 | return vals; 48 | } 49 | 50 | public static T GetAttribute(this ICustomAttributeProvider assembly, bool inherit = false) where T : Attribute 51 | { 52 | return assembly.GetCustomAttributes(typeof(T), inherit).OfType().FirstOrDefault(); 53 | } 54 | 55 | public static IEnumerable FlattenTree(this TreeView tv) 56 | { 57 | return FlattenTree(tv.Nodes); 58 | } 59 | 60 | public static IEnumerable FlattenTree(this TreeNodeCollection coll) 61 | { 62 | return coll.Cast().Concat(coll.Cast().SelectMany(x => FlattenTree(x.Nodes))); 63 | } 64 | 65 | public static void RemoveNested(this TreeView tv, TreeNode node) 66 | { 67 | tv.Nodes.Remove(node); 68 | RemoveNestedNode(tv.TopNode, node); 69 | } 70 | 71 | private static void RemoveNestedNode(TreeNode parent, TreeNode nodeToRemove) 72 | { 73 | if (parent == null) return; 74 | 75 | parent.Nodes.Remove(nodeToRemove); 76 | foreach (TreeNode checkNode in parent.Nodes) 77 | { 78 | RemoveNestedNode(checkNode, nodeToRemove); 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /N3DSCmbViewer/LZSS.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.IO; 6 | 7 | namespace N3DSCmbViewer 8 | { 9 | public class LZSS 10 | { 11 | /* https://github.com/lue/MM3D/blob/master/src/lzs.cpp */ 12 | public static byte[] Decompress(byte[] arcdata) 13 | { 14 | string tag = Encoding.ASCII.GetString(arcdata, 0, 4); 15 | uint unknown = BitConverter.ToUInt32(arcdata, 4); 16 | uint decompressedSize = BitConverter.ToUInt32(arcdata, 8); 17 | uint compressedSize = BitConverter.ToUInt32(arcdata, 12); 18 | 19 | if (arcdata.Length != compressedSize + 0x10) throw new Exception("compressed size mismatch"); 20 | 21 | List outdata = new List(); 22 | byte[] BUFFER = new byte[4096]; 23 | for (int i = 0; i < BUFFER.Length; i++) BUFFER[i] = 0; 24 | byte flags8 = 0; 25 | ushort writeidx = 0xFEE; 26 | ushort readidx = 0; 27 | uint fidx = 0x10; 28 | 29 | while (fidx < arcdata.Length) 30 | { 31 | flags8 = arcdata[fidx]; 32 | fidx++; 33 | 34 | for (int i = 0; i < 8; i++) 35 | { 36 | if ((flags8 & 1) != 0) 37 | { 38 | outdata.Add(arcdata[fidx]); 39 | BUFFER[writeidx] = arcdata[fidx]; 40 | writeidx++; writeidx %= 4096; 41 | fidx++; 42 | } 43 | else 44 | { 45 | readidx = arcdata[fidx]; 46 | fidx++; 47 | readidx |= (ushort)((arcdata[fidx] & 0xF0) << 4); 48 | for (int j = 0; j < (arcdata[fidx] & 0x0F) + 3; j++) 49 | { 50 | outdata.Add(BUFFER[readidx]); 51 | BUFFER[writeidx] = BUFFER[readidx]; 52 | readidx++; readidx %= 4096; 53 | writeidx++; writeidx %= 4096; 54 | } 55 | fidx++; 56 | } 57 | flags8 >>= 1; 58 | if (fidx >= arcdata.Length) break; 59 | } 60 | } 61 | 62 | if (decompressedSize != outdata.Count) 63 | throw new Exception(string.Format("Size mismatch: got {0} bytes after decompression, expected {1}.\n", outdata.Count, decompressedSize)); 64 | 65 | return outdata.ToArray(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /N3DSCmbViewer/MainForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace N3DSCmbViewer 2 | { 3 | partial class MainForm 4 | { 5 | /// 6 | /// Erforderliche Designervariable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Verwendete Ressourcen bereinigen. 12 | /// 13 | /// True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Vom Windows Form-Designer generierter Code 24 | 25 | /// 26 | /// Erforderliche Methode für die Designerunterstützung. 27 | /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.components = new System.ComponentModel.Container(); 32 | this.ofdOpenFile = new System.Windows.Forms.OpenFileDialog(); 33 | this.menuStrip1 = new System.Windows.Forms.MenuStrip(); 34 | this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 35 | this.openFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 36 | this.saveScreenshotToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 37 | this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); 38 | this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 39 | this.archiveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 40 | this.extractAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 41 | this.dumpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 42 | this.dumpModelInfosToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 43 | this.dumpCOLLADAFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 44 | this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 45 | this.enableHUDToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 46 | this.resetCameraToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 47 | this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); 48 | this.disableAllShadersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 49 | this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 50 | this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 51 | this.sfdScreenshot = new System.Windows.Forms.SaveFileDialog(); 52 | this.fbdArchiveExtractAll = new System.Windows.Forms.FolderBrowserDialog(); 53 | this.cmsTreeFile = new System.Windows.Forms.ContextMenuStrip(this.components); 54 | this.extractToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 55 | this.sfdExtractFile = new System.Windows.Forms.SaveFileDialog(); 56 | this.sfdLogFile = new System.Windows.Forms.SaveFileDialog(); 57 | this.glControl1 = new Aglex.GLControl(); 58 | this.sfdColladaDae = new System.Windows.Forms.SaveFileDialog(); 59 | this.treeViewEx1 = new N3DSCmbViewer.TreeViewEx(); 60 | this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator(); 61 | this.enableSkeletalRenderingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 62 | this.menuStrip1.SuspendLayout(); 63 | this.cmsTreeFile.SuspendLayout(); 64 | this.SuspendLayout(); 65 | // 66 | // ofdOpenFile 67 | // 68 | this.ofdOpenFile.Filter = "All Supported Files (*.cmb;*.zar;*.zsi;*.gar;*.lzs)|*.cmb;*.zar;*.zsi;*.gar;*.lzs" + 69 | "|All Files (*.*)|*.*"; 70 | this.ofdOpenFile.Title = "Open Cmb File"; 71 | // 72 | // menuStrip1 73 | // 74 | this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 75 | this.fileToolStripMenuItem, 76 | this.archiveToolStripMenuItem, 77 | this.dumpToolStripMenuItem, 78 | this.optionsToolStripMenuItem, 79 | this.helpToolStripMenuItem}); 80 | this.menuStrip1.Location = new System.Drawing.Point(0, 0); 81 | this.menuStrip1.Name = "menuStrip1"; 82 | this.menuStrip1.Size = new System.Drawing.Size(890, 24); 83 | this.menuStrip1.TabIndex = 1; 84 | this.menuStrip1.Text = "menuStrip1"; 85 | // 86 | // fileToolStripMenuItem 87 | // 88 | this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 89 | this.openFileToolStripMenuItem, 90 | this.saveScreenshotToolStripMenuItem, 91 | this.toolStripMenuItem1, 92 | this.exitToolStripMenuItem}); 93 | this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; 94 | this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); 95 | this.fileToolStripMenuItem.Text = "&File"; 96 | // 97 | // openFileToolStripMenuItem 98 | // 99 | this.openFileToolStripMenuItem.Name = "openFileToolStripMenuItem"; 100 | this.openFileToolStripMenuItem.Size = new System.Drawing.Size(158, 22); 101 | this.openFileToolStripMenuItem.Text = "&Open File..."; 102 | this.openFileToolStripMenuItem.Click += new System.EventHandler(this.openFileToolStripMenuItem_Click); 103 | // 104 | // saveScreenshotToolStripMenuItem 105 | // 106 | this.saveScreenshotToolStripMenuItem.Name = "saveScreenshotToolStripMenuItem"; 107 | this.saveScreenshotToolStripMenuItem.Size = new System.Drawing.Size(158, 22); 108 | this.saveScreenshotToolStripMenuItem.Text = "Save &Screenshot"; 109 | this.saveScreenshotToolStripMenuItem.Click += new System.EventHandler(this.saveScreenshotToolStripMenuItem_Click); 110 | // 111 | // toolStripMenuItem1 112 | // 113 | this.toolStripMenuItem1.Name = "toolStripMenuItem1"; 114 | this.toolStripMenuItem1.Size = new System.Drawing.Size(155, 6); 115 | // 116 | // exitToolStripMenuItem 117 | // 118 | this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; 119 | this.exitToolStripMenuItem.Size = new System.Drawing.Size(158, 22); 120 | this.exitToolStripMenuItem.Text = "E&xit"; 121 | this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); 122 | // 123 | // archiveToolStripMenuItem 124 | // 125 | this.archiveToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 126 | this.extractAllToolStripMenuItem}); 127 | this.archiveToolStripMenuItem.Enabled = false; 128 | this.archiveToolStripMenuItem.Name = "archiveToolStripMenuItem"; 129 | this.archiveToolStripMenuItem.Size = new System.Drawing.Size(57, 20); 130 | this.archiveToolStripMenuItem.Text = "&Archive"; 131 | // 132 | // extractAllToolStripMenuItem 133 | // 134 | this.extractAllToolStripMenuItem.Name = "extractAllToolStripMenuItem"; 135 | this.extractAllToolStripMenuItem.Size = new System.Drawing.Size(125, 22); 136 | this.extractAllToolStripMenuItem.Text = "&Extract All"; 137 | this.extractAllToolStripMenuItem.Click += new System.EventHandler(this.extractAllToolStripMenuItem_Click); 138 | // 139 | // dumpToolStripMenuItem 140 | // 141 | this.dumpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 142 | this.dumpModelInfosToolStripMenuItem, 143 | this.dumpCOLLADAFileToolStripMenuItem}); 144 | this.dumpToolStripMenuItem.Enabled = false; 145 | this.dumpToolStripMenuItem.Name = "dumpToolStripMenuItem"; 146 | this.dumpToolStripMenuItem.Size = new System.Drawing.Size(51, 20); 147 | this.dumpToolStripMenuItem.Text = "&Dump"; 148 | // 149 | // dumpModelInfosToolStripMenuItem 150 | // 151 | this.dumpModelInfosToolStripMenuItem.Name = "dumpModelInfosToolStripMenuItem"; 152 | this.dumpModelInfosToolStripMenuItem.Size = new System.Drawing.Size(180, 22); 153 | this.dumpModelInfosToolStripMenuItem.Text = "&Dump Model Infos"; 154 | this.dumpModelInfosToolStripMenuItem.Click += new System.EventHandler(this.dumpModelInfosToolStripMenuItem_Click); 155 | // 156 | // dumpCOLLADAFileToolStripMenuItem 157 | // 158 | this.dumpCOLLADAFileToolStripMenuItem.Name = "dumpCOLLADAFileToolStripMenuItem"; 159 | this.dumpCOLLADAFileToolStripMenuItem.Size = new System.Drawing.Size(180, 22); 160 | this.dumpCOLLADAFileToolStripMenuItem.Text = "Dump &COLLADA File"; 161 | this.dumpCOLLADAFileToolStripMenuItem.Click += new System.EventHandler(this.dumpCOLLADAFileToolStripMenuItem_Click); 162 | // 163 | // optionsToolStripMenuItem 164 | // 165 | this.optionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 166 | this.enableHUDToolStripMenuItem, 167 | this.resetCameraToolStripMenuItem, 168 | this.toolStripMenuItem3, 169 | this.enableSkeletalRenderingToolStripMenuItem, 170 | this.toolStripMenuItem2, 171 | this.disableAllShadersToolStripMenuItem}); 172 | this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem"; 173 | this.optionsToolStripMenuItem.Size = new System.Drawing.Size(61, 20); 174 | this.optionsToolStripMenuItem.Text = "&Options"; 175 | // 176 | // enableHUDToolStripMenuItem 177 | // 178 | this.enableHUDToolStripMenuItem.CheckOnClick = true; 179 | this.enableHUDToolStripMenuItem.Name = "enableHUDToolStripMenuItem"; 180 | this.enableHUDToolStripMenuItem.Size = new System.Drawing.Size(208, 22); 181 | this.enableHUDToolStripMenuItem.Text = "&Enable HUD"; 182 | this.enableHUDToolStripMenuItem.Click += new System.EventHandler(this.enableHUDToolStripMenuItem_Click); 183 | // 184 | // resetCameraToolStripMenuItem 185 | // 186 | this.resetCameraToolStripMenuItem.Name = "resetCameraToolStripMenuItem"; 187 | this.resetCameraToolStripMenuItem.Size = new System.Drawing.Size(208, 22); 188 | this.resetCameraToolStripMenuItem.Text = "&Reset Camera"; 189 | this.resetCameraToolStripMenuItem.Click += new System.EventHandler(this.resetCameraToolStripMenuItem_Click); 190 | // 191 | // toolStripMenuItem2 192 | // 193 | this.toolStripMenuItem2.Name = "toolStripMenuItem2"; 194 | this.toolStripMenuItem2.Size = new System.Drawing.Size(205, 6); 195 | // 196 | // disableAllShadersToolStripMenuItem 197 | // 198 | this.disableAllShadersToolStripMenuItem.CheckOnClick = true; 199 | this.disableAllShadersToolStripMenuItem.Name = "disableAllShadersToolStripMenuItem"; 200 | this.disableAllShadersToolStripMenuItem.Size = new System.Drawing.Size(208, 22); 201 | this.disableAllShadersToolStripMenuItem.Text = "Disable &All Shaders"; 202 | this.disableAllShadersToolStripMenuItem.Click += new System.EventHandler(this.disableAllShadersToolStripMenuItem_Click); 203 | // 204 | // helpToolStripMenuItem 205 | // 206 | this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 207 | this.aboutToolStripMenuItem}); 208 | this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; 209 | this.helpToolStripMenuItem.Size = new System.Drawing.Size(43, 20); 210 | this.helpToolStripMenuItem.Text = "&Help"; 211 | // 212 | // aboutToolStripMenuItem 213 | // 214 | this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; 215 | this.aboutToolStripMenuItem.Size = new System.Drawing.Size(106, 22); 216 | this.aboutToolStripMenuItem.Text = "&About"; 217 | this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click); 218 | // 219 | // sfdScreenshot 220 | // 221 | this.sfdScreenshot.Filter = "PNG Files (*.png)|*.png"; 222 | // 223 | // fbdArchiveExtractAll 224 | // 225 | this.fbdArchiveExtractAll.Description = "Select path to save extracted file to."; 226 | // 227 | // cmsTreeFile 228 | // 229 | this.cmsTreeFile.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 230 | this.extractToolStripMenuItem}); 231 | this.cmsTreeFile.Name = "cmsTreeFile"; 232 | this.cmsTreeFile.Size = new System.Drawing.Size(110, 26); 233 | // 234 | // extractToolStripMenuItem 235 | // 236 | this.extractToolStripMenuItem.Name = "extractToolStripMenuItem"; 237 | this.extractToolStripMenuItem.Size = new System.Drawing.Size(109, 22); 238 | this.extractToolStripMenuItem.Text = "&Extract"; 239 | this.extractToolStripMenuItem.Click += new System.EventHandler(this.extractToolStripMenuItem_Click); 240 | // 241 | // sfdExtractFile 242 | // 243 | this.sfdExtractFile.Filter = "All Files (*.*)|*.*"; 244 | // 245 | // sfdLogFile 246 | // 247 | this.sfdLogFile.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"; 248 | // 249 | // glControl1 250 | // 251 | this.glControl1.BackColor = System.Drawing.Color.SkyBlue; 252 | this.glControl1.Camera = true; 253 | this.glControl1.Dock = System.Windows.Forms.DockStyle.Fill; 254 | this.glControl1.Lighting = true; 255 | this.glControl1.Location = new System.Drawing.Point(250, 24); 256 | this.glControl1.Name = "glControl1"; 257 | this.glControl1.ProjectionType = Aglex.ProjectionTypes.Perspective; 258 | this.glControl1.Size = new System.Drawing.Size(640, 480); 259 | this.glControl1.TabIndex = 0; 260 | this.glControl1.VSync = true; 261 | this.glControl1.Render += new System.EventHandler(this.glControl1_Render); 262 | this.glControl1.Load += new System.EventHandler(this.glControl1_Load); 263 | this.glControl1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.glControl1_KeyDown); 264 | // 265 | // sfdColladaDae 266 | // 267 | this.sfdColladaDae.Filter = "COLLADA File (*.dae)|*.dae|All Files (*.*)|*.*"; 268 | // 269 | // treeViewEx1 270 | // 271 | this.treeViewEx1.Dock = System.Windows.Forms.DockStyle.Left; 272 | this.treeViewEx1.HideSelection = false; 273 | this.treeViewEx1.Location = new System.Drawing.Point(0, 24); 274 | this.treeViewEx1.Name = "treeViewEx1"; 275 | this.treeViewEx1.Size = new System.Drawing.Size(250, 480); 276 | this.treeViewEx1.TabIndex = 2; 277 | this.treeViewEx1.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeViewEx1_AfterSelect); 278 | this.treeViewEx1.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.treeViewEx1_NodeMouseClick); 279 | // 280 | // toolStripMenuItem3 281 | // 282 | this.toolStripMenuItem3.Name = "toolStripMenuItem3"; 283 | this.toolStripMenuItem3.Size = new System.Drawing.Size(205, 6); 284 | // 285 | // enableSkeletalRenderingToolStripMenuItem 286 | // 287 | this.enableSkeletalRenderingToolStripMenuItem.CheckOnClick = true; 288 | this.enableSkeletalRenderingToolStripMenuItem.Name = "enableSkeletalRenderingToolStripMenuItem"; 289 | this.enableSkeletalRenderingToolStripMenuItem.Size = new System.Drawing.Size(208, 22); 290 | this.enableSkeletalRenderingToolStripMenuItem.Text = "Enable &Skeletal Rendering"; 291 | this.enableSkeletalRenderingToolStripMenuItem.Click += new System.EventHandler(this.enableSkeletalRenderingToolStripMenuItem_Click); 292 | // 293 | // MainForm 294 | // 295 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 296 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 297 | this.ClientSize = new System.Drawing.Size(890, 504); 298 | this.Controls.Add(this.glControl1); 299 | this.Controls.Add(this.treeViewEx1); 300 | this.Controls.Add(this.menuStrip1); 301 | this.MainMenuStrip = this.menuStrip1; 302 | this.Name = "MainForm"; 303 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 304 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); 305 | this.menuStrip1.ResumeLayout(false); 306 | this.menuStrip1.PerformLayout(); 307 | this.cmsTreeFile.ResumeLayout(false); 308 | this.ResumeLayout(false); 309 | this.PerformLayout(); 310 | 311 | } 312 | 313 | #endregion 314 | 315 | private Aglex.GLControl glControl1; 316 | private System.Windows.Forms.OpenFileDialog ofdOpenFile; 317 | private System.Windows.Forms.MenuStrip menuStrip1; 318 | private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; 319 | private System.Windows.Forms.ToolStripMenuItem openFileToolStripMenuItem; 320 | private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; 321 | private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; 322 | private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem; 323 | private System.Windows.Forms.ToolStripMenuItem enableHUDToolStripMenuItem; 324 | private System.Windows.Forms.SaveFileDialog sfdScreenshot; 325 | private System.Windows.Forms.ToolStripMenuItem saveScreenshotToolStripMenuItem; 326 | private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; 327 | private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; 328 | private TreeViewEx treeViewEx1; 329 | private System.Windows.Forms.ToolStripMenuItem archiveToolStripMenuItem; 330 | private System.Windows.Forms.ToolStripMenuItem extractAllToolStripMenuItem; 331 | private System.Windows.Forms.FolderBrowserDialog fbdArchiveExtractAll; 332 | private System.Windows.Forms.ContextMenuStrip cmsTreeFile; 333 | private System.Windows.Forms.ToolStripMenuItem extractToolStripMenuItem; 334 | private System.Windows.Forms.SaveFileDialog sfdExtractFile; 335 | private System.Windows.Forms.ToolStripMenuItem resetCameraToolStripMenuItem; 336 | private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2; 337 | private System.Windows.Forms.ToolStripMenuItem dumpToolStripMenuItem; 338 | private System.Windows.Forms.ToolStripMenuItem dumpModelInfosToolStripMenuItem; 339 | private System.Windows.Forms.SaveFileDialog sfdLogFile; 340 | private System.Windows.Forms.ToolStripMenuItem disableAllShadersToolStripMenuItem; 341 | private System.Windows.Forms.ToolStripMenuItem dumpCOLLADAFileToolStripMenuItem; 342 | private System.Windows.Forms.SaveFileDialog sfdColladaDae; 343 | private System.Windows.Forms.ToolStripSeparator toolStripMenuItem3; 344 | private System.Windows.Forms.ToolStripMenuItem enableSkeletalRenderingToolStripMenuItem; 345 | } 346 | } 347 | 348 | -------------------------------------------------------------------------------- /N3DSCmbViewer/MainForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | 124 | 142, 17 125 | 126 | 127 | 257, 17 128 | 129 | 130 | 385, 17 131 | 132 | 133 | 546, 17 134 | 135 | 136 | 661, 17 137 | 138 | 139 | 784, 17 140 | 141 | 142 | 891, 17 143 | 144 | -------------------------------------------------------------------------------- /N3DSCmbViewer/N3DSCmbViewer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {BA569D8C-09D3-4BFC-B49F-7432A5FC7139} 9 | WinExe 10 | Properties 11 | N3DSCmbViewer 12 | N3DSCmbViewer 13 | v4.0 14 | 15 | 16 | 512 17 | 18 | 19 | x86 20 | true 21 | full 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | prompt 26 | 4 27 | false 28 | 29 | 30 | x86 31 | pdbonly 32 | true 33 | bin\Release\ 34 | TRACE 35 | prompt 36 | 4 37 | false 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | Form 64 | 65 | 66 | MainForm.cs 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | Component 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | MainForm.cs 96 | 97 | 98 | ResXFileCodeGenerator 99 | Resources.Designer.cs 100 | Designer 101 | 102 | 103 | True 104 | Resources.resx 105 | True 106 | 107 | 108 | 109 | Always 110 | 111 | 112 | SettingsSingleFileGenerator 113 | Settings.Designer.cs 114 | 115 | 116 | True 117 | Settings.settings 118 | True 119 | 120 | 121 | Always 122 | 123 | 124 | 125 | 126 | {A3F8E581-B021-48CE-934F-79F070D64821} 127 | Aglex 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | Always 136 | 137 | 138 | 139 | 146 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using System.Reflection; 6 | 7 | namespace N3DSCmbViewer 8 | { 9 | static class Program 10 | { 11 | public static string Description = string.Format("{0} v{1}", 12 | Assembly.GetExecutingAssembly().GetAttribute().Description, 13 | new Version(Assembly.GetExecutingAssembly().GetAttribute().Version).ToString(3)); 14 | 15 | [STAThread] 16 | static void Main() 17 | { 18 | /* Make sure OpenTK doesn't swallow ANY BLOODY EXCEPTION THAT OCCURES DURING RENDERING */ 19 | Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); 20 | 21 | Application.EnableVisualStyles(); 22 | Application.SetCompatibleTextRenderingDefault(false); 23 | Application.Run(new MainForm()); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // Allgemeine Informationen über eine Assembly werden über die folgenden 6 | // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, 7 | // die mit einer Assembly verknüpft sind. 8 | [assembly: AssemblyTitle("N3DSCmbViewer")] 9 | [assembly: AssemblyDescription("Experimental Cmb Viewer")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("xdaniel")] 12 | [assembly: AssemblyProduct("N3DSCmbViewer")] 13 | [assembly: AssemblyCopyright("Written 2014-2015 by xdaniel / DigitalZero Domain")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar 18 | // für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von 19 | // COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. 20 | [assembly: ComVisible(false)] 21 | 22 | // Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird 23 | [assembly: Guid("83c4f3bf-9396-4928-878e-b721d273d5ca")] 24 | 25 | // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: 26 | // 27 | // Hauptversion 28 | // Nebenversion 29 | // Buildnummer 30 | // Revision 31 | // 32 | // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern 33 | // übernehmen, indem Sie "*" eingeben: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("0.2.6.0")] 36 | [assembly: AssemblyFileVersion("0.2.6.0")] 37 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // Dieser Code wurde von einem Tool generiert. 4 | // Laufzeitversion:4.0.30319.18052 5 | // 6 | // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn 7 | // der Code erneut generiert wird. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace N3DSCmbViewer.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. 17 | /// 18 | // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert 19 | // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. 20 | // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen 21 | // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("N3DSCmbViewer.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle 51 | /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap DummyTexture { 67 | get { 68 | object obj = ResourceManager.GetObject("DummyTexture", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\dummytexture.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // Dieser Code wurde von einem Tool generiert. 4 | // Laufzeitversion:4.0.30319.18408 5 | // 6 | // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn 7 | // der Code erneut generiert wird. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace N3DSCmbViewer.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("")] 29 | public string LastFile { 30 | get { 31 | return ((string)(this["LastFile"])); 32 | } 33 | set { 34 | this["LastFile"] = value; 35 | } 36 | } 37 | 38 | [global::System.Configuration.UserScopedSettingAttribute()] 39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 40 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 41 | public bool AddWireframeOverlay { 42 | get { 43 | return ((bool)(this["AddWireframeOverlay"])); 44 | } 45 | set { 46 | this["AddWireframeOverlay"] = value; 47 | } 48 | } 49 | 50 | [global::System.Configuration.UserScopedSettingAttribute()] 51 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 52 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 53 | public bool EnableTextures { 54 | get { 55 | return ((bool)(this["EnableTextures"])); 56 | } 57 | set { 58 | this["EnableTextures"] = value; 59 | } 60 | } 61 | 62 | [global::System.Configuration.UserScopedSettingAttribute()] 63 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 64 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 65 | public bool VSync { 66 | get { 67 | return ((bool)(this["VSync"])); 68 | } 69 | set { 70 | this["VSync"] = value; 71 | } 72 | } 73 | 74 | [global::System.Configuration.UserScopedSettingAttribute()] 75 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 76 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 77 | public bool EnableHUD { 78 | get { 79 | return ((bool)(this["EnableHUD"])); 80 | } 81 | set { 82 | this["EnableHUD"] = value; 83 | } 84 | } 85 | 86 | [global::System.Configuration.UserScopedSettingAttribute()] 87 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 88 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 89 | public bool DisableAllShaders { 90 | get { 91 | return ((bool)(this["DisableAllShaders"])); 92 | } 93 | set { 94 | this["DisableAllShaders"] = value; 95 | } 96 | } 97 | 98 | [global::System.Configuration.UserScopedSettingAttribute()] 99 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 100 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 101 | public bool EnableLighting { 102 | get { 103 | return ((bool)(this["EnableLighting"])); 104 | } 105 | set { 106 | this["EnableLighting"] = value; 107 | } 108 | } 109 | 110 | [global::System.Configuration.UserScopedSettingAttribute()] 111 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 112 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 113 | public bool DisableAlpha { 114 | get { 115 | return ((bool)(this["DisableAlpha"])); 116 | } 117 | set { 118 | this["DisableAlpha"] = value; 119 | } 120 | } 121 | 122 | [global::System.Configuration.UserScopedSettingAttribute()] 123 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 124 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 125 | public bool EnableSkeletalStuff { 126 | get { 127 | return ((bool)(this["EnableSkeletalStuff"])); 128 | } 129 | set { 130 | this["EnableSkeletalStuff"] = value; 131 | } 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | False 10 | 11 | 12 | True 13 | 14 | 15 | True 16 | 17 | 18 | True 19 | 20 | 21 | False 22 | 23 | 24 | False 25 | 26 | 27 | False 28 | 29 | 30 | False 31 | 32 | 33 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Resources/dummytexture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xdanieldzd/N3DSCmbViewer/3c3f66cf40d9122f8d0ebeab07c4db659b426b8b/N3DSCmbViewer/Resources/dummytexture.png -------------------------------------------------------------------------------- /N3DSCmbViewer/Shaders/DVLB.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.IO; 6 | 7 | namespace N3DSCmbViewer.Shaders 8 | { 9 | /* 10 | * Would've been impossible for me without: 11 | * http://www.3dbrew.org/wiki/SHBIN 12 | * http://3dbrew.org/wiki/Shader_Instruction_Set 13 | * https://github.com/smealum/aemstro 14 | * 15 | * ...but note that my work here is 1) outdated compared to the 3dbrew wiki's current (Apr 14 2014) state and 2) doesn't -do- anything yet 16 | */ 17 | 18 | class DVLB : IDisposable 19 | { 20 | public const string DVLBMagic = "DVLB"; 21 | 22 | public bool Disposed { get; private set; } 23 | 24 | public string Magic { get; private set; } 25 | public uint NumberOfDVLEs { get; private set; } 26 | public uint[] DVLEOffsets { get; private set; } 27 | public DVLE[] DVLEs { get; private set; } 28 | 29 | public DVLP DVLP { get; private set; } 30 | 31 | public string Filename { get; set; } 32 | public byte[] Data { get; private set; } 33 | 34 | #region Constructor/Destructor/Disposal 35 | 36 | public DVLB(string filename) 37 | { 38 | Filename = filename; 39 | BinaryReader reader = new BinaryReader(File.Open(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)); 40 | Data = new byte[reader.BaseStream.Length]; 41 | reader.Read(Data, 0, Data.Length); 42 | reader.Close(); 43 | 44 | Load(); 45 | } 46 | 47 | public DVLB(byte[] data, int offset, int length) 48 | { 49 | Filename = string.Empty; 50 | Data = new byte[length]; 51 | Buffer.BlockCopy(data, offset, Data, 0, Data.Length); 52 | 53 | Load(); 54 | } 55 | 56 | ~DVLB() 57 | { 58 | Dispose(false); 59 | } 60 | 61 | public void Dispose() 62 | { 63 | Dispose(true); 64 | GC.SuppressFinalize(this); 65 | } 66 | 67 | protected virtual void Dispose(bool disposing) 68 | { 69 | if (!Disposed) 70 | { 71 | if (disposing) 72 | { 73 | // dispose all here 74 | } 75 | 76 | Disposed = true; 77 | } 78 | } 79 | 80 | #endregion 81 | 82 | public void Load() 83 | { 84 | Disposed = false; 85 | 86 | Magic = Encoding.ASCII.GetString(Data, 0x00, 4); 87 | if (Magic != DVLBMagic) throw new Exception(string.Format("Trying to read data with tag '{0}' as {1}, expected tag '{2}'", Magic, this.GetType().Name, DVLBMagic)); 88 | 89 | NumberOfDVLEs = BitConverter.ToUInt32(Data, 0x04); 90 | DVLEOffsets = new uint[NumberOfDVLEs]; 91 | DVLEs = new DVLE[NumberOfDVLEs]; 92 | 93 | for (int i = 0; i < NumberOfDVLEs; i++) 94 | { 95 | DVLEOffsets[i] = BitConverter.ToUInt32(Data, 0x08 + i * sizeof(uint)); 96 | DVLEs[i] = new DVLE(this, DVLEOffsets[i]); 97 | } 98 | 99 | DVLP = new DVLP(this, 0x08 + (NumberOfDVLEs * sizeof(uint))); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Shaders/DVLE.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.IO; 6 | 7 | namespace N3DSCmbViewer.Shaders 8 | { 9 | class DVLE : IDisposable 10 | { 11 | public const string DVLEMagic = "DVLE"; 12 | 13 | public enum ShaderTypes : byte { VertexShader = 0, GeometryShader = 1 }; 14 | 15 | public bool Disposed { get; private set; } 16 | 17 | public string Magic { get; private set; } 18 | public ShaderTypes ShaderType { get; private set; } 19 | public uint ProgramMainOffset { get; private set; } 20 | public uint ProgramEndMainOffset { get; private set; } 21 | public uint Unknown0x10 { get; private set; } 22 | public uint Unknown0x14 { get; private set; } 23 | public uint UniformTableOffset { get; private set; } 24 | public uint NumberOfUniformEntries { get; private set; } 25 | public uint LabelTableOffset { get; private set; } 26 | public uint NumberOfLabelEntries { get; private set; } 27 | public uint UnknownTableOffset { get; private set; } 28 | public uint NumberOfUnknownEntries { get; private set; } 29 | public uint VariableTableOffset { get; private set; } 30 | public uint NumberOfVariableEntries { get; private set; } 31 | public uint SymbolTableOffset { get; private set; } 32 | public uint SizeOfSymbolTable { get; private set; } 33 | 34 | public UniformTableEntry[] UniformTable { get; private set; } 35 | public LabelTableEntry[] LabelTable { get; private set; } 36 | //unknown table 37 | public VariableTableEntry[] VariableTable { get; private set; } 38 | 39 | public DVLB ParentDVLB { get; private set; } 40 | public uint Offset { get; private set; } 41 | 42 | #region Constructor/Destructor/Disposal 43 | 44 | public DVLE(DVLB parent, uint offset) 45 | { 46 | ParentDVLB = parent; 47 | Offset = offset; 48 | 49 | Load(); 50 | } 51 | 52 | ~DVLE() 53 | { 54 | Dispose(false); 55 | } 56 | 57 | public void Dispose() 58 | { 59 | Dispose(true); 60 | GC.SuppressFinalize(this); 61 | } 62 | 63 | protected virtual void Dispose(bool disposing) 64 | { 65 | if (!Disposed) 66 | { 67 | if (disposing) 68 | { 69 | // dispose all here 70 | } 71 | 72 | Disposed = true; 73 | } 74 | } 75 | 76 | #endregion 77 | 78 | public void Load() 79 | { 80 | Disposed = false; 81 | 82 | Magic = Encoding.ASCII.GetString(ParentDVLB.Data, (int)Offset + 0x00, 4); 83 | if (Magic != DVLEMagic) throw new Exception(string.Format("Trying to read data with tag '{0}' as {1}, expected tag '{2}'", Magic, this.GetType().Name, DVLEMagic)); 84 | 85 | ShaderType = (ShaderTypes)ParentDVLB.Data[Offset + 0x06]; 86 | ProgramMainOffset = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x08); 87 | ProgramEndMainOffset = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x0C); 88 | Unknown0x10 = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x10); 89 | Unknown0x14 = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x14); 90 | UniformTableOffset = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x18); 91 | NumberOfUniformEntries = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x1C); 92 | LabelTableOffset = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x20); 93 | NumberOfLabelEntries = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x24); 94 | UnknownTableOffset = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x28); 95 | NumberOfUnknownEntries = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x2C); 96 | VariableTableOffset = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x30); 97 | NumberOfVariableEntries = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x34); 98 | SymbolTableOffset = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x38); 99 | SizeOfSymbolTable = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x3C); 100 | 101 | UniformTable = new UniformTableEntry[NumberOfUniformEntries]; 102 | for (int i = 0; i < UniformTable.Length; i++) UniformTable[i] = new UniformTableEntry(this, (int)UniformTableOffset + (i * UniformTableEntry.Size)); 103 | 104 | LabelTable = new LabelTableEntry[NumberOfLabelEntries]; 105 | for (int i = 0; i < LabelTable.Length; i++) LabelTable[i] = new LabelTableEntry(this, (int)LabelTableOffset + (i * LabelTableEntry.Size)); 106 | 107 | //unknown table 108 | 109 | VariableTable = new VariableTableEntry[NumberOfVariableEntries]; 110 | for (int i = 0; i < VariableTable.Length; i++) VariableTable[i] = new VariableTableEntry(this, (int)VariableTableOffset + (i * VariableTableEntry.Size)); 111 | } 112 | 113 | public class UniformTableEntry 114 | { 115 | public const int Size = 0x14; 116 | 117 | public byte UniformID { get; private set; } 118 | public float X { get; private set; } 119 | public float Y { get; private set; } 120 | public float Z { get; private set; } 121 | public float W { get; private set; } 122 | 123 | public UniformTableEntry(DVLE parent, int offset) 124 | { 125 | int readOffset = (int)(parent.Offset + offset); 126 | UniformID = parent.ParentDVLB.Data[readOffset + 0x02]; 127 | X = ConvertFloat24(BitConverter.ToUInt32(parent.ParentDVLB.Data, readOffset + 0x04)); 128 | Y = ConvertFloat24(BitConverter.ToUInt32(parent.ParentDVLB.Data, readOffset + 0x08)); 129 | Z = ConvertFloat24(BitConverter.ToUInt32(parent.ParentDVLB.Data, readOffset + 0x0C)); 130 | W = ConvertFloat24(BitConverter.ToUInt32(parent.ParentDVLB.Data, readOffset + 0x10)); 131 | } 132 | 133 | private float ConvertFloat24(uint val) 134 | { 135 | if (val == 0) return 0.0f; 136 | uint tmp = ((val >> 16) & 0xFF) + 0x40; 137 | uint outp = ((tmp << 23) | ((val & 0x800000) << 31) | ((val & 0xFFFF) << 7)); 138 | return BitConverter.ToSingle(BitConverter.GetBytes(outp), 0); 139 | } 140 | } 141 | 142 | public class LabelTableEntry 143 | { 144 | public const int Size = 0x10; 145 | 146 | public byte LabelID { get; private set; } 147 | public uint LocationOffset { get; private set; } 148 | public uint Unknown { get; private set; } 149 | public uint SymbolOffset { get; private set; } 150 | 151 | public string LabelSymbol { get; private set; } 152 | 153 | public LabelTableEntry(DVLE parent, int offset) 154 | { 155 | int readOffset = (int)(parent.Offset + offset); 156 | LabelID = parent.ParentDVLB.Data[readOffset + 0x00]; 157 | LocationOffset = BitConverter.ToUInt32(parent.ParentDVLB.Data, readOffset + 0x04); 158 | Unknown = BitConverter.ToUInt32(parent.ParentDVLB.Data, readOffset + 0x08); 159 | SymbolOffset = BitConverter.ToUInt32(parent.ParentDVLB.Data, readOffset + 0x0C); 160 | 161 | readOffset = (int)(parent.Offset + parent.SymbolTableOffset + SymbolOffset); 162 | int len = Array.IndexOf(parent.ParentDVLB.Data, (byte)0, readOffset) - readOffset; 163 | LabelSymbol = Encoding.ASCII.GetString(parent.ParentDVLB.Data, readOffset, len); 164 | } 165 | } 166 | 167 | public class VariableTableEntry 168 | { 169 | public const int Size = 0x08; 170 | 171 | public uint SymbolOffset { get; private set; } 172 | public ushort StartRegister { get; private set; } 173 | public ushort EndRegister { get; private set; } 174 | 175 | public string VariableSymbol { get; private set; } 176 | 177 | public VariableTableEntry(DVLE parent, int offset) 178 | { 179 | int readOffset = (int)(parent.Offset + offset); 180 | SymbolOffset = BitConverter.ToUInt32(parent.ParentDVLB.Data, readOffset + 0x00); 181 | StartRegister = BitConverter.ToUInt16(parent.ParentDVLB.Data, readOffset + 0x04); 182 | EndRegister = BitConverter.ToUInt16(parent.ParentDVLB.Data, readOffset + 0x06); 183 | 184 | readOffset = (int)(parent.Offset + parent.SymbolTableOffset + SymbolOffset); 185 | int len = Array.IndexOf(parent.ParentDVLB.Data, (byte)0, readOffset) - readOffset; 186 | VariableSymbol = Encoding.ASCII.GetString(parent.ParentDVLB.Data, readOffset, len); 187 | } 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Shaders/DVLP.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.IO; 6 | 7 | namespace N3DSCmbViewer.Shaders 8 | { 9 | class DVLP : IDisposable 10 | { 11 | public const string DVLPMagic = "DVLP"; 12 | 13 | public bool Disposed { get; private set; } 14 | 15 | public string Magic { get; private set; } 16 | public uint ShaderBinaryOffset { get; private set; } 17 | public uint SizeOfShaderBinary { get; private set; } 18 | public uint ShaderInstructionExtensionTableOffset { get; private set; } 19 | public uint NumberOfShaderInstrExtTblEntries { get; private set; } 20 | public uint FilenameSymbolTableOffset { get; private set; } 21 | 22 | public byte[] ShaderBinary { get; private set; } 23 | public ulong[] ShaderInstructionExtensionTable { get; private set; } 24 | 25 | public DVLB ParentDVLB { get; private set; } 26 | public uint Offset { get; private set; } 27 | 28 | #region Constructor/Destructor/Disposal 29 | 30 | public DVLP(DVLB parent, uint offset) 31 | { 32 | ParentDVLB = parent; 33 | Offset = offset; 34 | 35 | Load(); 36 | } 37 | 38 | ~DVLP() 39 | { 40 | Dispose(false); 41 | } 42 | 43 | public void Dispose() 44 | { 45 | Dispose(true); 46 | GC.SuppressFinalize(this); 47 | } 48 | 49 | protected virtual void Dispose(bool disposing) 50 | { 51 | if (!Disposed) 52 | { 53 | if (disposing) 54 | { 55 | // dispose all here 56 | } 57 | 58 | Disposed = true; 59 | } 60 | } 61 | 62 | #endregion 63 | 64 | public void Load() 65 | { 66 | Disposed = false; 67 | 68 | Magic = Encoding.ASCII.GetString(ParentDVLB.Data, (int)Offset + 0x00, 4); 69 | if (Magic != DVLPMagic) throw new Exception(string.Format("Trying to read data with tag '{0}' as {1}, expected tag '{2}'", Magic, this.GetType().Name, DVLPMagic)); 70 | 71 | ShaderBinaryOffset = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x08); 72 | SizeOfShaderBinary = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x0C); 73 | ShaderInstructionExtensionTableOffset = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x10); 74 | NumberOfShaderInstrExtTblEntries = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x14); 75 | FilenameSymbolTableOffset = BitConverter.ToUInt32(ParentDVLB.Data, (int)Offset + 0x18); 76 | 77 | ShaderBinary = new byte[SizeOfShaderBinary * sizeof(uint)]; 78 | Buffer.BlockCopy(ParentDVLB.Data, (int)(Offset + ShaderBinaryOffset), ShaderBinary, 0, ShaderBinary.Length); 79 | 80 | ShaderInstructionExtensionTable = new ulong[NumberOfShaderInstrExtTblEntries]; 81 | Buffer.BlockCopy(ParentDVLB.Data, (int)(Offset + ShaderInstructionExtensionTableOffset), ShaderInstructionExtensionTable, 0, ShaderInstructionExtensionTable.Length * sizeof(ulong)); 82 | 83 | // TODO actually do stuff with the shader binary! 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /N3DSCmbViewer/TreeViewEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows.Forms; 6 | 7 | namespace N3DSCmbViewer 8 | { 9 | class TreeViewEx : TreeView 10 | { 11 | protected override void OnHandleCreated(EventArgs e) 12 | { 13 | base.OnHandleCreated(e); 14 | 15 | this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw, true); 16 | 17 | if (!this.DesignMode && Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= 6) 18 | { 19 | Win32.SetWindowTheme(this.Handle, "explorer", null); 20 | this.ShowLines = false; 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /N3DSCmbViewer/Win32.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | using System.Runtime.InteropServices; 7 | using System.Windows.Forms; 8 | 9 | namespace N3DSCmbViewer 10 | { 11 | public static class Win32 12 | { 13 | [DllImport("kernel32")] 14 | public static extern bool AllocConsole(); 15 | 16 | [DllImport("uxtheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode)] 17 | public static extern int SetWindowTheme(IntPtr hwnd, string pszSubAppName, string pszSubIdList); 18 | 19 | [DllImport("user32.dll", CharSet = CharSet.Auto)] 20 | public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); 21 | 22 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 23 | public struct SHFILEINFO 24 | { 25 | public IntPtr hIcon; 26 | public int iIcon; 27 | public uint dwAttributes; 28 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] 29 | public string szDisplayName; 30 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] 31 | public string szTypeName; 32 | }; 33 | 34 | public enum FolderType 35 | { 36 | Closed, 37 | Open 38 | } 39 | 40 | public enum IconSize 41 | { 42 | Large, 43 | Small 44 | } 45 | 46 | [DllImport("shell32.dll", CharSet = CharSet.Auto)] 47 | public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, out SHFILEINFO psfi, uint cbFileInfo, uint uFlags); 48 | 49 | [DllImport("user32.dll", SetLastError = true)] 50 | [return: MarshalAs(UnmanagedType.Bool)] 51 | static extern bool DestroyIcon(IntPtr hIcon); 52 | 53 | public const uint SHGFI_ICON = 0x000000100; 54 | public const uint SHGFI_USEFILEATTRIBUTES = 0x000000010; 55 | public const uint SHGFI_OPENICON = 0x000000002; 56 | public const uint SHGFI_SMALLICON = 0x000000001; 57 | public const uint SHGFI_LARGEICON = 0x000000000; 58 | public const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010; 59 | public const uint FILE_ATTRIBUTE_NORMAL = 0x00000080; 60 | 61 | public static Icon GetFolderIcon(IconSize size, FolderType folderType) 62 | { 63 | uint flags = SHGFI_ICON | SHGFI_USEFILEATTRIBUTES; 64 | 65 | if (FolderType.Open == folderType) flags += SHGFI_OPENICON; 66 | if (IconSize.Small == size) flags += SHGFI_SMALLICON; 67 | else flags += SHGFI_LARGEICON; 68 | 69 | var shfi = new SHFILEINFO(); 70 | var res = SHGetFileInfo("AnyNonEmptyStringWillDo", FILE_ATTRIBUTE_DIRECTORY, out shfi, (uint)Marshal.SizeOf(shfi), flags); 71 | 72 | if (res == IntPtr.Zero) throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()); 73 | 74 | Icon.FromHandle(shfi.hIcon); 75 | var icon = (Icon)Icon.FromHandle(shfi.hIcon).Clone(); 76 | 77 | DestroyIcon(shfi.hIcon); 78 | 79 | return icon; 80 | } 81 | 82 | public static Icon GetFileIcon(IconSize size, string ext) 83 | { 84 | uint flags = SHGFI_ICON | SHGFI_USEFILEATTRIBUTES; 85 | 86 | string fn = "*." + ext; 87 | 88 | if (size == IconSize.Large) flags += SHGFI_LARGEICON; 89 | else flags += SHGFI_SMALLICON; 90 | 91 | var shfi = new SHFILEINFO(); 92 | var res = SHGetFileInfo(fn, FILE_ATTRIBUTE_NORMAL, out shfi, (uint)Marshal.SizeOf(shfi), flags); 93 | 94 | if (res == IntPtr.Zero) throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()); 95 | 96 | Icon.FromHandle(shfi.hIcon); 97 | var icon = (Icon)Icon.FromHandle(shfi.hIcon).Clone(); 98 | 99 | DestroyIcon(shfi.hIcon); 100 | 101 | return icon; 102 | } 103 | 104 | [DllImport("Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 105 | private static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons); 106 | 107 | public static Icon GetDllIcon(string file, int number, IconSize size) 108 | { 109 | IntPtr large; 110 | IntPtr small; 111 | ExtractIconEx(file, number, out large, out small, 1); 112 | try 113 | { 114 | return Icon.FromHandle(size == IconSize.Large ? large : small); 115 | } 116 | catch 117 | { 118 | return null; 119 | } 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /N3DSCmbViewer/ZSI/Actor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace N3DSCmbViewer.ZSI 7 | { 8 | public class Actor 9 | { 10 | public int Offset { get; private set; } 11 | 12 | /* The usual approximation */ 13 | public ushort Number { get; private set; } 14 | public short PositionX { get; private set; } 15 | public short PositionY { get; private set; } 16 | public short PositionZ { get; private set; } 17 | public short RotationX { get; private set; } 18 | public short RotationY { get; private set; } 19 | public short RotationZ { get; private set; } 20 | public ushort Variable { get; private set; } 21 | 22 | public Actor(byte[] data, int offset) 23 | { 24 | Offset = offset; 25 | 26 | Number = BitConverter.ToUInt16(data, offset); 27 | PositionX = BitConverter.ToInt16(data, offset + 2); 28 | PositionY = BitConverter.ToInt16(data, offset + 4); 29 | PositionZ = BitConverter.ToInt16(data, offset + 6); 30 | RotationX = BitConverter.ToInt16(data, offset + 8); 31 | RotationY = BitConverter.ToInt16(data, offset + 10); 32 | RotationZ = BitConverter.ToInt16(data, offset + 12); 33 | Variable = BitConverter.ToUInt16(data, offset + 14); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /N3DSCmbViewer/ZSI/Setup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using OpenTK; 7 | using OpenTK.Graphics; 8 | using OpenTK.Graphics.OpenGL; 9 | 10 | using N3DSCmbViewer.Cmb; 11 | 12 | namespace N3DSCmbViewer.ZSI 13 | { 14 | class Setup 15 | { 16 | public int Offset { get; private set; } 17 | 18 | public List Actors { get; private set; } 19 | public Actor SelectedActor { get; set; } 20 | 21 | public ModelHandler Model { get; private set; } 22 | 23 | public Setup(byte[] data, int offset) 24 | { 25 | Offset = offset; 26 | 27 | Actors = new List(); 28 | SelectedActor = null; 29 | 30 | Model = null; 31 | 32 | ulong command = ulong.MaxValue; 33 | while (command != ZSIHandler.EndHeaderCommand) 34 | { 35 | command = BitConverter.ToUInt64(data, offset).Reverse(); 36 | switch ((byte)(command >> 56)) 37 | { 38 | case 0x01: 39 | /* Room actors */ 40 | byte actorCount = (byte)(command >> 48); 41 | uint actorOffset = (((uint)(command & 0xFFFFFFFF)).Reverse() + ZSIHandler.CommandsOffset); 42 | for (int i = 0; i < actorCount; i++) 43 | { 44 | Actors.Add(new Actor(data, (int)(actorOffset + i * 0x10))); 45 | } 46 | break; 47 | 48 | case 0x0A: 49 | /* Mesh header (aka ".cmb reference" in this hack of OoT64's format that Grezzo did?) */ 50 | /* That said, implementation here is hacky & incomplete too! */ 51 | uint meshHeaderOffset = (((uint)(command & 0xFFFFFFFF)).Reverse() + ZSIHandler.CommandsOffset); 52 | byte meshType = data[meshHeaderOffset]; 53 | byte meshCount = data[meshHeaderOffset + 1]; 54 | 55 | if (meshCount == 0) break; 56 | 57 | uint meshEntryStart = BitConverter.ToUInt32(data, (int)(meshHeaderOffset + 4)) + ZSIHandler.CommandsOffset; 58 | uint meshEntryEnd = BitConverter.ToUInt32(data, (int)(meshHeaderOffset + 8)) + ZSIHandler.CommandsOffset; 59 | 60 | if (meshType != 2 && meshCount != 1) throw new Exception("Unhandled mesh type OR mesh count! (Not 0x02, 0x01)"); 61 | 62 | uint modelOffset1 = BitConverter.ToUInt32(data, (int)(meshEntryStart + 8)); 63 | uint modelOffset2 = BitConverter.ToUInt32(data, (int)(meshEntryStart + 12)); 64 | 65 | if (modelOffset1 != 0 && modelOffset2 != 0) throw new Exception("Unhandled model offsets! (Both are non-zero)"); 66 | 67 | uint modelOffset = (modelOffset1 != 0 ? modelOffset1 : modelOffset2) + ZSIHandler.CommandsOffset; 68 | 69 | Model = new ModelHandler(data, (int)modelOffset, (int)(data.Length - modelOffset)); 70 | break; 71 | } 72 | offset += 8; 73 | } 74 | } 75 | 76 | public void RenderActors() 77 | { 78 | // TODO also get rid of immediate mode here, it's just easier to do it this way for now... 79 | GL.PushAttrib(AttribMask.AllAttribBits); 80 | GL.Disable(EnableCap.DepthTest); 81 | GL.Disable(EnableCap.Lighting); 82 | GL.PointSize(15.0f); 83 | GL.UseProgram(0); 84 | GL.Begin(PrimitiveType.Points); 85 | foreach (Actor actor in Actors) 86 | { 87 | if (SelectedActor != null && actor == SelectedActor) 88 | GL.Color4(Color4.Yellow); 89 | else 90 | GL.Color4(Color4.GreenYellow); 91 | 92 | GL.Vertex3(actor.PositionX, actor.PositionY, actor.PositionZ); 93 | } 94 | GL.End(); 95 | GL.PopAttrib(); 96 | // END TODO 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /N3DSCmbViewer/ZSI/ZSIHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.IO; 6 | 7 | using N3DSCmbViewer.Cmb; 8 | 9 | namespace N3DSCmbViewer.ZSI 10 | { 11 | [System.Diagnostics.DebuggerDisplay("{GetType()}")] 12 | class ZSIHandler : IDisposable 13 | { 14 | public bool Disposed { get; private set; } 15 | 16 | public const string FileTag_OoT = "ZSI\x01"; 17 | public const string FileTag_MM = "ZSI\x09"; 18 | public const uint CommandsOffset = 0x10; 19 | public const ulong AlternateSetupsCommand = 0x1800000000000000; 20 | public const ulong EndHeaderCommand = 0x1400000000000000; 21 | 22 | public string Tag { get; private set; } 23 | public string CodenameString { get; private set; } 24 | 25 | public string Filename { get; set; } 26 | public byte[] Data { get; private set; } 27 | 28 | public List Setups { get; private set; } 29 | public Setup SelectedSetup { get; set; } 30 | 31 | public ZSIHandler(string filename) 32 | { 33 | Filename = filename; 34 | BinaryReader reader = new BinaryReader(File.Open(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)); 35 | Data = new byte[reader.BaseStream.Length]; 36 | reader.Read(Data, 0, Data.Length); 37 | reader.Close(); 38 | 39 | Load(); 40 | } 41 | 42 | public ZSIHandler(byte[] data, int offset, int length) 43 | { 44 | Filename = string.Empty; 45 | Data = new byte[length]; 46 | Buffer.BlockCopy(data, offset, Data, 0, Data.Length); 47 | 48 | Load(); 49 | } 50 | 51 | ~ZSIHandler() 52 | { 53 | Dispose(false); 54 | } 55 | 56 | public void Dispose() 57 | { 58 | Dispose(true); 59 | GC.SuppressFinalize(this); 60 | } 61 | 62 | protected virtual void Dispose(bool disposing) 63 | { 64 | if (!Disposed) 65 | { 66 | if (disposing) 67 | { 68 | foreach (Setup setup in Setups) 69 | { 70 | if (setup.Model != null) 71 | setup.Model.Dispose(); 72 | } 73 | } 74 | 75 | Disposed = true; 76 | } 77 | } 78 | 79 | public void Load() 80 | { 81 | Disposed = false; 82 | 83 | Tag = Encoding.ASCII.GetString(Data, 0, 4); 84 | if (Tag != FileTag_OoT && Tag != FileTag_MM) 85 | throw new Exception(string.Format("Trying to read chunk with tag '{0}' as {1}, expected tag '{2}' OR '{3}'", Tag, this.GetType().Name, FileTag_OoT, FileTag_MM)); 86 | 87 | CodenameString = Encoding.ASCII.GetString(Data, 4, 12).TrimEnd('\0'); 88 | 89 | Setups = new List(); 90 | 91 | ulong firstCommand = BitConverter.ToUInt64(Data, (int)CommandsOffset).Reverse(); 92 | if ((firstCommand & 0xFF00FFFF00000000) == AlternateSetupsCommand) 93 | { 94 | Setups.Add(new Setup(Data, (int)(CommandsOffset + 0x08))); 95 | 96 | int setupListOffset = (int)(((uint)(firstCommand & 0xFFFFFFFF)).Reverse() + CommandsOffset); 97 | for (int i = 0; i < (int)((firstCommand >> 48) & 0xFF); i++) 98 | { 99 | int setupOffset = (int)(BitConverter.ToUInt32(Data, setupListOffset + i * 0x04) + CommandsOffset); 100 | if (setupOffset != CommandsOffset) Setups.Add(new Setup(Data, setupOffset)); 101 | } 102 | } 103 | else 104 | Setups.Add(new Setup(Data, (int)CommandsOffset)); 105 | 106 | SelectedSetup = Setups.FirstOrDefault(); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /N3DSCmbViewer/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | False 16 | 17 | 18 | True 19 | 20 | 21 | True 22 | 23 | 24 | True 25 | 26 | 27 | False 28 | 29 | 30 | False 31 | 32 | 33 | False 34 | 35 | 36 | False 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | False 45 | 46 | 47 | True 48 | 49 | 50 | True 51 | 52 | 53 | True 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /N3DSCmbViewer/general-fs.glsl: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | /* General */ 4 | varying vec4 vertexPosition; 5 | 6 | /* For lighting calculations */ 7 | varying vec4 diffuse, ambient; 8 | varying vec3 normal, halfVector; 9 | 10 | /* Texture sampler */ 11 | uniform sampler2D tex0; 12 | uniform sampler2D tex1; 13 | uniform sampler2D tex2; 14 | 15 | /* Data from cmb */ 16 | uniform vec4 materialColor; 17 | 18 | /* Settings */ 19 | uniform bool disableAlpha; 20 | uniform bool enableLighting; 21 | 22 | void main() 23 | { 24 | vec4 color = vec4(1.0, 1.0, 1.0, 1.0); 25 | vec3 n = normalize(normal); 26 | vec3 lightDir = vec3(gl_LightSource[0].position.xyz); 27 | 28 | /* Lighting */ 29 | if(enableLighting) 30 | { 31 | vec3 halfV; 32 | float NdotL, NdotHV; 33 | 34 | color = ambient; 35 | NdotL = max(dot(n, lightDir), 0.0); 36 | if (NdotL > 0.0) 37 | { 38 | color += diffuse * NdotL; 39 | halfV = normalize(halfVector); 40 | NdotHV = max(dot(n, halfV), 0.0); 41 | color += gl_FrontMaterial.specular * gl_LightSource[0].specular * pow(NdotHV, gl_FrontMaterial.shininess); 42 | } 43 | } 44 | 45 | /* Texturing */ 46 | vec2 textureCoord0 = vec2(gl_TexCoord[0].s, 1.0 - gl_TexCoord[0].t); 47 | vec4 textureColor0 = texture2D(tex0, textureCoord0); 48 | vec4 textureColor1 = texture2D(tex1, textureCoord0); 49 | vec4 textureColor2 = texture2D(tex2, textureCoord0); 50 | vec4 textureMixed = textureColor0; // * textureColor1; 51 | 52 | /* Finalize */ 53 | gl_FragColor = textureMixed * color * (gl_Color * materialColor); 54 | 55 | if(disableAlpha) 56 | { 57 | gl_FragColor.a = 1.0; 58 | } 59 | 60 | /* HACK: brightness */ 61 | //gl_FragColor *= vec4(2.0, 2.0, 2.0, 1.0); 62 | } 63 | -------------------------------------------------------------------------------- /N3DSCmbViewer/general-vs.glsl: -------------------------------------------------------------------------------- 1 | #version 120 2 | #extension GL_EXT_gpu_shader4 : enable 3 | #extension GL_EXT_geometry_shader4 : enable 4 | 5 | #define MAX_BONE_MATRIX 128 6 | 7 | #define SKINNING_SINGLEBONE 0 8 | #define SKINNING_PERVERTEX 1 9 | #define SKINNING_PERVERTEXNOTRANS 2 10 | 11 | /* General */ 12 | varying vec4 vertexPosition; 13 | 14 | /* For lighting calculations */ 15 | varying vec4 diffuse, ambient; 16 | varying vec3 normal, halfVector; 17 | 18 | /* Data from cmb */ 19 | uniform usamplerBuffer vertBoneSampler; 20 | 21 | uniform mat4 boneMatrix[MAX_BONE_MATRIX]; 22 | uniform int skinningMode; 23 | uniform int boneId; 24 | uniform float vertexScale; 25 | uniform float texCoordScale; 26 | uniform float normalScale; 27 | 28 | /* Settings */ 29 | uniform bool enableLighting; 30 | uniform bool enableSkeletalStuff; 31 | 32 | void main() 33 | { 34 | /* Lighting */ 35 | if(enableLighting) 36 | { 37 | normal = normalize((gl_NormalMatrix * gl_Normal) * normalScale); 38 | halfVector = gl_LightSource[0].halfVector.xyz; 39 | 40 | diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse; 41 | ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient; 42 | ambient += gl_LightModel.ambient * gl_FrontMaterial.ambient; 43 | } 44 | 45 | /* Bone workings */ 46 | mat4 tempMatrix = mat4(1.0); 47 | 48 | /* ...I have no idea ... */ 49 | if(enableSkeletalStuff) 50 | { 51 | uint lookupId = uint(texelFetchBuffer(vertBoneSampler, gl_VertexID).r); 52 | 53 | if(skinningMode == SKINNING_SINGLEBONE) 54 | { 55 | /* Single bone */ 56 | tempMatrix = boneMatrix[boneId]; 57 | } 58 | else if(skinningMode == SKINNING_PERVERTEX) 59 | { 60 | /* Per vertex */ 61 | tempMatrix = boneMatrix[lookupId]; 62 | } 63 | else if(skinningMode == SKINNING_PERVERTEXNOTRANS) 64 | { 65 | /* Per vertex, no translation */ 66 | tempMatrix = boneMatrix[lookupId]; 67 | tempMatrix[0][3] = 0.0; 68 | tempMatrix[1][3] = 0.0; 69 | tempMatrix[2][3] = 0.0; 70 | } 71 | } 72 | 73 | /* Vertex positioning */ 74 | vec4 vertex = vec4(gl_ModelViewMatrix * (tempMatrix * (vec4(gl_Vertex.xyz, 1.0) * vertexScale))); 75 | vertexPosition = gl_ProjectionMatrix * vertex; 76 | 77 | /* Finalize */ 78 | gl_Position = vertexPosition; 79 | gl_TexCoord[0] = gl_MultiTexCoord0 * texCoordScale; 80 | 81 | /* TEST: gl_VertexID support */ 82 | //float test = float(gl_VertexID) / 255.0; 83 | //gl_Color = vec4(test, 0.0, 0.0, 1.0); 84 | 85 | gl_FrontColor = gl_Color; 86 | } 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | N3DSCmbViewer 2 | ============= 3 | 4 | An unfinished model viewer for The Legend of Zelda: Ocarina of Time 3D and Majora's Mask 3D, written in C#. 5 | 6 | Screenshots 7 | =========== 8 | 9 | ![N3DSCmbViewer](http://i.imgur.com/uyXvgSI.png) 10 | ![N3DSCmbViewer](http://i.imgur.com/A0fSt2h.png) 11 | 12 | Warning 13 | ======= 14 | 15 | __This is unfinished, experimental code.__ You _will_ encounter glitches, broken functionality, etc., etc. Do not _expect_ anything related to OoT3D/MM3D (models, animation, archives, etc.) to work and be happy if something _does_. There should, however, _not_ be any problems just running the application. 16 | 17 | Also note that this repository supersedes [the old source code archive](http://magicstone.de/dzd/random/3ds/N3DSCmbViewer-bin-src.rar) posted in 2014, before this repository existed. 18 | 19 | Acknowledgements 20 | ================ 21 | 22 | * ZAR archive format reverse-engineered and documented by Twili 23 | * Various additional research by Twili 24 | * COLLADA exporter written with a lot of help from Peardian 25 | * LZSS decompression code adapted from [C++ code by ShimmerFairy](https://github.com/ShimmerFairy/MM3D/) 26 | --------------------------------------------------------------------------------