├── .gitignore ├── License ├── Readme.md ├── TConvert.sln └── TConvert ├── App.config ├── App.ico ├── App.xaml ├── App.xaml.cs ├── CommandLine.cs ├── Config.cs ├── Convert ├── PngConverter.cs ├── WavConverter.cs └── XCompress.cs ├── ErrorLogger.cs ├── Extract ├── ADPCMConverter.cs ├── DtxUtil.cs ├── Ffmpeg.cs ├── HuffTable.cs ├── LzxBuffer.cs ├── LzxDecoder.cs ├── XactExtractor.cs └── XnbExtractor.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Processing.cs ├── Properties ├── AssemblyInfo.cs ├── Resources.Designer.cs ├── Resources.resx ├── Settings.Designer.cs └── Settings.settings ├── Resources ├── Icons │ ├── About.png │ ├── AppError.ico │ ├── AutoClose.png │ ├── Browse.png │ ├── CloseCmdProgress.png │ ├── CloseDropProgress.png │ ├── CloseProgress.png │ ├── Compression.png │ ├── Credits.png │ ├── Empty.png │ ├── ErrorIcon.png │ ├── Exit.png │ ├── Github.png │ ├── Help.png │ ├── InfoIcon.png │ ├── Premultiply.png │ ├── QuestionIcon.png │ ├── Sound.png │ ├── TerrariaIcon.png │ └── WarningIcon.png ├── Logo112.png ├── ffmpeg.exe └── xcompress32.dll ├── Startup.cs ├── TConvert.csproj ├── Util ├── EmbeddedResources.cs ├── Helpers.cs ├── TerrariaLocator.cs └── Xnb.cs └── Windows ├── AboutWindow.xaml ├── AboutWindow.xaml.cs ├── CreditsWindow.xaml ├── CreditsWindow.xaml.cs ├── ErrorLogWindow.xaml ├── ErrorLogWindow.xaml.cs ├── ErrorMessageBox.xaml ├── ErrorMessageBox.xaml.cs ├── FlashWindow.cs ├── FolderBrowserLauncher.cs ├── ProgressWindow.xaml ├── ProgressWindow.xaml.cs ├── TriggerMessageBox.xaml └── TriggerMessageBox.xaml.cs /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # .NET Core 46 | project.lock.json 47 | project.fragment.lock.json 48 | artifacts/ 49 | **/Properties/launchSettings.json 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # Visual Studio code coverage results 117 | *.coverage 118 | *.coveragexml 119 | 120 | # NCrunch 121 | _NCrunch_* 122 | .*crunch*.local.xml 123 | nCrunchTemp_* 124 | 125 | # MightyMoose 126 | *.mm.* 127 | AutoTest.Net/ 128 | 129 | # Web workbench (sass) 130 | .sass-cache/ 131 | 132 | # Installshield output folder 133 | [Ee]xpress/ 134 | 135 | # DocProject is a documentation generator add-in 136 | DocProject/buildhelp/ 137 | DocProject/Help/*.HxT 138 | DocProject/Help/*.HxC 139 | DocProject/Help/*.hhc 140 | DocProject/Help/*.hhk 141 | DocProject/Help/*.hhp 142 | DocProject/Help/Html2 143 | DocProject/Help/html 144 | 145 | # Click-Once directory 146 | publish/ 147 | 148 | # Publish Web Output 149 | *.[Pp]ublish.xml 150 | *.azurePubxml 151 | # TODO: Comment the next line if you want to checkin your web deploy settings 152 | # but database connection strings (with potential passwords) will be unencrypted 153 | *.pubxml 154 | *.publishproj 155 | 156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 157 | # checkin your Azure Web App publish settings, but sensitive information contained 158 | # in these scripts will be unencrypted 159 | PublishScripts/ 160 | 161 | # NuGet Packages 162 | *.nupkg 163 | # The packages folder can be ignored because of Package Restore 164 | **/packages/* 165 | # except build/, which is used as an MSBuild target. 166 | !**/packages/build/ 167 | # Uncomment if necessary however generally it will be regenerated when needed 168 | #!**/packages/repositories.config 169 | # NuGet v3's project.json files produces more ignorable files 170 | *.nuget.props 171 | *.nuget.targets 172 | 173 | # Microsoft Azure Build Output 174 | csx/ 175 | *.build.csdef 176 | 177 | # Microsoft Azure Emulator 178 | ecf/ 179 | rcf/ 180 | 181 | # Windows Store app package directories and files 182 | AppPackages/ 183 | BundleArtifacts/ 184 | Package.StoreAssociation.xml 185 | _pkginfo.txt 186 | 187 | # Visual Studio cache files 188 | # files ending in .cache can be ignored 189 | *.[Cc]ache 190 | # but keep track of directories ending in .cache 191 | !*.[Cc]ache/ 192 | 193 | # Others 194 | ClientBin/ 195 | ~$* 196 | *~ 197 | *.dbmdl 198 | *.dbproj.schemaview 199 | *.jfm 200 | *.pfx 201 | *.publishsettings 202 | orleans.codegen.cs 203 | 204 | # Since there are multiple workflows, uncomment next line to ignore bower_components 205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 206 | #bower_components/ 207 | 208 | # RIA/Silverlight projects 209 | Generated_Code/ 210 | 211 | # Backup & report files from converting an old project file 212 | # to a newer Visual Studio version. Backup files are not needed, 213 | # because we have git ;-) 214 | _UpgradeReport_Files/ 215 | Backup*/ 216 | UpgradeLog*.XML 217 | UpgradeLog*.htm 218 | 219 | # SQL Server files 220 | *.mdf 221 | *.ldf 222 | *.ndf 223 | 224 | # Business Intelligence projects 225 | *.rdl.data 226 | *.bim.layout 227 | *.bim_*.settings 228 | 229 | # Microsoft Fakes 230 | FakesAssemblies/ 231 | 232 | # GhostDoc plugin setting file 233 | *.GhostDoc.xml 234 | 235 | # Node.js Tools for Visual Studio 236 | .ntvs_analysis.dat 237 | node_modules/ 238 | 239 | # Typescript v1 declaration files 240 | typings/ 241 | 242 | # Visual Studio 6 build log 243 | *.plg 244 | 245 | # Visual Studio 6 workspace options file 246 | *.opt 247 | 248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 249 | *.vbw 250 | 251 | # Visual Studio LightSwitch build output 252 | **/*.HTMLClient/GeneratedArtifacts 253 | **/*.DesktopClient/GeneratedArtifacts 254 | **/*.DesktopClient/ModelManifest.xml 255 | **/*.Server/GeneratedArtifacts 256 | **/*.Server/ModelManifest.xml 257 | _Pvt_Extensions 258 | 259 | # Paket dependency manager 260 | .paket/paket.exe 261 | paket-files/ 262 | 263 | # FAKE - F# Make 264 | .fake/ 265 | 266 | # JetBrains Rider 267 | .idea/ 268 | *.sln.iml 269 | 270 | # CodeRush 271 | .cr/ 272 | 273 | # Python Tools for Visual Studio (PTVS) 274 | __pycache__/ 275 | *.pyc 276 | 277 | # Cake - Uncomment if you are using it 278 | # tools/** 279 | # !tools/packages.config 280 | 281 | # Telerik's JustMock configuration file 282 | *.jmconfig 283 | 284 | # BizTalk build output 285 | *.btp.cs 286 | *.btm.cs 287 | *.odx.cs 288 | *.xsd.cs 289 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # TConvert ![AppIcon](http://i.imgur.com/5WPwZ3W.png) 2 | 3 | [![Latest Release](https://img.shields.io/github/release/trigger-death/TConvert.svg?style=flat&label=version)](https://github.com/trigger-death/TConvert/releases/latest) 4 | [![Latest Release Date](https://img.shields.io/github/release-date-pre/trigger-death/TConvert.svg?style=flat&label=released)](https://github.com/trigger-death/TConvert/releases/latest) 5 | [![Total Downloads](https://img.shields.io/github/downloads/trigger-death/TConvert/total.svg?style=flat)](https://github.com/trigger-death/TConvert/releases) 6 | [![Creation Date](https://img.shields.io/badge/created-august%202017-A642FF.svg?style=flat)](https://github.com/trigger-death/TConvert/commit/81d10e01975c1974f73ee90089fa30d85e71370e) 7 | [![Terraria Forums](https://img.shields.io/badge/terraria-forums-28A828.svg?style=flat)](https://forums.terraria.org/index.php?threads/61706/) 8 | [![Discord](https://img.shields.io/discord/436949335947870238.svg?style=flat&logo=discord&label=chat&colorB=7389DC&link=https://discord.gg/vB7jUbY)](https://discord.gg/vB7jUbY) 9 | 10 | A combination tool for managing Terraria content resources. Convert, extract, backup, and restore. The unofficial sequel to TExtract. 11 | 12 | ![Window Preview](https://i.imgur.com/oTuVrGQ.png) 13 | 14 | ### [Wiki](https://github.com/trigger-death/TConvert/wiki) | [Credits](https://github.com/trigger-death/TConvert/wiki/Credits) | [Image Album](https://imgur.com/a/QaoPd) 15 | 16 | ### [![Get TConvert](http://i.imgur.com/4BGRFF0.png)](https://github.com/trigger-death/TConvert/releases/latest) 17 | 18 | ## About 19 | 20 | * **Created By:** Robert Jordan 21 | * **Version:** 1.0.2.1 22 | * **Language:** C#, WPF 23 | 24 | ## Requirements for Running 25 | * .NET Framework 4.5.2 | [Offline Installer](https://www.microsoft.com/en-us/download/details.aspx?id=42642) | [Web Installer](https://www.microsoft.com/en-us/download/details.aspx?id=42643) 26 | * Windows 7 or later 27 | 28 | ## Building from Source 29 | * Build with configuration *WinDebug* or *WinRelease* for the UI version. 30 | * Build with configuration *ConDebug* or *ConRelease* for the pure console version. 31 | 32 | ## Features 33 | * Extract image, sound, and font resources from Terraria's Xnb files, and extract songs from Terraria's Xwb wave bank. 34 | * Convert images and sounds back into Xnb format and copy them to the content directory. 35 | * Backup and restore your content folder for when you need to remove changes. (Glorified file copier) 36 | * Run scripts that give more control over where files go when they are converted or extracted. 37 | * Drop files into the window to automatically process them. 38 | * Command line support for use with Windows Shell or the command prompt. 39 | 40 | ## About Xnb Format 41 | 42 | Everything I learned about the Xnb format in order to read sprite fonts was gotten from the [documentation available on this page](http://xbox.create.msdn.com/en-us/sample/xnb_format). [Here's a mirror](http://www.mediafire.com/file/pf5dqw5dmup1msa/XNA_XNB_Format.zip) if that link ever goes down like old Microsoft links usually do. 43 | -------------------------------------------------------------------------------- /TConvert.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TConvert", "TConvert\TConvert.csproj", "{A0490315-2780-4572-BBA1-F56A7C2A5901}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | ConDebug|Any CPU = ConDebug|Any CPU 11 | ConRelease|Any CPU = ConRelease|Any CPU 12 | WinDebug|Any CPU = WinDebug|Any CPU 13 | WinRelease|Any CPU = WinRelease|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {A0490315-2780-4572-BBA1-F56A7C2A5901}.ConDebug|Any CPU.ActiveCfg = ConDebug|Any CPU 17 | {A0490315-2780-4572-BBA1-F56A7C2A5901}.ConDebug|Any CPU.Build.0 = ConDebug|Any CPU 18 | {A0490315-2780-4572-BBA1-F56A7C2A5901}.ConRelease|Any CPU.ActiveCfg = ConRelease|Any CPU 19 | {A0490315-2780-4572-BBA1-F56A7C2A5901}.ConRelease|Any CPU.Build.0 = ConRelease|Any CPU 20 | {A0490315-2780-4572-BBA1-F56A7C2A5901}.WinDebug|Any CPU.ActiveCfg = WinDebug|Any CPU 21 | {A0490315-2780-4572-BBA1-F56A7C2A5901}.WinDebug|Any CPU.Build.0 = WinDebug|Any CPU 22 | {A0490315-2780-4572-BBA1-F56A7C2A5901}.WinRelease|Any CPU.ActiveCfg = WinRelease|Any CPU 23 | {A0490315-2780-4572-BBA1-F56A7C2A5901}.WinRelease|Any CPU.Build.0 = WinRelease|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /TConvert/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | True 61 | 62 | 63 | True 64 | 65 | 66 | True 67 | 68 | 69 | False 70 | 71 | 72 | True 73 | 74 | 75 | True 76 | 77 | 78 | False 79 | 80 | 81 | Extract 82 | 83 | 84 | False 85 | 86 | 87 | True 88 | 89 | 90 | True 91 | 92 | 93 | True 94 | 95 | 96 | False 97 | 98 | 99 | True 100 | 101 | 102 | True 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /TConvert/App.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/App.ico -------------------------------------------------------------------------------- /TConvert/App.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TConvert/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Globalization; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | using System.Windows; 12 | using System.Windows.Threading; 13 | using TConvert.Extract; 14 | using TConvert.Windows; 15 | 16 | namespace TConvert { 17 | /**The application class.*/ 18 | public partial class App : Application { 19 | //=========== MEMBERS ============ 20 | #region Members 21 | 22 | /**The last exception. Used to prevent multiple error windows for the same error.*/ 23 | private static object lastException = null; 24 | 25 | #endregion 26 | //========= CONSTRUCTORS ========= 27 | #region Constructors 28 | 29 | /**Constructs the app and sets up embedded assembly resolving.*/ 30 | public App() { 31 | AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssemblies; 32 | } 33 | 34 | #endregion 35 | //============ EVENTS ============ 36 | #region Events 37 | 38 | private Assembly OnResolveAssemblies(object sender, ResolveEventArgs args) { 39 | var executingAssembly = Assembly.GetExecutingAssembly(); 40 | var assemblyName = new AssemblyName(args.Name); 41 | 42 | string path = assemblyName.Name + ".dll"; 43 | if (assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false) { 44 | path = string.Format(@"{0}\{1}", assemblyName.CultureInfo, path); 45 | } 46 | 47 | using (Stream stream = executingAssembly.GetManifestResourceStream(path)) { 48 | if (stream == null) 49 | return null; 50 | 51 | byte[] assemblyRawBytes = new byte[stream.Length]; 52 | stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length); 53 | return Assembly.Load(assemblyRawBytes); 54 | } 55 | } 56 | private void OnAppStartup(object sender, StartupEventArgs e) { 57 | // Catch exceptions not in a UI thread 58 | AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnAppDomainUnhandledException); 59 | TaskScheduler.UnobservedTaskException += OnTaskSchedulerUnobservedTaskException; 60 | if (e.Args.Length > 0) { 61 | // Only reach here from CommandLine starting up the app to use the progress window. 62 | CommandLine.ProcessFiles(); 63 | } 64 | } 65 | private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { 66 | if (e.Exception != lastException) { 67 | lastException = e.Exception; 68 | if (ErrorMessageBox.Show(e.Exception)) 69 | Environment.Exit(0); 70 | e.Handled = true; 71 | } 72 | } 73 | private void OnAppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e) { 74 | if (e.ExceptionObject != lastException) { 75 | lastException = e.ExceptionObject; 76 | Dispatcher.Invoke(() => { 77 | if (ErrorMessageBox.Show(e.ExceptionObject)) 78 | Environment.Exit(0); 79 | }); 80 | } 81 | } 82 | private void OnTaskSchedulerUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) { 83 | if (e.Exception != lastException) { 84 | lastException = e.Exception; 85 | Dispatcher.Invoke(() => { 86 | if (ErrorMessageBox.Show(e.Exception)) 87 | Environment.Exit(0); 88 | }); 89 | } 90 | } 91 | 92 | #endregion 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /TConvert/Config.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using TConvert.Convert; 7 | using TConvert.Properties; 8 | using TConvert.Util; 9 | 10 | namespace TConvert { 11 | /**The types of input modes for convert or extract.*/ 12 | public enum InputModes { 13 | Folder = 0, 14 | File = 1 15 | } 16 | /**The tabs to be switched to and from.*/ 17 | public enum Tabs { 18 | Extract = 0, 19 | Convert = 1, 20 | Backup = 2, 21 | Script = 3 22 | } 23 | /**The config settings handler.*/ 24 | public static class Config { 25 | //=========== MEMBERS ============ 26 | #region Members 27 | 28 | /**The specified Terraria Content folder.*/ 29 | public static string TerrariaContentDirectory { get; set; } 30 | /**The current tab.*/ 31 | public static Tabs CurrentTab { get; set; } 32 | /**True if normal progress windows are auto-closed.*/ 33 | public static bool AutoCloseProgress { get; set; } 34 | /**True if file drop progress windows are auto-closed.*/ 35 | public static bool AutoCloseDropProgress { get; set; } 36 | /**True if command line progress windows are auto-closed.*/ 37 | public static bool AutoCloseCmdProgress { get; set; } 38 | /**True if images are compressed.*/ 39 | public static bool CompressImages { get; set; } 40 | /**True if a sound is played on completion.*/ 41 | public static bool CompletionSound { get; set; } 42 | /**True if alpha is premultiplied by default when converting to xnb.*/ 43 | public static bool PremultiplyAlpha { get; set; } 44 | 45 | #endregion 46 | //=========== CLASSES ============ 47 | #region Classes 48 | 49 | /**A container for extract settings.*/ 50 | public static class Extract { 51 | /**File or Folder mode.*/ 52 | public static InputModes Mode; 53 | /**The input for folder mode.*/ 54 | public static string FolderInput { get; set; } 55 | /**The output for folder mode.*/ 56 | public static string FolderOutput { get; set; } 57 | /**The input for file mode.*/ 58 | public static string FileInput { get; set; } 59 | /**The output for file mode.*/ 60 | public static string FileOutput { get; set; } 61 | /**True if images are extracted.*/ 62 | public static bool AllowImages { get; set; } 63 | /**True if sounds are extracted.*/ 64 | public static bool AllowSounds { get; set; } 65 | /**True if fonts are extracted.*/ 66 | public static bool AllowFonts { get; set; } 67 | /**True if wave banks are extracted.*/ 68 | public static bool AllowWaveBank { get; set; } 69 | /**True if the output path is the input path.*/ 70 | public static bool UseInput { get; set; } 71 | /**Gets the current input path.*/ 72 | public static string CurrentInput { 73 | get { 74 | switch (Mode) { 75 | case InputModes.Folder: return FolderInput; 76 | case InputModes.File: return FileInput; 77 | } 78 | return ""; 79 | } 80 | set { 81 | switch (Mode) { 82 | case InputModes.Folder: FolderInput = value; break; 83 | case InputModes.File: FileInput = value; break; 84 | } 85 | } 86 | } 87 | /**Gets the current output path.*/ 88 | public static string CurrentOutput { 89 | get { 90 | switch (Mode) { 91 | case InputModes.Folder: return FolderOutput; 92 | case InputModes.File: return FileOutput; 93 | } 94 | return ""; 95 | } 96 | set { 97 | switch (Mode) { 98 | case InputModes.Folder: FolderOutput = value; break; 99 | case InputModes.File: FileOutput = value; break; 100 | } 101 | } 102 | } 103 | } 104 | /**A container for convert settings.*/ 105 | public static class Convert { 106 | /**File or Folder mode.*/ 107 | public static InputModes Mode { get; set; } 108 | /**The input for folder mode.*/ 109 | public static string FolderInput { get; set; } 110 | /**The output for folder mode.*/ 111 | public static string FolderOutput { get; set; } 112 | /**The input for file mode.*/ 113 | public static string FileInput { get; set; } 114 | /**The output for file mode.*/ 115 | public static string FileOutput { get; set; } 116 | /**True if images are converted.*/ 117 | public static bool AllowImages { get; set; } 118 | /**True if sounds are converted.*/ 119 | public static bool AllowSounds { get; set; } 120 | /**True if the output path is the input path.*/ 121 | public static bool UseInput { get; set; } 122 | /**Gets the current input path.*/ 123 | public static string CurrentInput { 124 | get { 125 | switch (Mode) { 126 | case InputModes.Folder: return FolderInput; 127 | case InputModes.File: return FileInput; 128 | } 129 | return ""; 130 | } 131 | set { 132 | switch (Mode) { 133 | case InputModes.Folder: FolderInput = value; break; 134 | case InputModes.File: FileInput = value; break; 135 | } 136 | } 137 | } 138 | /**Gets the current output path.*/ 139 | public static string CurrentOutput { 140 | get { 141 | switch (Mode) { 142 | case InputModes.Folder: return FolderOutput; 143 | case InputModes.File: return FileOutput; 144 | } 145 | return ""; 146 | } 147 | set { 148 | switch (Mode) { 149 | case InputModes.Folder: FolderOutput = value; break; 150 | case InputModes.File: FileOutput = value; break; 151 | } 152 | } 153 | } 154 | } 155 | /**A container for backup settings.*/ 156 | public static class Backup { 157 | /**The last selected content folder.*/ 158 | public static string FolderContent { get; set; } 159 | /**The last selected backup folder.*/ 160 | public static string FolderBackup { get; set; } 161 | } 162 | /**A container for script settings.*/ 163 | public static class Script { 164 | /**The last selected script file.*/ 165 | public static string File { get; set; } 166 | } 167 | 168 | #endregion 169 | //=========== LOADING ============ 170 | #region Loading 171 | 172 | /**Loads the settings.*/ 173 | public static void Load() { 174 | TerrariaContentDirectory = Settings.Default.TerrariaContentDirectory; 175 | if (TerrariaContentDirectory == "" && !string.IsNullOrEmpty(TerrariaLocator.TerrariaContentDirectory)) { 176 | TerrariaContentDirectory = TerrariaLocator.TerrariaContentDirectory; 177 | } 178 | Tabs tab; 179 | Enum.TryParse(Settings.Default.CurrentTab, out tab); 180 | CurrentTab = tab; 181 | AutoCloseProgress = Settings.Default.AutoCloseProgress; 182 | AutoCloseDropProgress = Settings.Default.AutoCloseDropProgress; 183 | AutoCloseCmdProgress = Settings.Default.AutoCloseCmdProgress; 184 | CompressImages = Settings.Default.CompressImages && XCompress.IsAvailable; 185 | CompletionSound = Settings.Default.CompletionSound; 186 | PremultiplyAlpha = Settings.Default.PremultiplyAlpha; 187 | 188 | Extract.FolderInput = Settings.Default.ExtractFolderInput; 189 | Extract.FolderOutput = Settings.Default.ExtractFolderOutput; 190 | Extract.FileInput = Settings.Default.ExtractFileInput; 191 | Extract.FileOutput = Settings.Default.ExtractFileOutput; 192 | 193 | Convert.FolderInput = Settings.Default.ConvertFolderInput; 194 | Convert.FolderOutput = Settings.Default.ConvertFolderOutput; 195 | Convert.FileInput = Settings.Default.ConvertFileInput; 196 | Convert.FileOutput = Settings.Default.ConvertFileOutput; 197 | 198 | Backup.FolderContent = Settings.Default.BackupFolderContent; 199 | Backup.FolderBackup = Settings.Default.BackupFolderBackup; 200 | 201 | Script.File = Settings.Default.ScriptFile; 202 | 203 | InputModes mode; 204 | Enum.TryParse(Settings.Default.ExtractMode, out mode); 205 | Extract.Mode = mode; 206 | 207 | Enum.TryParse(Settings.Default.ConvertMode, out mode); 208 | Convert.Mode = mode; 209 | 210 | Extract.AllowImages = Settings.Default.ExtractAllowImages; 211 | Extract.AllowSounds = Settings.Default.ExtractAllowSounds; 212 | Extract.AllowFonts = Settings.Default.ExtractAllowFonts; 213 | Extract.AllowWaveBank = Settings.Default.ExtractAllowWaveBank; 214 | Extract.UseInput = Settings.Default.ExtractUseInput; 215 | 216 | Convert.AllowImages = Settings.Default.ConvertAllowImages; 217 | Convert.AllowSounds = Settings.Default.ConvertAllowSounds; 218 | Convert.UseInput = Settings.Default.ConvertUseInput; 219 | 220 | } 221 | /**Saves the settings.*/ 222 | public static void Save() { 223 | Settings.Default.TerrariaContentDirectory = TerrariaContentDirectory; 224 | Settings.Default.CurrentTab = CurrentTab.ToString(); 225 | Settings.Default.AutoCloseProgress = AutoCloseProgress; 226 | Settings.Default.AutoCloseDropProgress = AutoCloseDropProgress; 227 | Settings.Default.AutoCloseCmdProgress = AutoCloseCmdProgress; 228 | Settings.Default.CompressImages = CompressImages; 229 | Settings.Default.CompletionSound = CompletionSound; 230 | Settings.Default.PremultiplyAlpha = PremultiplyAlpha; 231 | 232 | Settings.Default.ExtractFolderInput = Extract.FolderInput; 233 | Settings.Default.ExtractFolderOutput = Extract.FolderOutput; 234 | Settings.Default.ExtractFileInput = Extract.FileInput; 235 | Settings.Default.ExtractFileOutput = Extract.FileOutput; 236 | 237 | Settings.Default.ConvertFolderInput = Convert.FolderInput; 238 | Settings.Default.ConvertFolderOutput = Convert.FolderOutput; 239 | Settings.Default.ConvertFileInput = Convert.FileInput; 240 | Settings.Default.ConvertFileOutput = Convert.FileOutput; 241 | 242 | Settings.Default.BackupFolderContent = Backup.FolderContent; 243 | Settings.Default.BackupFolderBackup = Backup.FolderBackup; 244 | 245 | Settings.Default.ScriptFile = Script.File; 246 | 247 | Settings.Default.ExtractMode = Extract.Mode.ToString(); 248 | Settings.Default.ConvertMode = Convert.Mode.ToString(); 249 | 250 | Settings.Default.ExtractAllowImages = Extract.AllowImages; 251 | Settings.Default.ExtractAllowSounds = Extract.AllowSounds; 252 | Settings.Default.ExtractAllowFonts = Extract.AllowFonts; 253 | Settings.Default.ExtractAllowWaveBank = Extract.AllowWaveBank; 254 | Settings.Default.ExtractUseInput = Extract.UseInput; 255 | 256 | Settings.Default.ConvertAllowImages = Convert.AllowImages; 257 | Settings.Default.ConvertAllowSounds = Convert.AllowSounds; 258 | Settings.Default.ConvertUseInput = Convert.UseInput; 259 | 260 | Settings.Default.Save(); 261 | } 262 | 263 | #endregion 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /TConvert/Convert/PngConverter.cs: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (C) 2017 sullerandras 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | ******************************************************************************/ 17 | using System; 18 | using System.Collections.Generic; 19 | using System.Drawing; 20 | using System.Drawing.Imaging; 21 | using System.IO; 22 | using System.Linq; 23 | using System.Runtime.InteropServices; 24 | using System.Text; 25 | using System.Threading.Tasks; 26 | using System.Windows.Media.Imaging; 27 | using TConvert.Util; 28 | 29 | namespace TConvert.Convert { 30 | /**A Png to Xnb Converter.*/ 31 | public class PngConverter { 32 | //========== CONSTANTS =========== 33 | #region Constants 34 | 35 | private const string Texture2DType = 36 | "Microsoft.Xna.Framework.Content.Texture2DReader, " + 37 | "Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, " + 38 | "Culture=neutral, PublicKeyToken=842cf8be1de50553"; 39 | 40 | private const int HeaderSize = 3 + 1 + 1 + 1; 41 | private const int CompressedFileSize = 4; 42 | private const int TypeReaderCountSize = 1; 43 | private static readonly int TypeSize = 2 + Texture2DType.Length + 4; 44 | private const int SharedResourceCountSize = 1; 45 | private const int ObjectHeaderSize = 21; 46 | 47 | private static readonly int MetadataSize = 48 | HeaderSize + CompressedFileSize + TypeReaderCountSize + 49 | TypeSize + SharedResourceCountSize + ObjectHeaderSize; 50 | 51 | #endregion 52 | //========== CONVERTING ========== 53 | #region Converting 54 | 55 | /**Converts the specified input file and writes it to the output file.*/ 56 | public static bool Convert(string inputFile, string outputFile, bool changeExtension, bool compressed, bool reach, bool premultiply) { 57 | if (changeExtension) { 58 | outputFile = Path.ChangeExtension(outputFile, ".xnb"); 59 | } 60 | 61 | // Throw more helpful exceptions than what Bitmap.ctor() throws. 62 | if (!Directory.Exists(Path.GetDirectoryName(inputFile))) 63 | throw new DirectoryNotFoundException("Could not find a part of the path '" + inputFile + "'."); 64 | else if (!File.Exists(inputFile)) 65 | throw new FileNotFoundException("Could not find file '" + inputFile + "'."); 66 | 67 | using (Bitmap bmp = new Bitmap(inputFile)) { 68 | using (FileStream stream = new FileStream(outputFile, FileMode.OpenOrCreate, FileAccess.Write)) { 69 | using (BinaryWriter writer = new BinaryWriter(stream)) { 70 | stream.SetLength(0); 71 | writer.Write(Encoding.UTF8.GetBytes("XNB")); // format-identifier 72 | writer.Write(Encoding.UTF8.GetBytes("w")); // target-platform 73 | writer.Write((byte)5); // xnb-format-version 74 | byte flagBits = 0; 75 | if (!reach) { 76 | flagBits |= 0x01; 77 | } 78 | if (compressed) { 79 | flagBits |= 0x80; 80 | } 81 | writer.Write(flagBits); // flag-bits; 00=reach, 01=hiprofile, 80=compressed, 00=uncompressed 82 | if (compressed) { 83 | WriteCompressedData(writer, bmp, premultiply); 84 | } 85 | else { 86 | writer.Write(MetadataSize + bmp.Width * bmp.Height * 4); // compressed file size 87 | WriteData(bmp, writer, premultiply); 88 | } 89 | } 90 | } 91 | } 92 | return true; 93 | } 94 | 95 | #endregion 96 | //=========== WRITING ============ 97 | #region Writing 98 | 99 | /**Write compressed image data.*/ 100 | private static void WriteCompressedData(BinaryWriter writer, Bitmap png, bool premultiply) { 101 | using (MemoryStream stream = new MemoryStream()) { 102 | byte[] uncompressedData; 103 | using (BinaryWriter writer2 = new BinaryWriter(stream)) { 104 | WriteData(png, writer2, premultiply); 105 | uncompressedData = stream.ToArray(); 106 | } 107 | byte[] compressedData = XCompress.Compress(uncompressedData); 108 | writer.Write(6 + 4 + 4 + compressedData.Length); // compressed file size including headers 109 | writer.Write(uncompressedData.Length); // uncompressed data size (exluding headers! only the data) 110 | writer.Write(compressedData); 111 | } 112 | } 113 | /**Write uncompressed image data.*/ 114 | private static void WriteData(Bitmap bmp, BinaryWriter writer, bool premultiply) { 115 | writer.Write7BitEncodedInt(1); // type-reader-count 116 | writer.Write7BitEncodedString(Texture2DType); // type-reader-name 117 | writer.Write((int)0); // reader version number 118 | writer.Write7BitEncodedInt(0); // shared-resource-count 119 | 120 | // writing the image pixel data 121 | writer.Write((byte)1); 122 | writer.Write((int)0); 123 | writer.Write(bmp.Width); 124 | writer.Write(bmp.Height); 125 | writer.Write((int)1); 126 | writer.Write(bmp.Width * bmp.Height * 4); 127 | if (bmp.PixelFormat != PixelFormat.Format32bppArgb) { 128 | Bitmap newBmp = new Bitmap(bmp); 129 | bmp = newBmp.Clone(new Rectangle(0, 0, newBmp.Width, newBmp.Height), PixelFormat.Format32bppArgb); 130 | } 131 | BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); 132 | try { 133 | int length = bitmapData.Stride * bitmapData.Height; 134 | byte[] bytes = new byte[length]; 135 | Marshal.Copy(bitmapData.Scan0, bytes, 0, length); 136 | for (int i = 0; i < bytes.Length; i += 4) { 137 | // Always swap red and blue channels premultiply alpha if requested 138 | int a = bytes[i + 3]; 139 | if (!premultiply || a == 255) { 140 | // No premultiply necessary 141 | byte b = bytes[i]; 142 | bytes[i] = bytes[i + 2]; 143 | bytes[i + 2] = b; 144 | } 145 | else if (a != 0) { 146 | byte b = bytes[i]; 147 | bytes[i] = (byte) (bytes[i + 2] * a / 255); 148 | bytes[i + 1] = (byte) (bytes[i + 1] * a / 255); 149 | bytes[i + 2] = (byte) (b * a / 255); 150 | } 151 | else { 152 | // alpha is zero, so just zero everything 153 | bytes[i] = 0; 154 | bytes[i + 1] = 0; 155 | bytes[i + 2] = 0; 156 | } 157 | } 158 | writer.Write(bytes); 159 | } 160 | catch (Exception ex) { 161 | throw ex; 162 | } 163 | finally { 164 | bmp.UnlockBits(bitmapData); 165 | } 166 | } 167 | 168 | #endregion 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /TConvert/Convert/WavConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using TConvert.Extract; 8 | using TConvert.Util; 9 | 10 | namespace TConvert.Convert { 11 | public static class WavConverter { 12 | //========== CONSTANTS =========== 13 | #region Constants 14 | 15 | private const string SoundEffectType = "Microsoft.Xna.Framework.Content.SoundEffectReader"; 16 | /**The path of the temporary converting.*/ 17 | public static readonly string TempConverting = Path.Combine(Path.GetTempPath(), "TriggersToolsGames", "TConvert"); 18 | 19 | public static readonly Random Random = new Random(); 20 | 21 | #endregion 22 | //========= WavConverter ========= 23 | #region Constructors 24 | 25 | /**Creates the temp converting directory.*/ 26 | static WavConverter() { 27 | Directory.CreateDirectory(TempConverting); 28 | } 29 | 30 | #endregion 31 | //========== CONVERTING ========== 32 | #region Converting 33 | 34 | /**Converts the specified wave input file and writes it to the output file.*/ 35 | public static bool Convert(string inputFile, string outputFile, bool changeExtension) { 36 | if (changeExtension) { 37 | outputFile = Path.ChangeExtension(outputFile, ".xnb"); 38 | } 39 | 40 | string ext = Path.GetExtension(inputFile).ToLower(); 41 | bool isTemp = false; 42 | if (ext != ".wav") { 43 | isTemp = true; 44 | string tempOut = Path.Combine(TempConverting, Random.Next().ToString() + ".wav"); 45 | if (!FFmpeg.Convert(inputFile, tempOut)) 46 | throw new WavException("Failed to convert to wav format."); 47 | inputFile = tempOut; 48 | } 49 | 50 | ushort wFormatTag; 51 | ushort nChannels; 52 | uint nSamplesPerSec; 53 | uint nAvgBytesPerSec; 54 | ushort nBlockAlign; 55 | ushort wBitsPerSample; 56 | 57 | int dataChunkSize; 58 | byte[] waveData; 59 | 60 | using (FileStream inputStream = new FileStream(inputFile, FileMode.Open)) { 61 | using (BinaryReader reader = new BinaryReader(inputStream)) { 62 | string format = new string(reader.ReadChars(4)); 63 | if (format != "RIFF") 64 | throw new WavException("Invalid file format: " + format + "."); 65 | 66 | uint fileLength = reader.ReadUInt32(); 67 | if (fileLength != inputStream.Length-8) 68 | throw new WavException("File length mismatch: " + fileLength + " - should be " + inputStream.Length + "."); 69 | 70 | format = new string(reader.ReadChars(4)); 71 | if (format != "WAVE") 72 | throw new WavException("No WAVE tag. (" + format + ")"); 73 | 74 | format = new string(reader.ReadChars(4)); 75 | if (format != "fmt ") 76 | throw new WavException("No fmt tag. (" + format + ")"); 77 | 78 | int chunkSize = reader.ReadInt32(); 79 | if (chunkSize < 16) 80 | throw new WavException("Incorrect format length."); 81 | chunkSize += (int)inputStream.Position; 82 | 83 | if ((wFormatTag = reader.ReadUInt16()) != 1) 84 | throw new Exception("Unimplemented wav codec (must be PCM)."); 85 | 86 | nChannels = reader.ReadUInt16(); 87 | 88 | nSamplesPerSec = reader.ReadUInt32(); 89 | 90 | nAvgBytesPerSec = reader.ReadUInt32(); 91 | 92 | nBlockAlign = reader.ReadUInt16(); 93 | 94 | wBitsPerSample = reader.ReadUInt16(); 95 | 96 | if (nAvgBytesPerSec != (nSamplesPerSec * nChannels * (wBitsPerSample / 8))) 97 | throw new WavException("Average bytes per second number incorrect."); 98 | if (nBlockAlign != (nChannels * (wBitsPerSample / 8))) 99 | throw new WavException("Block align number incorrect."); 100 | 101 | inputStream.Position = chunkSize; 102 | 103 | format = new string(reader.ReadChars(4)); 104 | dataChunkSize = reader.ReadInt32(); 105 | while (format != "data") { 106 | inputStream.Position += dataChunkSize; 107 | format = new string(reader.ReadChars(4)); 108 | dataChunkSize = reader.ReadInt32(); 109 | if (dataChunkSize < 0 || dataChunkSize + (int)inputStream.Position > (int)inputStream.Length) 110 | break; 111 | } 112 | if (format != "data") throw new WavException("No data tag."); 113 | 114 | waveData = reader.ReadBytes(dataChunkSize); 115 | } 116 | } 117 | 118 | using (FileStream outputStream = new FileStream(outputFile, FileMode.OpenOrCreate)) { 119 | using (BinaryWriter writer = new BinaryWriter(outputStream)) { 120 | outputStream.SetLength(0); 121 | 122 | writer.Write(Encoding.UTF8.GetBytes("XNB")); // Format identifier 123 | writer.Write(Encoding.UTF8.GetBytes("w")); // TargetPlatform Windows 124 | writer.Write((byte)5); // XNB format version 125 | 126 | writer.Write((byte)0); // Flag bits: 127 | // File Size TODO 128 | writer.Write(dataChunkSize + 105); //?? 61? 129 | writer.Write7BitEncodedInt(1); // Type Reader count 130 | 131 | writer.Write(SoundEffectType); // String reader name 132 | 133 | writer.Write(0); // reader version number 134 | writer.Write((byte)0); // shared Resource Count 135 | writer.Write((byte)1); // Object Primary asset data....? 136 | 137 | writer.Write(18); // Format size 138 | // Format 139 | writer.Write((ushort)wFormatTag); // ushort wFormatTag; 140 | writer.Write((ushort)nChannels); // ushort nChannels; 141 | writer.Write((uint)nSamplesPerSec); // uint nSamplesPerSec; 142 | writer.Write((uint)nAvgBytesPerSec); // uint nAvgBytesPerSec; 143 | writer.Write((ushort)nBlockAlign); // ushort nBlockAlign; 144 | writer.Write((ushort)wBitsPerSample); // ushort wBitsPerSample; 145 | writer.Write((ushort)0); // ushort cbSize; 146 | 147 | writer.Write(dataChunkSize); // Uint32 Data Size 148 | writer.Write(waveData); // Byte[data size] data 149 | 150 | writer.Write(0); // int32 loop start 151 | writer.Write(dataChunkSize / nBlockAlign); // int32 loop length 152 | 153 | // int32 duration 154 | writer.Write((int)(1000 * dataChunkSize / (nChannels * wBitsPerSample * nSamplesPerSec / 8))); 155 | } 156 | } 157 | 158 | if (isTemp) 159 | File.Delete(inputFile); 160 | return true; 161 | } 162 | 163 | #endregion 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /TConvert/Convert/XCompress.cs: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (C) 2017 sullerandras 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | ******************************************************************************/ 17 | using System; 18 | using System.Collections.Generic; 19 | using System.IO; 20 | using System.Linq; 21 | using System.Reflection; 22 | using System.Runtime.InteropServices; 23 | using System.Text; 24 | using System.Threading.Tasks; 25 | using TConvert.Properties; 26 | using TConvert.Util; 27 | 28 | namespace TConvert.Convert { 29 | /**A static class for xcompress-based compression and decompression.*/ 30 | public static class XCompress { 31 | //========== CONSTANTS =========== 32 | #region Constants 33 | 34 | /**The path of the temporary dll.*/ 35 | private static readonly string TempXCompressDll = Path.Combine(Path.GetTempPath(), "TriggersToolsGames", "xcompress32.dll"); 36 | /**True if xcompress is available to use.*/ 37 | public static readonly bool IsAvailable; 38 | 39 | #endregion 40 | //========= CONSTRUCTORS ========= 41 | #region Constructors 42 | 43 | /**Extracts and loads the xcompress dll.*/ 44 | static XCompress() { 45 | try { 46 | EmbeddedResources.Extract(TempXCompressDll, Resources.xcompress32); 47 | EmbeddedResources.LoadDll(TempXCompressDll); 48 | Compress(new byte[1]); 49 | IsAvailable = true; 50 | } 51 | catch (DllNotFoundException) { 52 | IsAvailable = false; 53 | } 54 | } 55 | 56 | #endregion 57 | //========= COMPRESSION ========== 58 | #region Compression 59 | 60 | /**Compresses the data.*/ 61 | public static byte[] Compress(byte[] decompressedData) { 62 | // Setup our compression context 63 | int compressionContext = 0; 64 | 65 | XMEMCODEC_PARAMETERS_LZX codecParams; 66 | codecParams.Flags = 0; 67 | codecParams.WindowSize = 64 * 1024; 68 | codecParams.CompressionPartitionSize = 256 * 1024; 69 | 70 | XMemCreateCompressionContext( 71 | XMEMCODEC_TYPE.XMEMCODEC_LZX, 72 | ref codecParams, 0, ref compressionContext); 73 | 74 | // Now lets compress 75 | int compressedLen = decompressedData.Length * 2; 76 | byte[] compressed = new byte[compressedLen]; 77 | int decompressedLen = decompressedData.Length; 78 | XMemCompress(compressionContext, 79 | compressed, ref compressedLen, 80 | decompressedData, decompressedLen); 81 | // Go ahead and destory our context 82 | XMemDestroyCompressionContext(compressionContext); 83 | 84 | // Resize our compressed data 85 | Array.Resize(ref compressed, compressedLen); 86 | 87 | // Now lets return it 88 | return compressed; 89 | } 90 | /**Decompresses the data.*/ 91 | public static byte[] Decompress(byte[] compressedData, byte[] decompressedData) { 92 | // Setup our decompression context 93 | int DecompressionContext = 0; 94 | 95 | XMEMCODEC_PARAMETERS_LZX codecParams; 96 | codecParams.Flags = 0; 97 | codecParams.WindowSize = 64 * 1024; 98 | codecParams.CompressionPartitionSize = 256 * 1024; 99 | 100 | XMemCreateDecompressionContext( 101 | XMEMCODEC_TYPE.XMEMCODEC_LZX, 102 | ref codecParams, 0, ref DecompressionContext); 103 | 104 | // Now lets decompress 105 | int compressedLen = compressedData.Length; 106 | int decompressedLen = decompressedData.Length; 107 | try { 108 | XMemDecompress(DecompressionContext, 109 | decompressedData, ref decompressedLen, 110 | compressedData, compressedLen); 111 | } 112 | catch { 113 | } 114 | // Go ahead and destory our context 115 | XMemDestroyDecompressionContext(DecompressionContext); 116 | // Return our decompressed bytes 117 | return decompressedData; 118 | } 119 | 120 | #endregion 121 | //============ NATIVE ============ 122 | #region Native 123 | 124 | public enum XMEMCODEC_TYPE { 125 | XMEMCODEC_DEFAULT = 0, 126 | XMEMCODEC_LZX = 1 127 | } 128 | 129 | [StructLayout(LayoutKind.Explicit)] 130 | public struct XMEMCODEC_PARAMETERS_LZX { 131 | [FieldOffset(0)] 132 | public int Flags; 133 | [FieldOffset(4)] 134 | public int WindowSize; 135 | [FieldOffset(8)] 136 | public int CompressionPartitionSize; 137 | } 138 | 139 | [DllImport("xcompress32.dll", EntryPoint = "XMemCompress")] 140 | public static extern int XMemCompress(int Context, 141 | byte[] pDestination, ref int pDestSize, 142 | byte[] pSource, int pSrcSize); 143 | 144 | [DllImport("xcompress32.dll", EntryPoint = "XMemCreateCompressionContext")] 145 | public static extern int XMemCreateCompressionContext( 146 | XMEMCODEC_TYPE CodecType, ref XMEMCODEC_PARAMETERS_LZX pCodecParams, 147 | int Flags, ref int pContext); 148 | 149 | [DllImport("xcompress32.dll", EntryPoint = "XMemDestroyCompressionContext")] 150 | public static extern void XMemDestroyCompressionContext(int Context); 151 | 152 | [DllImport("xcompress32.dll", EntryPoint = "XMemDecompress")] 153 | public static extern int XMemDecompress(int Context, 154 | byte[] pDestination, ref int pDestSize, 155 | byte[] pSource, int pSrcSize); 156 | 157 | [DllImport("xcompress32.dll", EntryPoint = "XMemCreateDecompressionContext")] 158 | public static extern int XMemCreateDecompressionContext( 159 | XMEMCODEC_TYPE CodecType, 160 | ref XMEMCODEC_PARAMETERS_LZX pCodecParams, 161 | int Flags, ref int pContext); 162 | 163 | [DllImport("xcompress32.dll", EntryPoint = "XMemDestroyDecompressionContext")] 164 | public static extern void XMemDestroyDecompressionContext(int Context); 165 | 166 | #endregion 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /TConvert/ErrorLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace TConvert { 10 | /**A class for writing errors to a default log file.*/ 11 | public static class ErrorLogger { 12 | //========== CONSTANTS =========== 13 | #region Constants 14 | 15 | /**The path of the error log.*/ 16 | public static readonly string LogPath = Path.Combine( 17 | Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), 18 | "TConvert-ErrorLog.txt" 19 | ); 20 | 21 | #endregion 22 | //=========== MEMBERS ============ 23 | #region Members 24 | 25 | /**The writer for the error log file.*/ 26 | private static StreamWriter writer = null; 27 | 28 | #endregion 29 | //=========== WRITING ============ 30 | #region Writing 31 | 32 | /**Returns true if the error log file is open.*/ 33 | public static bool IsOpen { 34 | get { return writer != null; } 35 | } 36 | 37 | /**Opens the error log file.*/ 38 | public static bool Open() { 39 | Close(); 40 | try { 41 | writer = new StreamWriter(LogPath); 42 | WriteErrorHeader(); 43 | return true; 44 | } 45 | catch { 46 | return false; 47 | } 48 | } 49 | /**Closes the error log file.*/ 50 | public static void Close() { 51 | try { 52 | if (writer != null) { 53 | writer.Close(); 54 | writer = null; 55 | } 56 | } 57 | catch { } 58 | 59 | } 60 | /**Starts a new line.*/ 61 | public static void WriteLine() { 62 | if (writer != null || Open()) 63 | writer.WriteLine(); 64 | } 65 | /**Writes the text then starts a new line.*/ 66 | public static void WriteLine(string text) { 67 | if (writer != null || Open()) 68 | writer.WriteLine(text); 69 | } 70 | /**Writes the text.*/ 71 | public static void Write(string text) { 72 | if (writer != null || Open()) 73 | writer.Write(text); 74 | } 75 | 76 | /**Writes the standard error log header.*/ 77 | private static void WriteErrorHeader() { 78 | if (writer != null) { 79 | writer.WriteLine("------------------------------------------------"); 80 | writer.WriteLine("Time: " + DateTime.Now.ToString()); 81 | writer.WriteLine(); 82 | } 83 | } 84 | 85 | #endregion 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /TConvert/Extract/ADPCMConverter.cs: -------------------------------------------------------------------------------- 1 | /* MSADPCMToPCM - Public Domain MSADPCM Decoder 2 | * https://github.com/flibitijibibo/MSADPCMToPCM 3 | * 4 | * Written by Ethan "flibitijibibo" Lee 5 | * http://www.flibitijibibo.com/ 6 | * 7 | * Released under public domain. 8 | * No warranty implied; use at your own risk. 9 | * 10 | * For more on the MSADPCM format, see the MultimediaWiki: 11 | * http://wiki.multimedia.cx/index.php?title=Microsoft_ADPCM 12 | */ 13 | using System; 14 | using System.Collections.Generic; 15 | using System.IO; 16 | using System.Linq; 17 | using System.Text; 18 | using System.Threading.Tasks; 19 | 20 | namespace TConvert.Extract { 21 | public static class ADPCMConverter { 22 | /** 23 | * A bunch of magical numbers that predict the sample data from the 24 | * MSADPCM wavedata. Do not attempt to understand at all costs! 25 | */ 26 | private static readonly int[] adaptionTable = { 27 | 230, 230, 230, 230, 307, 409, 512, 614, 28 | 768, 614, 512, 409, 307, 230, 230, 230 29 | }; 30 | private static readonly int[] adaptCoeff_1 = { 31 | 256, 512, 0, 192, 240, 460, 392 32 | }; 33 | private static readonly int[] adaptCoeff_2 = { 34 | 0, -256, 0, 64, 0, -208, -232 35 | }; 36 | 37 | /** 38 | * Splits the MSADPCM samples from each byte block. 39 | * 40 | * @param block An MSADPCM sample byte 41 | * @param nibbleBlock we copy the parsed shorts into here 42 | */ 43 | private static void getNibbleBlock(int block, int[] nibbleBlock) { 44 | nibbleBlock[0] = (int)((uint)block >> 4); // Upper half 45 | nibbleBlock[1] = (int)(block & 0xF); // Lower half 46 | } 47 | 48 | /** 49 | * Calculates PCM samples based on previous samples and a nibble input. 50 | * 51 | * @param nibble A parsed MSADPCM sample we got from getNibbleBlock 52 | * @param predictor The predictor we get from the MSADPCM block's preamble 53 | * @param sample_1 The first sample we use to predict the next sample 54 | * @param sample_2 The second sample we use to predict the next sample 55 | * @param delta Used to calculate the final sample 56 | * @return The calculated PCM sample 57 | */ 58 | private static short CalculateSample( 59 | int nibble, 60 | int predictor, 61 | short[] sample_1, 62 | short[] sample_2, 63 | short[] delta 64 | ) { 65 | // Get a signed number out of the nibble. We need to retain the 66 | // original nibble value for when we access AdaptionTable[]. 67 | byte signedNibble = (byte) nibble;// sbyte 68 | if ((signedNibble & 0x8) == 0x8) { 69 | signedNibble -= 0x10; 70 | } 71 | 72 | // Calculate new sample 73 | int sampleInt = ( 74 | ((sample_1[0] * adaptCoeff_1[predictor]) + 75 | (sample_2[0] * adaptCoeff_2[predictor]) 76 | ) / 256 77 | ); 78 | sampleInt += signedNibble * delta[0]; 79 | 80 | // Clamp result to 16-bit 81 | short sample; 82 | if (sampleInt < short.MinValue) { 83 | sample = short.MinValue; 84 | } 85 | else if (sampleInt > short.MaxValue) { 86 | sample = short.MaxValue; 87 | } 88 | else { 89 | sample = (short)sampleInt; 90 | } 91 | 92 | // Shuffle samples, get new delta 93 | sample_2[0] = sample_1[0]; 94 | sample_1[0] = sample; 95 | delta[0] = (short)(adaptionTable[nibble] * delta[0] / 256); 96 | 97 | // Saturate the delta to a lower bound of 16 98 | if (delta[0] < 16) 99 | delta[0] = 16; 100 | 101 | return sample; 102 | } 103 | 104 | /** 105 | * Decodes MSADPCM data to signed 16-bit PCM data. 106 | * 107 | * @param source A ByteBuffer containing the headerless MSADPCM data 108 | * @param numChannels The number of channels (WAVEFORMATEX nChannels) 109 | * @param blockAlign The ADPCM block size (WAVEFORMATEX nBlockAlign) 110 | * @return A byte array containing the raw 16-bit PCM wavedata 111 | * 112 | * NOTE: The original MSADPCMToPCM class returns as a short[] array! 113 | */ 114 | public static byte[] ConvertToPCM(byte[] source, short numChannels, short blockAlign) { 115 | //source.order(ByteOrder.LITTLE_ENDIAN); 116 | BinaryReader reader = new BinaryReader(new MemoryStream(source)); 117 | try { 118 | // We write to output when reading the PCM data, then we convert 119 | // it back to a short array at the end. 120 | MemoryStream outStream = new MemoryStream(); 121 | BinaryWriter writer = new BinaryWriter(outStream); 122 | //ByteArrayOutputStream output = new ByteArrayOutputStream(); 123 | //BufferWriter pcmOut = new BufferWriter(output); 124 | //pcmOut.setOrder(ByteOrder.LITTLE_ENDIAN); 125 | 126 | // We'll be using this to get each sample from the blocks. 127 | int[] nibbleBlock = new int[2]; 128 | 129 | // Assuming the whole stream is what we want. 130 | long fileLength = source.Length - blockAlign; 131 | 132 | // Mono or Stereo? 133 | if (numChannels == 1) { 134 | // Read to the end of the file. 135 | while ((int)reader.BaseStream.Position <= fileLength) { 136 | // Read block preamble 137 | int predictor = reader.ReadByte() & 0xff; 138 | short[] delta = { reader.ReadInt16() }; 139 | short[] sample_1 = { reader.ReadInt16() }; 140 | short[] sample_2 = { reader.ReadInt16() }; 141 | 142 | // Send the initial samples straight to PCM out. 143 | writer.Write(sample_2[0]); 144 | writer.Write(sample_1[0]); 145 | 146 | // Go through the bytes in this MSADPCM block. 147 | for (int bytes = 0; bytes < (blockAlign + 15); bytes++) { 148 | // Each sample is one half of a nibbleBlock. 149 | getNibbleBlock(reader.ReadByte() & 0xff, nibbleBlock); 150 | for (int i = 0; i < 2; i++) { 151 | writer.Write( 152 | CalculateSample( 153 | nibbleBlock[i], 154 | predictor, 155 | sample_1, 156 | sample_2, 157 | delta 158 | ) 159 | ); 160 | } 161 | } 162 | } 163 | } 164 | else if (numChannels == 2) { 165 | // Read to the end of the file. 166 | while ((int)reader.BaseStream.Position <= fileLength) { 167 | // Read block preamble 168 | int l_predictor = reader.ReadByte() & 0xff; 169 | int r_predictor = reader.ReadByte() & 0xff; 170 | short[] l_delta = { reader.ReadInt16() }; 171 | short[] r_delta = { reader.ReadInt16() }; 172 | short[] l_sample_1 = { reader.ReadInt16() }; 173 | short[] r_sample_1 = { reader.ReadInt16() }; 174 | short[] l_sample_2 = { reader.ReadInt16() }; 175 | short[] r_sample_2 = { reader.ReadInt16() }; 176 | 177 | // Send the initial samples straight to PCM out. 178 | writer.Write(l_sample_2[0]); 179 | writer.Write(r_sample_2[0]); 180 | writer.Write(l_sample_1[0]); 181 | writer.Write(r_sample_1[0]); 182 | 183 | // Go through the bytes in this MSADPCM block. 184 | for (int bytes = 0; bytes < ((blockAlign + 15) * 2); bytes++) { 185 | // Each block carries one left/right sample. 186 | getNibbleBlock(reader.ReadByte() & 0xff, nibbleBlock); 187 | 188 | // Left channel... 189 | writer.Write( 190 | CalculateSample( 191 | nibbleBlock[0], 192 | l_predictor, 193 | l_sample_1, 194 | l_sample_2, 195 | l_delta 196 | ) 197 | ); 198 | 199 | // Right channel... 200 | writer.Write( 201 | CalculateSample( 202 | nibbleBlock[1], 203 | r_predictor, 204 | r_sample_1, 205 | r_sample_2, 206 | r_delta 207 | ) 208 | ); 209 | } 210 | } 211 | } 212 | else { 213 | throw new Exception("MSADPCM WAVEDATA IS NOT MONO OR STEREO!"); 214 | } 215 | 216 | // We're done writing PCM data... 217 | writer.Close(); 218 | 219 | // Return the array. 220 | return outStream.ToArray(); 221 | } 222 | catch (IOException ex) { 223 | throw new Exception("This should not happen as no I/O" 224 | + " resources are used", ex); 225 | } 226 | } 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /TConvert/Extract/DtxUtil.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | /* FNA - XNA4 Reimplementation for Desktop Platforms 3 | * Copyright 2009-2017 Ethan Lee and the MonoGame Team 4 | * 5 | * Released under the Microsoft Public License. 6 | * See LICENSE for details. 7 | */ 8 | #endregion 9 | 10 | #region Using Statements 11 | using System.IO; 12 | #endregion 13 | 14 | namespace TConvert.Extract { 15 | public static class DxtUtil { 16 | #region Internal Static Methods 17 | 18 | internal static byte[] DecompressDxt1(byte[] imageData, int width, int height) { 19 | using (MemoryStream imageStream = new MemoryStream(imageData)) { 20 | return DecompressDxt1(imageStream, width, height); 21 | } 22 | } 23 | 24 | internal static byte[] DecompressDxt1(Stream imageStream, int width, int height) { 25 | byte[] imageData = new byte[width * height * 4]; 26 | 27 | using (BinaryReader imageReader = new BinaryReader(imageStream)) { 28 | int blockCountX = (width + 3) / 4; 29 | int blockCountY = (height + 3) / 4; 30 | 31 | for (int y = 0; y < blockCountY; y++) { 32 | for (int x = 0; x < blockCountX; x++) { 33 | DecompressDxt1Block(imageReader, x, y, blockCountX, width, height, imageData); 34 | } 35 | } 36 | } 37 | 38 | return imageData; 39 | } 40 | 41 | internal static byte[] DecompressDxt3(byte[] imageData, int width, int height) { 42 | using (MemoryStream imageStream = new MemoryStream(imageData)) { 43 | return DecompressDxt3(imageStream, width, height); 44 | } 45 | } 46 | 47 | internal static byte[] DecompressDxt3(Stream imageStream, int width, int height) { 48 | byte[] imageData = new byte[width * height * 4]; 49 | 50 | using (BinaryReader imageReader = new BinaryReader(imageStream)) { 51 | int blockCountX = (width + 3) / 4; 52 | int blockCountY = (height + 3) / 4; 53 | 54 | for (int y = 0; y < blockCountY; y++) { 55 | for (int x = 0; x < blockCountX; x++) { 56 | DecompressDxt3Block(imageReader, x, y, blockCountX, width, height, imageData); 57 | } 58 | } 59 | } 60 | 61 | return imageData; 62 | } 63 | 64 | internal static byte[] DecompressDxt5(byte[] imageData, int width, int height) { 65 | using (MemoryStream imageStream = new MemoryStream(imageData)) { 66 | return DecompressDxt5(imageStream, width, height); 67 | } 68 | } 69 | 70 | internal static byte[] DecompressDxt5(Stream imageStream, int width, int height) { 71 | byte[] imageData = new byte[width * height * 4]; 72 | 73 | using (BinaryReader imageReader = new BinaryReader(imageStream)) { 74 | int blockCountX = (width + 3) / 4; 75 | int blockCountY = (height + 3) / 4; 76 | 77 | for (int y = 0; y < blockCountY; y++) { 78 | for (int x = 0; x < blockCountX; x++) { 79 | DecompressDxt5Block(imageReader, x, y, blockCountX, width, height, imageData); 80 | } 81 | } 82 | } 83 | 84 | return imageData; 85 | } 86 | 87 | #endregion 88 | 89 | #region Private Static Methods 90 | 91 | private static void DecompressDxt1Block(BinaryReader imageReader, int x, int y, int blockCountX, int width, int height, byte[] imageData) { 92 | ushort c0 = imageReader.ReadUInt16(); 93 | ushort c1 = imageReader.ReadUInt16(); 94 | 95 | byte r0, g0, b0; 96 | byte r1, g1, b1; 97 | ConvertRgb565ToRgb888(c0, out r0, out g0, out b0); 98 | ConvertRgb565ToRgb888(c1, out r1, out g1, out b1); 99 | 100 | uint lookupTable = imageReader.ReadUInt32(); 101 | 102 | for (int blockY = 0; blockY < 4; blockY++) { 103 | for (int blockX = 0; blockX < 4; blockX++) { 104 | byte r = 0, g = 0, b = 0, a = 255; 105 | uint index = (lookupTable >> 2 * (4 * blockY + blockX)) & 0x03; 106 | 107 | if (c0 > c1) { 108 | switch (index) { 109 | case 0: 110 | r = r0; 111 | g = g0; 112 | b = b0; 113 | break; 114 | case 1: 115 | r = r1; 116 | g = g1; 117 | b = b1; 118 | break; 119 | case 2: 120 | r = (byte)((2 * r0 + r1) / 3); 121 | g = (byte)((2 * g0 + g1) / 3); 122 | b = (byte)((2 * b0 + b1) / 3); 123 | break; 124 | case 3: 125 | r = (byte)((r0 + 2 * r1) / 3); 126 | g = (byte)((g0 + 2 * g1) / 3); 127 | b = (byte)((b0 + 2 * b1) / 3); 128 | break; 129 | } 130 | } 131 | else { 132 | switch (index) { 133 | case 0: 134 | r = r0; 135 | g = g0; 136 | b = b0; 137 | break; 138 | case 1: 139 | r = r1; 140 | g = g1; 141 | b = b1; 142 | break; 143 | case 2: 144 | r = (byte)((r0 + r1) / 2); 145 | g = (byte)((g0 + g1) / 2); 146 | b = (byte)((b0 + b1) / 2); 147 | break; 148 | case 3: 149 | r = 0; 150 | g = 0; 151 | b = 0; 152 | a = 0; 153 | break; 154 | } 155 | } 156 | 157 | int px = (x << 2) + blockX; 158 | int py = (y << 2) + blockY; 159 | if ((px < width) && (py < height)) { 160 | int offset = ((py * width) + px) << 2; 161 | imageData[offset] = r; 162 | imageData[offset + 1] = g; 163 | imageData[offset + 2] = b; 164 | imageData[offset + 3] = a; 165 | } 166 | } 167 | } 168 | } 169 | 170 | private static void DecompressDxt3Block(BinaryReader imageReader, int x, int y, int blockCountX, int width, int height, byte[] imageData) { 171 | byte a0 = imageReader.ReadByte(); 172 | byte a1 = imageReader.ReadByte(); 173 | byte a2 = imageReader.ReadByte(); 174 | byte a3 = imageReader.ReadByte(); 175 | byte a4 = imageReader.ReadByte(); 176 | byte a5 = imageReader.ReadByte(); 177 | byte a6 = imageReader.ReadByte(); 178 | byte a7 = imageReader.ReadByte(); 179 | 180 | ushort c0 = imageReader.ReadUInt16(); 181 | ushort c1 = imageReader.ReadUInt16(); 182 | 183 | byte r0, g0, b0; 184 | byte r1, g1, b1; 185 | ConvertRgb565ToRgb888(c0, out r0, out g0, out b0); 186 | ConvertRgb565ToRgb888(c1, out r1, out g1, out b1); 187 | 188 | uint lookupTable = imageReader.ReadUInt32(); 189 | 190 | int alphaIndex = 0; 191 | for (int blockY = 0; blockY < 4; blockY++) { 192 | for (int blockX = 0; blockX < 4; blockX++) { 193 | byte r = 0, g = 0, b = 0, a = 0; 194 | 195 | uint index = (lookupTable >> 2 * (4 * blockY + blockX)) & 0x03; 196 | 197 | switch (alphaIndex) { 198 | case 0: 199 | a = (byte)((a0 & 0x0F) | ((a0 & 0x0F) << 4)); 200 | break; 201 | case 1: 202 | a = (byte)((a0 & 0xF0) | ((a0 & 0xF0) >> 4)); 203 | break; 204 | case 2: 205 | a = (byte)((a1 & 0x0F) | ((a1 & 0x0F) << 4)); 206 | break; 207 | case 3: 208 | a = (byte)((a1 & 0xF0) | ((a1 & 0xF0) >> 4)); 209 | break; 210 | case 4: 211 | a = (byte)((a2 & 0x0F) | ((a2 & 0x0F) << 4)); 212 | break; 213 | case 5: 214 | a = (byte)((a2 & 0xF0) | ((a2 & 0xF0) >> 4)); 215 | break; 216 | case 6: 217 | a = (byte)((a3 & 0x0F) | ((a3 & 0x0F) << 4)); 218 | break; 219 | case 7: 220 | a = (byte)((a3 & 0xF0) | ((a3 & 0xF0) >> 4)); 221 | break; 222 | case 8: 223 | a = (byte)((a4 & 0x0F) | ((a4 & 0x0F) << 4)); 224 | break; 225 | case 9: 226 | a = (byte)((a4 & 0xF0) | ((a4 & 0xF0) >> 4)); 227 | break; 228 | case 10: 229 | a = (byte)((a5 & 0x0F) | ((a5 & 0x0F) << 4)); 230 | break; 231 | case 11: 232 | a = (byte)((a5 & 0xF0) | ((a5 & 0xF0) >> 4)); 233 | break; 234 | case 12: 235 | a = (byte)((a6 & 0x0F) | ((a6 & 0x0F) << 4)); 236 | break; 237 | case 13: 238 | a = (byte)((a6 & 0xF0) | ((a6 & 0xF0) >> 4)); 239 | break; 240 | case 14: 241 | a = (byte)((a7 & 0x0F) | ((a7 & 0x0F) << 4)); 242 | break; 243 | case 15: 244 | a = (byte)((a7 & 0xF0) | ((a7 & 0xF0) >> 4)); 245 | break; 246 | } 247 | ++alphaIndex; 248 | 249 | switch (index) { 250 | case 0: 251 | r = r0; 252 | g = g0; 253 | b = b0; 254 | break; 255 | case 1: 256 | r = r1; 257 | g = g1; 258 | b = b1; 259 | break; 260 | case 2: 261 | r = (byte)((2 * r0 + r1) / 3); 262 | g = (byte)((2 * g0 + g1) / 3); 263 | b = (byte)((2 * b0 + b1) / 3); 264 | break; 265 | case 3: 266 | r = (byte)((r0 + 2 * r1) / 3); 267 | g = (byte)((g0 + 2 * g1) / 3); 268 | b = (byte)((b0 + 2 * b1) / 3); 269 | break; 270 | } 271 | 272 | int px = (x << 2) + blockX; 273 | int py = (y << 2) + blockY; 274 | if ((px < width) && (py < height)) { 275 | int offset = ((py * width) + px) << 2; 276 | imageData[offset] = r; 277 | imageData[offset + 1] = g; 278 | imageData[offset + 2] = b; 279 | imageData[offset + 3] = a; 280 | } 281 | } 282 | } 283 | } 284 | 285 | private static void DecompressDxt5Block(BinaryReader imageReader, int x, int y, int blockCountX, int width, int height, byte[] imageData) { 286 | byte alpha0 = imageReader.ReadByte(); 287 | byte alpha1 = imageReader.ReadByte(); 288 | 289 | ulong alphaMask = (ulong) imageReader.ReadByte(); 290 | alphaMask += (ulong)imageReader.ReadByte() << 8; 291 | alphaMask += (ulong)imageReader.ReadByte() << 16; 292 | alphaMask += (ulong)imageReader.ReadByte() << 24; 293 | alphaMask += (ulong)imageReader.ReadByte() << 32; 294 | alphaMask += (ulong)imageReader.ReadByte() << 40; 295 | 296 | ushort c0 = imageReader.ReadUInt16(); 297 | ushort c1 = imageReader.ReadUInt16(); 298 | 299 | byte r0, g0, b0; 300 | byte r1, g1, b1; 301 | ConvertRgb565ToRgb888(c0, out r0, out g0, out b0); 302 | ConvertRgb565ToRgb888(c1, out r1, out g1, out b1); 303 | 304 | uint lookupTable = imageReader.ReadUInt32(); 305 | 306 | for (int blockY = 0; blockY < 4; blockY++) { 307 | for (int blockX = 0; blockX < 4; blockX++) { 308 | byte r = 0, g = 0, b = 0, a = 255; 309 | uint index = (lookupTable >> 2 * (4 * blockY + blockX)) & 0x03; 310 | 311 | uint alphaIndex = (uint) ((alphaMask >> 3 * (4 * blockY + blockX)) & 0x07); 312 | if (alphaIndex == 0) { 313 | a = alpha0; 314 | } 315 | else if (alphaIndex == 1) { 316 | a = alpha1; 317 | } 318 | else if (alpha0 > alpha1) { 319 | a = (byte)(((8 - alphaIndex) * alpha0 + (alphaIndex - 1) * alpha1) / 7); 320 | } 321 | else if (alphaIndex == 6) { 322 | a = 0; 323 | } 324 | else if (alphaIndex == 7) { 325 | a = 0xff; 326 | } 327 | else { 328 | a = (byte)(((6 - alphaIndex) * alpha0 + (alphaIndex - 1) * alpha1) / 5); 329 | } 330 | 331 | switch (index) { 332 | case 0: 333 | r = r0; 334 | g = g0; 335 | b = b0; 336 | break; 337 | case 1: 338 | r = r1; 339 | g = g1; 340 | b = b1; 341 | break; 342 | case 2: 343 | r = (byte)((2 * r0 + r1) / 3); 344 | g = (byte)((2 * g0 + g1) / 3); 345 | b = (byte)((2 * b0 + b1) / 3); 346 | break; 347 | case 3: 348 | r = (byte)((r0 + 2 * r1) / 3); 349 | g = (byte)((g0 + 2 * g1) / 3); 350 | b = (byte)((b0 + 2 * b1) / 3); 351 | break; 352 | } 353 | 354 | int px = (x << 2) + blockX; 355 | int py = (y << 2) + blockY; 356 | if ((px < width) && (py < height)) { 357 | int offset = ((py * width) + px) << 2; 358 | imageData[offset] = r; 359 | imageData[offset + 1] = g; 360 | imageData[offset + 2] = b; 361 | imageData[offset + 3] = a; 362 | } 363 | } 364 | } 365 | } 366 | 367 | private static void ConvertRgb565ToRgb888(ushort color, out byte r, out byte g, out byte b) { 368 | int temp; 369 | 370 | temp = (color >> 11) * 255 + 16; 371 | r = (byte)((temp / 32 + temp) / 32); 372 | temp = ((color & 0x07E0) >> 5) * 255 + 32; 373 | g = (byte)((temp / 64 + temp) / 64); 374 | temp = (color & 0x001F) * 255 + 16; 375 | b = (byte)((temp / 32 + temp) / 32); 376 | } 377 | 378 | #endregion 379 | } 380 | } 381 | -------------------------------------------------------------------------------- /TConvert/Extract/Ffmpeg.cs: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (C) 2014-2015 Anton Gustafsson 3 | * 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 13 | * all 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 | ******************************************************************************/ 23 | using System; 24 | using System.Collections.Generic; 25 | using System.Diagnostics; 26 | using System.IO; 27 | using System.Linq; 28 | using System.Reflection; 29 | using System.Text; 30 | using System.Threading.Tasks; 31 | using System.Windows; 32 | using TConvert.Properties; 33 | using TConvert.Util; 34 | 35 | namespace TConvert.Extract { 36 | public static class FFmpeg { 37 | //========== CONSTANTS =========== 38 | #region Constants 39 | 40 | /**The path of the temporary executable.*/ 41 | private static readonly string TempFFmpeg = Path.Combine(Path.GetTempPath(), "TriggersToolsGames", "ffmpeg.exe"); 42 | 43 | #endregion 44 | //========= CONSTRUCTORS ========= 45 | #region Constructors 46 | 47 | /**Extracts FFmpeg.*/ 48 | static FFmpeg() { 49 | EmbeddedResources.Extract(TempFFmpeg, Resources.ffmpeg); 50 | } 51 | 52 | #endregion 53 | //========== CONVERTING ========== 54 | #region Converting 55 | 56 | /**Converts the specified input file to wave format.*/ 57 | public static bool Convert(string input, string output) { 58 | List command = new List(); 59 | string arguments = 60 | "-i \"" + Path.GetFullPath(input) + "\" " + 61 | "-acodec pcm_s16le " + 62 | "-nostdin " + 63 | "-ab 128k " + 64 | "-map_metadata -1 " + 65 | "-y " + 66 | "\"" + Path.GetFullPath(output) + "\""; 67 | 68 | ProcessStartInfo start = new ProcessStartInfo(); 69 | start.FileName = TempFFmpeg; 70 | start.Arguments = arguments; 71 | start.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; 72 | 73 | Process process = Process.Start(start); 74 | process.WaitForExit(); 75 | return (process.ExitCode == 0); 76 | } 77 | 78 | #endregion 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /TConvert/Extract/HuffTable.cs: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (C) 2014-2015 Anton Gustafsson 3 | * 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 13 | * all 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 | ******************************************************************************/ 23 | using System; 24 | using System.Collections.Generic; 25 | using System.Linq; 26 | using System.Text; 27 | using System.Threading.Tasks; 28 | using TConvert.Util; 29 | 30 | namespace TConvert.Extract { 31 | public class HuffTable { 32 | private short[] table; 33 | private byte[] length; 34 | 35 | private int maxSymbols; 36 | private int tableBits; 37 | 38 | private const int Safety = 64; 39 | 40 | public HuffTable(int maxSymbols, int tableBits) { 41 | this.maxSymbols = maxSymbols; 42 | this.tableBits = tableBits; 43 | table = new short[(1 << tableBits) + (maxSymbols << 1)]; 44 | length = new byte[maxSymbols + Safety]; 45 | } 46 | 47 | public int MaxSymbols { 48 | get { return maxSymbols; } 49 | } 50 | 51 | public void MakeDecodeTable() { 52 | short sym; 53 | int leaf; 54 | byte bit_num = 1; 55 | int fill; 56 | int pos = 0; /* the current position in the decode table */ 57 | int table_mask = (1 << (int) tableBits); 58 | int bit_mask = (int)((uint)table_mask >> 1); /* don't do 0 length codes */ 59 | int next_symbol = bit_mask; /* base of allocation for long codes */ 60 | 61 | /* fill entries for codes short enough for a direct mapping */ 62 | while (bit_num <= tableBits) { 63 | for (sym = 0; sym < maxSymbols; sym++) { 64 | if (length[sym] == bit_num) { 65 | leaf = pos; 66 | 67 | if ((pos += bit_mask) > table_mask) 68 | return;// 1; /* table overrun */ 69 | 70 | /* fill all possible lookups of this symbol with the symbol itself */ 71 | fill = bit_mask; 72 | while (fill-- > 0) 73 | table[leaf++] = sym; 74 | } 75 | } 76 | uint zeroShift = (uint)bit_mask; 77 | zeroShift >>= 1; 78 | bit_mask = (int)zeroShift; 79 | bit_num++; 80 | } 81 | 82 | /* if there are any codes longer than tableBits */ 83 | if (pos != table_mask) { 84 | /* clear the remainder of the table */ 85 | for (sym = (short)pos; sym < table_mask; sym++) 86 | table[sym] = 0; 87 | 88 | /* give ourselves room for codes to grow by up to 16 more bits */ 89 | pos <<= 16; 90 | table_mask <<= 16; 91 | bit_mask = 1 << 15; 92 | 93 | while (bit_num <= 16) { 94 | for (sym = 0; sym < maxSymbols; sym++) { 95 | if (length[sym] == bit_num) { 96 | leaf = (int)((uint)pos >> 16); 97 | for (fill = 0; fill < bit_num - tableBits; fill++) { 98 | /* if this path hasn't been taken yet, 'allocate' two entries */ 99 | if (table[leaf] == 0) { 100 | table[(next_symbol << 1)] = 0; 101 | table[(next_symbol << 1) + 1] = 0; 102 | table[leaf] = (short)(next_symbol++); 103 | } 104 | /* follow the path and select either left or right for next bit */ 105 | leaf = (table[leaf] << 1); 106 | if (((int)((uint)pos >> (int)(15 - fill)) & 1) == 1) 107 | leaf++; 108 | } 109 | table[leaf] = sym; 110 | 111 | if ((pos += bit_mask) > table_mask) 112 | return;// 1; 113 | } 114 | } 115 | uint zeroShift = (uint)bit_mask; 116 | zeroShift >>= 1; 117 | bit_mask = (int)zeroShift; 118 | bit_num++; 119 | } 120 | } 121 | 122 | /* full talbe? */ 123 | if (pos == table_mask) 124 | return;// 0; 125 | 126 | /* either erroneous table, or all elements are 0 - let's find out. */ 127 | for (sym = 0; sym < maxSymbols; sym++) 128 | if (length[sym] != 0) 129 | return;// 1; 130 | } 131 | 132 | public int ReadHuffSym(LzxBuffer buffer) { 133 | int i, j; 134 | buffer.EnsureBits(16); 135 | if ((i = table[buffer.PeekBits((byte)tableBits)]) >= maxSymbols) { 136 | j = (int)(1 << (int)((4 * 8) - tableBits)); 137 | do { 138 | uint zeroShift = (uint)j; 139 | zeroShift >>= 1; 140 | j = (int)zeroShift; 141 | i <<= 1; 142 | i |= (buffer.BitBuffer & j) != 0 ? (int)1 : 0; 143 | 144 | if (j == 0) 145 | throw new Exception(); // return 0; 146 | 147 | } while ((i = table[i]) >= maxSymbols); 148 | } 149 | j = length[i]; 150 | buffer.RemoveBits((byte)j); 151 | 152 | return i; 153 | } 154 | 155 | public void Reset() { 156 | 157 | table.Fill((short)0); 158 | length.Fill((byte)0); 159 | } 160 | 161 | public short[] Table { 162 | get { return table; } 163 | } 164 | 165 | public byte[] Length { 166 | get { return length; } 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /TConvert/Extract/LzxBuffer.cs: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (C) 2014-2015 Anton Gustafsson 3 | * 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 13 | * all 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 | ******************************************************************************/ 23 | using System; 24 | using System.Collections.Generic; 25 | using System.IO; 26 | using System.Linq; 27 | using System.Text; 28 | using System.Threading.Tasks; 29 | 30 | namespace TConvert.Extract { 31 | public class LzxBuffer { 32 | private BinaryReader reader; 33 | private int remainingBits = 0; 34 | private int bitBuffer = 0; 35 | 36 | public LzxBuffer(BinaryReader reader) { 37 | this.reader = reader; 38 | } 39 | 40 | public void Reset() { 41 | remainingBits = 0; 42 | bitBuffer = 0; 43 | } 44 | 45 | public void EnsureBits(int bitCount) { 46 | if (bitCount < 0 || bitCount > 32) { 47 | throw new ArgumentException(bitCount.ToString()); 48 | } 49 | 50 | while (remainingBits < bitCount) { 51 | int lo = reader.ReadByte() & 0xff; 52 | int hi = reader.ReadByte() & 0xff; 53 | bitBuffer |= ((hi << 8) | lo) << (4 * 8 - 16 - remainingBits); 54 | remainingBits += 16; 55 | } 56 | } 57 | 58 | public int PeekBits(int bitCount) { 59 | if (bitCount > remainingBits) { 60 | throw new ArgumentException("Not enough bits: required " 61 | + bitCount + " has " + remainingBits); 62 | } 63 | 64 | return (int)((uint)bitBuffer >> (32 - bitCount)); 65 | } 66 | 67 | public void RemoveBits(int bitCount) { 68 | bitBuffer <<= bitCount; 69 | remainingBits -= bitCount; 70 | } 71 | 72 | public int ReadBits(int bitCount) { 73 | int result = 0; 74 | 75 | if (bitCount > 0) { 76 | EnsureBits(bitCount); 77 | result = PeekBits(bitCount); 78 | RemoveBits(bitCount); 79 | } 80 | 81 | return result; 82 | } 83 | 84 | public int BitBuffer { 85 | get { return bitBuffer; } 86 | } 87 | 88 | public int RemainingBits { 89 | get { return remainingBits; } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /TConvert/Extract/XnbExtractor.cs: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * Implementation of LZX decoding, 4 | * a java port of LzxDecoder.cs from MonoGame 5 | */ 6 | 7 | /* This file was derived from libmspack 8 | * (C) 2003-2004 Stuart Caie. 9 | * (C) 2011 Ali Scissons. 10 | * 11 | * The LZX method was created by Jonathan Forbes and Tomi Poutanen, adapted 12 | * by Microsoft Corporation. 13 | * 14 | * This source file is Dual licensed; meaning the end-user of this source file 15 | * may redistribute/modify it under the LGPL 2.1 or MS-PL licenses. 16 | */ 17 | // LGPL License 18 | /* GNU LESSER GENERAL PUBLIC LICENSE version 2.1 19 | * LzxDecoder is free software; you can redistribute it and/or modify it under 20 | * the terms of the GNU Lesser General Public License (LGPL) version 2.1 21 | */ 22 | // MS-PL License 23 | /* 24 | * MICROSOFT PUBLIC LICENSE 25 | * This source code is subject to the terms of the Microsoft Public License (Ms-PL). 26 | * 27 | * Redistribution and use in source and binary forms, with or without modification, 28 | * is permitted provided that redistributions of the source code retain the above 29 | * copyright notices and this file header. 30 | * 31 | * Additional copyright notices should be appended to the list above. 32 | * 33 | * For details, see . 34 | */ 35 | /* 36 | * This derived work is recognized by Stuart Caie and is authorized to adapt 37 | * any changes made to lzxd.c in his libmspack library and will still retain 38 | * this dual licensing scheme. Big thanks to Stuart Caie! 39 | * 40 | * DETAILS 41 | * This file is a pure C# port of the lzxd.c file from libmspack, with minor 42 | * changes towards the decompression of XNB files. The original decompression 43 | * software of LZX encoded data was written by Suart Caie in his 44 | * libmspack/cabextract projects, which can be located at 45 | * http://http://www.cabextract.org.uk/ 46 | */ 47 | using System; 48 | using System.Collections.Generic; 49 | using System.Drawing; 50 | using System.Drawing.Imaging; 51 | using System.IO; 52 | using System.Linq; 53 | using System.Runtime.InteropServices; 54 | using System.Text; 55 | using System.Threading.Tasks; 56 | using TConvert.Util; 57 | 58 | namespace TConvert.Extract { 59 | 60 | /**An extractor for Xnb files.*/ 61 | public static class XnbExtractor { 62 | //========== CONSTANTS =========== 63 | #region Constants 64 | 65 | private const int SurfaceFormatColor = 0; 66 | private const int SurfaceFormatDxt1 = 4; 67 | private const int SurfaceFormatDxt3 = 5; 68 | private const int SurfaceFormatDxt5 = 6; 69 | 70 | private const int HeaderSize = 14; 71 | 72 | #endregion 73 | //=========== MEMBERS ============ 74 | #region Members 75 | 76 | /**The compression decoder.*/ 77 | private static LzxDecoder lzxDecoder = new LzxDecoder(); 78 | 79 | #endregion 80 | //========== EXTRACTING ========== 81 | #region Extracting 82 | 83 | /**Extracts and writes the image to file.*/ 84 | public static bool Extract(string inputFile, string outputFile, bool changeExtension, bool extractImages, bool extractSounds, bool extractFonts) { 85 | using (MemoryStream inputStream = new MemoryStream(File.ReadAllBytes(inputFile))) { 86 | BinaryReader reader = new BinaryReader(inputStream); 87 | 88 | if (!reader.ReadAndCompareString("XNB")) { 89 | reader.Close(); 90 | throw new XnbException("Not an XNB file: " + Path.GetFileName(inputFile) + "."); 91 | } 92 | 93 | // Ignore target platform, it shouldn't matter 94 | int targetPlatform = reader.ReadByte(); 95 | 96 | int version = reader.ReadByte(); 97 | if (version != 5) { 98 | reader.Close(); 99 | throw new XnbException("Unsupported XNB version: " + version + "."); 100 | } 101 | 102 | bool compressed = (reader.ReadByte() & 0x80) != 0; 103 | 104 | int compressedSize = reader.ReadInt32(); 105 | int decompressedSize = (compressed ? reader.ReadInt32() : compressedSize); 106 | 107 | if (compressed) { 108 | MemoryStream decompressedStream = new MemoryStream(decompressedSize); 109 | 110 | lzxDecoder.Decompress(reader, compressedSize - HeaderSize, decompressedStream, decompressedSize); 111 | 112 | decompressedStream.Position = 0; 113 | 114 | reader.Close(); 115 | reader = new BinaryReader(decompressedStream); 116 | } 117 | 118 | int typeReaderCount = reader.Read7BitEncodedInt(); 119 | 120 | // The first type reader is used for reading the primary asset 121 | string typeReaderName = reader.Read7BitEncodedString(); 122 | // The type reader version - Dosen't matter 123 | reader.ReadInt32(); 124 | 125 | // Type reader names MIGHT contain assembly information 126 | int assemblyInformationIndex = typeReaderName.IndexOf(','); 127 | if (assemblyInformationIndex != -1) 128 | typeReaderName = typeReaderName.Substring(0, assemblyInformationIndex); 129 | 130 | // Skip the remaining type readers, as all types are known 131 | for (int k = 1; k < typeReaderCount; k++) { 132 | reader.Read7BitEncodedString(); 133 | reader.ReadInt32(); 134 | } 135 | 136 | // Shared resources are unused by Terraria assets 137 | if (reader.Read7BitEncodedInt() != 0) { 138 | reader.Close(); 139 | throw new XnbException("Shared resources are not supported."); 140 | } 141 | 142 | if (reader.Read7BitEncodedInt() != 1) { 143 | reader.Close(); 144 | throw new XnbException("Primary asset is null; this shouldn't happen."); 145 | } 146 | 147 | //string baseFileName = Path.GetFileNameWithoutExtension(inputFile); 148 | 149 | // Switch on the type reader name, excluding assembly information 150 | switch (typeReaderName) { 151 | case "Microsoft.Xna.Framework.Content.Texture2DReader": { 152 | if (!extractImages) { 153 | reader.Close(); 154 | return false; 155 | } 156 | if (changeExtension) { 157 | outputFile = Path.ChangeExtension(outputFile, ".png"); 158 | } 159 | 160 | Bitmap bmp = ReadTexture2D(reader); 161 | bmp.Save(outputFile, ImageFormat.Png); 162 | return true; 163 | } 164 | case "Microsoft.Xna.Framework.Content.SoundEffectReader": { 165 | if (!extractSounds) { 166 | reader.Close(); 167 | return false; 168 | } 169 | if (changeExtension) { 170 | outputFile = Path.ChangeExtension(outputFile, ".wav"); 171 | } 172 | 173 | int audioFormat = reader.ReadInt32(); 174 | if (audioFormat != 18) { 175 | reader.Close(); 176 | throw new XnbException("Unimplemented audio format: " + audioFormat + "."); 177 | } 178 | 179 | int wavCodec = reader.ReadInt16(); 180 | if (wavCodec != 1) { 181 | reader.Close(); 182 | throw new XnbException("Unimplemented wav codec: " + wavCodec + "."); 183 | } 184 | 185 | int channels = reader.ReadInt16() & 0xffff; 186 | int samplesPerSecond = reader.ReadInt32(); 187 | int averageBytesPerSecond = reader.ReadInt32(); 188 | int blockAlign = reader.ReadInt16() & 0xffff; 189 | int bitsPerSample = reader.ReadInt16() & 0xffff; 190 | reader.ReadInt16(); // Unknown 191 | int dataChunkSize = reader.ReadInt32(); 192 | 193 | // Note that the samples are written directly from the source buffer 194 | 195 | FileStream stream = new FileStream(outputFile, FileMode.OpenOrCreate); 196 | BinaryWriter writer = new BinaryWriter(stream); 197 | stream.SetLength(0); 198 | 199 | // Write header 200 | writer.Write(Encoding.UTF8.GetBytes("RIFF")); 201 | writer.Write(dataChunkSize + 36); 202 | writer.Write(Encoding.UTF8.GetBytes("WAVE")); 203 | writer.Write(Encoding.UTF8.GetBytes("fmt ")); 204 | writer.Write((int)16); 205 | writer.Write((short)1); 206 | writer.Write((short)channels); 207 | writer.Write(samplesPerSecond); 208 | writer.Write(averageBytesPerSecond); 209 | writer.Write((short)blockAlign); 210 | writer.Write((short)bitsPerSample); 211 | writer.Write(Encoding.UTF8.GetBytes("data")); 212 | writer.Write(dataChunkSize); 213 | 214 | // Write samples 215 | writer.Write(reader.ReadBytes(dataChunkSize), 0, dataChunkSize); 216 | 217 | writer.Close(); 218 | reader.Close(); 219 | return true; 220 | } 221 | case "ReLogic.Graphics.DynamicSpriteFontReader": { 222 | if (!extractFonts) { 223 | reader.Close(); 224 | return false; 225 | } 226 | if (changeExtension) { 227 | outputFile = Path.ChangeExtension(outputFile, ".png"); 228 | } 229 | 230 | float spacing = reader.ReadSingle(); 231 | int lineSpacing = reader.ReadInt32(); 232 | char defaultCharacter = (char)reader.ReadChar(); 233 | int numPages = reader.ReadInt32(); 234 | for (int i = 0; i < numPages; i++) { 235 | string newOutputFile = Path.Combine(Path.GetDirectoryName(outputFile), 236 | Path.GetFileNameWithoutExtension(outputFile) + 237 | "_" + i + Path.GetExtension(outputFile)); 238 | 239 | reader.Read7BitEncodedInt(); 240 | Bitmap bmp = ReadTexture2D(reader); 241 | bmp.Save(newOutputFile, ImageFormat.Png); 242 | 243 | SkipList(reader, 16); // List 244 | SkipList(reader, 16); // List 245 | SkipCharList(reader); // List 246 | SkipList(reader, 12); // List 247 | } 248 | reader.Close(); 249 | return true; 250 | } 251 | case "Microsoft.Xna.Framework.Content.SpriteFontReader": { 252 | // Not in use by Terraria anymore, but it's easy to read so I may as well include it. 253 | if (!extractFonts) { 254 | reader.Close(); 255 | return false; 256 | } 257 | if (changeExtension) { 258 | outputFile = Path.ChangeExtension(outputFile, ".png"); 259 | } 260 | 261 | reader.Read7BitEncodedInt(); 262 | Bitmap bmp = ReadTexture2D(reader); 263 | bmp.Save(outputFile, ImageFormat.Png); 264 | 265 | // Skip the rest of the data. It's not needed. 266 | 267 | reader.Close(); 268 | return true; 269 | } 270 | 271 | default: 272 | reader.Close(); 273 | throw new XnbException("Unsupported asset type: " + typeReaderName + "."); 274 | } 275 | } 276 | } 277 | 278 | /**Reads an Xnb Texture2D.*/ 279 | private static Bitmap ReadTexture2D(BinaryReader reader) { 280 | int surfaceFormat = reader.ReadInt32(); 281 | int width = reader.ReadInt32(); 282 | int height = reader.ReadInt32(); 283 | 284 | // Mip count 285 | int mipCount = reader.ReadInt32(); 286 | // Size 287 | int size = reader.ReadInt32(); 288 | 289 | if (mipCount < 1) { 290 | throw new XnbException("Unexpected mipCount: " + mipCount + "."); 291 | } 292 | 293 | byte[] source = reader.ReadBytes(size); 294 | 295 | if (surfaceFormat != SurfaceFormatColor) { 296 | //https://github.com/mcgrue/FNA/blob/master/src/Content/ContentReaders/Texture2DReader.cs 297 | 298 | if (surfaceFormat == SurfaceFormatDxt1) { 299 | source = DxtUtil.DecompressDxt1(source, width, height); 300 | } 301 | else if (surfaceFormat == SurfaceFormatDxt3) { 302 | source = DxtUtil.DecompressDxt3(source, width, height); 303 | } 304 | else if (surfaceFormat == SurfaceFormatDxt5) { 305 | source = DxtUtil.DecompressDxt5(source, width, height); 306 | } 307 | else { 308 | throw new XnbException("Unexpected surface format: " + surfaceFormat + "."); 309 | } 310 | } 311 | 312 | // Swap R and B channels 313 | for (int j = 0; j < width * height; j++) { 314 | byte swap = source[j * 4 + 0]; 315 | source[j * 4 + 0] = source[j * 4 + 2]; 316 | source[j * 4 + 2] = swap; 317 | } 318 | 319 | // Write to the bitmap 320 | Bitmap bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb); 321 | BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); 322 | IntPtr data = bmpData.Scan0; 323 | Marshal.Copy(source, 0, data, source.Length); 324 | bmp.UnlockBits(bmpData); 325 | 326 | // Skip the rest of the mips 327 | for (int i = 1; i < mipCount; i++) { 328 | size = reader.ReadInt32(); 329 | reader.BaseStream.Position += size; 330 | } 331 | 332 | return bmp; 333 | } 334 | /**Skips an Xnb list object.*/ 335 | private static void SkipList(BinaryReader reader, int objSize) { 336 | reader.Read7BitEncodedInt(); 337 | int count = reader.ReadInt32(); 338 | reader.BaseStream.Position += count * objSize; 339 | } 340 | /**Skips an Xnb char list object.*/ 341 | private static void SkipCharList(BinaryReader reader) { 342 | reader.Read7BitEncodedInt(); 343 | int count = reader.ReadInt32(); 344 | reader.ReadChars(count); 345 | } 346 | 347 | #endregion 348 | } 349 | } 350 | -------------------------------------------------------------------------------- /TConvert/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("TConvert")] 11 | #if !(CONSOLE) 12 | [assembly: AssemblyDescription("TConvert - A combination tool for Terraria content resources.")] 13 | #else 14 | [assembly: AssemblyDescription("TConvert (Console Ver) - A combination tool for Terraria content resources.")] 15 | #endif 16 | [assembly: AssemblyConfiguration("")] 17 | [assembly: AssemblyCompany("Trigger's Tools & Games")] 18 | [assembly: AssemblyProduct("TConvert")] 19 | [assembly: AssemblyCopyright("Copyright © Robert Jordan 2018")] 20 | [assembly: AssemblyTrademark("")] 21 | [assembly: AssemblyCulture("")] 22 | 23 | // Setting ComVisible to false makes the types in this assembly not visible 24 | // to COM components. If you need to access a type in this assembly from 25 | // COM, set the ComVisible attribute to true on that type. 26 | [assembly: ComVisible(false)] 27 | 28 | //In order to begin building localizable applications, set 29 | //CultureYouAreCodingWith in your .csproj file 30 | //inside a . For example, if you are using US english 31 | //in your source files, set the to en-US. Then uncomment 32 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 33 | //the line below to match the UICulture setting in the project file. 34 | 35 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 36 | 37 | 38 | [assembly: ThemeInfo( 39 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 40 | //(used if a resource is not found in the page, 41 | // or application resource dictionaries) 42 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 43 | //(used if a resource is not found in the page, 44 | // app, or any theme specific resource dictionaries) 45 | )] 46 | 47 | 48 | // Version information for an assembly consists of the following four values: 49 | // 50 | // Major Version 51 | // Minor Version 52 | // Build Number 53 | // Revision 54 | // 55 | // You can specify all the values or you can default the Build and Revision Numbers 56 | // by using the '*' as shown below: 57 | // [assembly: AssemblyVersion("1.0.*")] 58 | [assembly: AssemblyVersion("1.0.2.1")] 59 | [assembly: AssemblyFileVersion("1.0.2.1")] 60 | [assembly: Guid("81FD8C9E-23D9-4CE3-95F7-21B735444371")] 61 | [assembly: NeutralResourcesLanguage("en-US")] 62 | 63 | -------------------------------------------------------------------------------- /TConvert/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace TConvert.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.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 | /// Returns the cached ResourceManager instance used by this class. 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("TConvert.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 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 About { 67 | get { 68 | object obj = ResourceManager.GetObject("About", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). 75 | /// 76 | internal static System.Drawing.Icon AppError { 77 | get { 78 | object obj = ResourceManager.GetObject("AppError", resourceCulture); 79 | return ((System.Drawing.Icon)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Drawing.Bitmap. 85 | /// 86 | internal static System.Drawing.Bitmap AutoClose { 87 | get { 88 | object obj = ResourceManager.GetObject("AutoClose", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | 93 | /// 94 | /// Looks up a localized resource of type System.Drawing.Bitmap. 95 | /// 96 | internal static System.Drawing.Bitmap Browse { 97 | get { 98 | object obj = ResourceManager.GetObject("Browse", resourceCulture); 99 | return ((System.Drawing.Bitmap)(obj)); 100 | } 101 | } 102 | 103 | /// 104 | /// Looks up a localized resource of type System.Drawing.Bitmap. 105 | /// 106 | internal static System.Drawing.Bitmap CloseCmdProgress { 107 | get { 108 | object obj = ResourceManager.GetObject("CloseCmdProgress", resourceCulture); 109 | return ((System.Drawing.Bitmap)(obj)); 110 | } 111 | } 112 | 113 | /// 114 | /// Looks up a localized resource of type System.Drawing.Bitmap. 115 | /// 116 | internal static System.Drawing.Bitmap CloseDropProgress { 117 | get { 118 | object obj = ResourceManager.GetObject("CloseDropProgress", resourceCulture); 119 | return ((System.Drawing.Bitmap)(obj)); 120 | } 121 | } 122 | 123 | /// 124 | /// Looks up a localized resource of type System.Drawing.Bitmap. 125 | /// 126 | internal static System.Drawing.Bitmap CloseProgress { 127 | get { 128 | object obj = ResourceManager.GetObject("CloseProgress", resourceCulture); 129 | return ((System.Drawing.Bitmap)(obj)); 130 | } 131 | } 132 | 133 | /// 134 | /// Looks up a localized resource of type System.Drawing.Bitmap. 135 | /// 136 | internal static System.Drawing.Bitmap Compression { 137 | get { 138 | object obj = ResourceManager.GetObject("Compression", resourceCulture); 139 | return ((System.Drawing.Bitmap)(obj)); 140 | } 141 | } 142 | 143 | /// 144 | /// Looks up a localized resource of type System.Drawing.Bitmap. 145 | /// 146 | internal static System.Drawing.Bitmap Credits { 147 | get { 148 | object obj = ResourceManager.GetObject("Credits", resourceCulture); 149 | return ((System.Drawing.Bitmap)(obj)); 150 | } 151 | } 152 | 153 | /// 154 | /// Looks up a localized resource of type System.Drawing.Bitmap. 155 | /// 156 | internal static System.Drawing.Bitmap Empty { 157 | get { 158 | object obj = ResourceManager.GetObject("Empty", resourceCulture); 159 | return ((System.Drawing.Bitmap)(obj)); 160 | } 161 | } 162 | 163 | /// 164 | /// Looks up a localized resource of type System.Drawing.Bitmap. 165 | /// 166 | internal static System.Drawing.Bitmap ErrorIcon { 167 | get { 168 | object obj = ResourceManager.GetObject("ErrorIcon", resourceCulture); 169 | return ((System.Drawing.Bitmap)(obj)); 170 | } 171 | } 172 | 173 | /// 174 | /// Looks up a localized resource of type System.Drawing.Bitmap. 175 | /// 176 | internal static System.Drawing.Bitmap Exit { 177 | get { 178 | object obj = ResourceManager.GetObject("Exit", resourceCulture); 179 | return ((System.Drawing.Bitmap)(obj)); 180 | } 181 | } 182 | 183 | /// 184 | /// Looks up a localized resource of type System.Byte[]. 185 | /// 186 | internal static byte[] ffmpeg { 187 | get { 188 | object obj = ResourceManager.GetObject("ffmpeg", resourceCulture); 189 | return ((byte[])(obj)); 190 | } 191 | } 192 | 193 | /// 194 | /// Looks up a localized resource of type System.Drawing.Bitmap. 195 | /// 196 | internal static System.Drawing.Bitmap Github { 197 | get { 198 | object obj = ResourceManager.GetObject("Github", resourceCulture); 199 | return ((System.Drawing.Bitmap)(obj)); 200 | } 201 | } 202 | 203 | /// 204 | /// Looks up a localized resource of type System.Drawing.Bitmap. 205 | /// 206 | internal static System.Drawing.Bitmap Help { 207 | get { 208 | object obj = ResourceManager.GetObject("Help", resourceCulture); 209 | return ((System.Drawing.Bitmap)(obj)); 210 | } 211 | } 212 | 213 | /// 214 | /// Looks up a localized resource of type System.Drawing.Bitmap. 215 | /// 216 | internal static System.Drawing.Bitmap InfoIcon { 217 | get { 218 | object obj = ResourceManager.GetObject("InfoIcon", resourceCulture); 219 | return ((System.Drawing.Bitmap)(obj)); 220 | } 221 | } 222 | 223 | /// 224 | /// Looks up a localized resource of type System.Drawing.Bitmap. 225 | /// 226 | internal static System.Drawing.Bitmap Logo112 { 227 | get { 228 | object obj = ResourceManager.GetObject("Logo112", resourceCulture); 229 | return ((System.Drawing.Bitmap)(obj)); 230 | } 231 | } 232 | 233 | /// 234 | /// Looks up a localized resource of type System.Drawing.Bitmap. 235 | /// 236 | internal static System.Drawing.Bitmap Premultiply { 237 | get { 238 | object obj = ResourceManager.GetObject("Premultiply", resourceCulture); 239 | return ((System.Drawing.Bitmap)(obj)); 240 | } 241 | } 242 | 243 | /// 244 | /// Looks up a localized resource of type System.Drawing.Bitmap. 245 | /// 246 | internal static System.Drawing.Bitmap QuestionIcon { 247 | get { 248 | object obj = ResourceManager.GetObject("QuestionIcon", resourceCulture); 249 | return ((System.Drawing.Bitmap)(obj)); 250 | } 251 | } 252 | 253 | /// 254 | /// Looks up a localized resource of type System.Drawing.Bitmap. 255 | /// 256 | internal static System.Drawing.Bitmap Sound { 257 | get { 258 | object obj = ResourceManager.GetObject("Sound", resourceCulture); 259 | return ((System.Drawing.Bitmap)(obj)); 260 | } 261 | } 262 | 263 | /// 264 | /// Looks up a localized resource of type System.Drawing.Bitmap. 265 | /// 266 | internal static System.Drawing.Bitmap TerrariaIcon { 267 | get { 268 | object obj = ResourceManager.GetObject("TerrariaIcon", resourceCulture); 269 | return ((System.Drawing.Bitmap)(obj)); 270 | } 271 | } 272 | 273 | /// 274 | /// Looks up a localized resource of type System.Drawing.Bitmap. 275 | /// 276 | internal static System.Drawing.Bitmap WarningIcon { 277 | get { 278 | object obj = ResourceManager.GetObject("WarningIcon", resourceCulture); 279 | return ((System.Drawing.Bitmap)(obj)); 280 | } 281 | } 282 | 283 | /// 284 | /// Looks up a localized resource of type System.Byte[]. 285 | /// 286 | internal static byte[] xcompress32 { 287 | get { 288 | object obj = ResourceManager.GetObject("xcompress32", resourceCulture); 289 | return ((byte[])(obj)); 290 | } 291 | } 292 | } 293 | } 294 | -------------------------------------------------------------------------------- /TConvert/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\Icons\AppError.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | ..\Resources\Icons\Browse.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | 128 | ..\Resources\Icons\Empty.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 129 | 130 | 131 | ..\Resources\Icons\ErrorIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 132 | 133 | 134 | ..\Resources\ffmpeg.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 135 | 136 | 137 | ..\Resources\Icons\InfoIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 138 | 139 | 140 | ..\Resources\Icons\QuestionIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 141 | 142 | 143 | ..\Resources\Icons\WarningIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 144 | 145 | 146 | ..\Resources\Icons\About.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 147 | 148 | 149 | ..\Resources\Icons\CloseDropProgress.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 150 | 151 | 152 | ..\Resources\Icons\CloseProgress.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 153 | 154 | 155 | ..\Resources\Icons\Credits.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 156 | 157 | 158 | ..\Resources\Icons\Exit.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 159 | 160 | 161 | ..\Resources\Icons\Github.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 162 | 163 | 164 | ..\Resources\Icons\Help.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 165 | 166 | 167 | ..\Resources\Logo112.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 168 | 169 | 170 | ..\Resources\Icons\TerrariaIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 171 | 172 | 173 | ..\Resources\Icons\CloseCmdProgress.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 174 | 175 | 176 | ..\Resources\Icons\Compression.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 177 | 178 | 179 | ..\Resources\xcompress32.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 180 | 181 | 182 | ..\Resources\Icons\AutoClose.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 183 | 184 | 185 | ..\Resources\Icons\Sound.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 186 | 187 | 188 | ..\Resources\Icons\Premultiply.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 189 | 190 | -------------------------------------------------------------------------------- /TConvert/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace TConvert.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.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 TerrariaContentDirectory { 30 | get { 31 | return ((string)(this["TerrariaContentDirectory"])); 32 | } 33 | set { 34 | this["TerrariaContentDirectory"] = value; 35 | } 36 | } 37 | 38 | [global::System.Configuration.UserScopedSettingAttribute()] 39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 40 | [global::System.Configuration.DefaultSettingValueAttribute("")] 41 | public string ExtractFolderInput { 42 | get { 43 | return ((string)(this["ExtractFolderInput"])); 44 | } 45 | set { 46 | this["ExtractFolderInput"] = value; 47 | } 48 | } 49 | 50 | [global::System.Configuration.UserScopedSettingAttribute()] 51 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 52 | [global::System.Configuration.DefaultSettingValueAttribute("")] 53 | public string ExtractFolderOutput { 54 | get { 55 | return ((string)(this["ExtractFolderOutput"])); 56 | } 57 | set { 58 | this["ExtractFolderOutput"] = value; 59 | } 60 | } 61 | 62 | [global::System.Configuration.UserScopedSettingAttribute()] 63 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 64 | [global::System.Configuration.DefaultSettingValueAttribute("")] 65 | public string ExtractFileInput { 66 | get { 67 | return ((string)(this["ExtractFileInput"])); 68 | } 69 | set { 70 | this["ExtractFileInput"] = value; 71 | } 72 | } 73 | 74 | [global::System.Configuration.UserScopedSettingAttribute()] 75 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 76 | [global::System.Configuration.DefaultSettingValueAttribute("")] 77 | public string ExtractFileOutput { 78 | get { 79 | return ((string)(this["ExtractFileOutput"])); 80 | } 81 | set { 82 | this["ExtractFileOutput"] = value; 83 | } 84 | } 85 | 86 | [global::System.Configuration.UserScopedSettingAttribute()] 87 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 88 | [global::System.Configuration.DefaultSettingValueAttribute("")] 89 | public string ConvertFolderInput { 90 | get { 91 | return ((string)(this["ConvertFolderInput"])); 92 | } 93 | set { 94 | this["ConvertFolderInput"] = value; 95 | } 96 | } 97 | 98 | [global::System.Configuration.UserScopedSettingAttribute()] 99 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 100 | [global::System.Configuration.DefaultSettingValueAttribute("")] 101 | public string ConvertFolderOutput { 102 | get { 103 | return ((string)(this["ConvertFolderOutput"])); 104 | } 105 | set { 106 | this["ConvertFolderOutput"] = value; 107 | } 108 | } 109 | 110 | [global::System.Configuration.UserScopedSettingAttribute()] 111 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 112 | [global::System.Configuration.DefaultSettingValueAttribute("")] 113 | public string ConvertFileInput { 114 | get { 115 | return ((string)(this["ConvertFileInput"])); 116 | } 117 | set { 118 | this["ConvertFileInput"] = value; 119 | } 120 | } 121 | 122 | [global::System.Configuration.UserScopedSettingAttribute()] 123 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 124 | [global::System.Configuration.DefaultSettingValueAttribute("")] 125 | public string ConvertFileOutput { 126 | get { 127 | return ((string)(this["ConvertFileOutput"])); 128 | } 129 | set { 130 | this["ConvertFileOutput"] = value; 131 | } 132 | } 133 | 134 | [global::System.Configuration.UserScopedSettingAttribute()] 135 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 136 | [global::System.Configuration.DefaultSettingValueAttribute("")] 137 | public string ScriptFile { 138 | get { 139 | return ((string)(this["ScriptFile"])); 140 | } 141 | set { 142 | this["ScriptFile"] = value; 143 | } 144 | } 145 | 146 | [global::System.Configuration.UserScopedSettingAttribute()] 147 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 148 | [global::System.Configuration.DefaultSettingValueAttribute("")] 149 | public string BackupFolderContent { 150 | get { 151 | return ((string)(this["BackupFolderContent"])); 152 | } 153 | set { 154 | this["BackupFolderContent"] = value; 155 | } 156 | } 157 | 158 | [global::System.Configuration.UserScopedSettingAttribute()] 159 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 160 | [global::System.Configuration.DefaultSettingValueAttribute("")] 161 | public string BackupFolderBackup { 162 | get { 163 | return ((string)(this["BackupFolderBackup"])); 164 | } 165 | set { 166 | this["BackupFolderBackup"] = value; 167 | } 168 | } 169 | 170 | [global::System.Configuration.UserScopedSettingAttribute()] 171 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 172 | [global::System.Configuration.DefaultSettingValueAttribute("")] 173 | public string ExtractMode { 174 | get { 175 | return ((string)(this["ExtractMode"])); 176 | } 177 | set { 178 | this["ExtractMode"] = value; 179 | } 180 | } 181 | 182 | [global::System.Configuration.UserScopedSettingAttribute()] 183 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 184 | [global::System.Configuration.DefaultSettingValueAttribute("")] 185 | public string ConvertMode { 186 | get { 187 | return ((string)(this["ConvertMode"])); 188 | } 189 | set { 190 | this["ConvertMode"] = value; 191 | } 192 | } 193 | 194 | [global::System.Configuration.UserScopedSettingAttribute()] 195 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 196 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 197 | public bool ExtractAllowImages { 198 | get { 199 | return ((bool)(this["ExtractAllowImages"])); 200 | } 201 | set { 202 | this["ExtractAllowImages"] = value; 203 | } 204 | } 205 | 206 | [global::System.Configuration.UserScopedSettingAttribute()] 207 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 208 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 209 | public bool ExtractAllowSounds { 210 | get { 211 | return ((bool)(this["ExtractAllowSounds"])); 212 | } 213 | set { 214 | this["ExtractAllowSounds"] = value; 215 | } 216 | } 217 | 218 | [global::System.Configuration.UserScopedSettingAttribute()] 219 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 220 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 221 | public bool ExtractAllowWaveBank { 222 | get { 223 | return ((bool)(this["ExtractAllowWaveBank"])); 224 | } 225 | set { 226 | this["ExtractAllowWaveBank"] = value; 227 | } 228 | } 229 | 230 | [global::System.Configuration.UserScopedSettingAttribute()] 231 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 232 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 233 | public bool ExtractUseInput { 234 | get { 235 | return ((bool)(this["ExtractUseInput"])); 236 | } 237 | set { 238 | this["ExtractUseInput"] = value; 239 | } 240 | } 241 | 242 | [global::System.Configuration.UserScopedSettingAttribute()] 243 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 244 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 245 | public bool ConvertAllowImages { 246 | get { 247 | return ((bool)(this["ConvertAllowImages"])); 248 | } 249 | set { 250 | this["ConvertAllowImages"] = value; 251 | } 252 | } 253 | 254 | [global::System.Configuration.UserScopedSettingAttribute()] 255 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 256 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 257 | public bool ConvertAllowSounds { 258 | get { 259 | return ((bool)(this["ConvertAllowSounds"])); 260 | } 261 | set { 262 | this["ConvertAllowSounds"] = value; 263 | } 264 | } 265 | 266 | [global::System.Configuration.UserScopedSettingAttribute()] 267 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 268 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 269 | public bool ConvertUseInput { 270 | get { 271 | return ((bool)(this["ConvertUseInput"])); 272 | } 273 | set { 274 | this["ConvertUseInput"] = value; 275 | } 276 | } 277 | 278 | [global::System.Configuration.UserScopedSettingAttribute()] 279 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 280 | [global::System.Configuration.DefaultSettingValueAttribute("Extract")] 281 | public string CurrentTab { 282 | get { 283 | return ((string)(this["CurrentTab"])); 284 | } 285 | set { 286 | this["CurrentTab"] = value; 287 | } 288 | } 289 | 290 | [global::System.Configuration.UserScopedSettingAttribute()] 291 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 292 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 293 | public bool AutoCloseProgress { 294 | get { 295 | return ((bool)(this["AutoCloseProgress"])); 296 | } 297 | set { 298 | this["AutoCloseProgress"] = value; 299 | } 300 | } 301 | 302 | [global::System.Configuration.UserScopedSettingAttribute()] 303 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 304 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 305 | public bool AutoCloseDropProgress { 306 | get { 307 | return ((bool)(this["AutoCloseDropProgress"])); 308 | } 309 | set { 310 | this["AutoCloseDropProgress"] = value; 311 | } 312 | } 313 | 314 | [global::System.Configuration.UserScopedSettingAttribute()] 315 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 316 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 317 | public bool AutoCloseCmdProgress { 318 | get { 319 | return ((bool)(this["AutoCloseCmdProgress"])); 320 | } 321 | set { 322 | this["AutoCloseCmdProgress"] = value; 323 | } 324 | } 325 | 326 | [global::System.Configuration.UserScopedSettingAttribute()] 327 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 328 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 329 | public bool CompressImages { 330 | get { 331 | return ((bool)(this["CompressImages"])); 332 | } 333 | set { 334 | this["CompressImages"] = value; 335 | } 336 | } 337 | 338 | [global::System.Configuration.UserScopedSettingAttribute()] 339 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 340 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 341 | public bool CompletionSound { 342 | get { 343 | return ((bool)(this["CompletionSound"])); 344 | } 345 | set { 346 | this["CompletionSound"] = value; 347 | } 348 | } 349 | 350 | [global::System.Configuration.UserScopedSettingAttribute()] 351 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 352 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 353 | public bool ExtractAllowFonts { 354 | get { 355 | return ((bool)(this["ExtractAllowFonts"])); 356 | } 357 | set { 358 | this["ExtractAllowFonts"] = value; 359 | } 360 | } 361 | 362 | [global::System.Configuration.UserScopedSettingAttribute()] 363 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 364 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 365 | public bool PremultiplyAlpha { 366 | get { 367 | return ((bool)(this["PremultiplyAlpha"])); 368 | } 369 | set { 370 | this["PremultiplyAlpha"] = value; 371 | } 372 | } 373 | } 374 | } 375 | -------------------------------------------------------------------------------- /TConvert/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | True 49 | 50 | 51 | True 52 | 53 | 54 | True 55 | 56 | 57 | False 58 | 59 | 60 | True 61 | 62 | 63 | True 64 | 65 | 66 | False 67 | 68 | 69 | Extract 70 | 71 | 72 | False 73 | 74 | 75 | True 76 | 77 | 78 | True 79 | 80 | 81 | True 82 | 83 | 84 | False 85 | 86 | 87 | True 88 | 89 | 90 | True 91 | 92 | 93 | -------------------------------------------------------------------------------- /TConvert/Resources/Icons/About.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/About.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/AppError.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/AppError.ico -------------------------------------------------------------------------------- /TConvert/Resources/Icons/AutoClose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/AutoClose.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/Browse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/Browse.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/CloseCmdProgress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/CloseCmdProgress.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/CloseDropProgress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/CloseDropProgress.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/CloseProgress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/CloseProgress.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/Compression.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/Compression.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/Credits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/Credits.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/Empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/Empty.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/ErrorIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/ErrorIcon.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/Exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/Exit.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/Github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/Github.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/Help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/Help.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/InfoIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/InfoIcon.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/Premultiply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/Premultiply.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/QuestionIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/QuestionIcon.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/Sound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/Sound.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/TerrariaIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/TerrariaIcon.png -------------------------------------------------------------------------------- /TConvert/Resources/Icons/WarningIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Icons/WarningIcon.png -------------------------------------------------------------------------------- /TConvert/Resources/Logo112.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/Logo112.png -------------------------------------------------------------------------------- /TConvert/Resources/ffmpeg.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/ffmpeg.exe -------------------------------------------------------------------------------- /TConvert/Resources/xcompress32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trigger-segfault/TConvert/52cbabdbe7cda81a60f2f4ed31f4a71e8dec6043/TConvert/Resources/xcompress32.dll -------------------------------------------------------------------------------- /TConvert/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace TConvert { 10 | /**The class defining the entry point to the program.*/ 11 | static class Startup { 12 | //============= MAIN ============= 13 | #region Main 14 | 15 | /**The entry point to the program.*/ 16 | [STAThread] 17 | static void Main(string[] args) { 18 | #if !(CONSOLE) 19 | if (args.Length > 0) { 20 | AttachConsole(-1); 21 | CommandLine.ParseCommand(args); 22 | } 23 | if (args.Length == 0) { 24 | App app = new App(); 25 | app.InitializeComponent(); 26 | app.Run(new MainWindow()); 27 | } 28 | #else 29 | CommandLine.ParseCommand(args); 30 | #endif 31 | } 32 | 33 | [DllImport("kernel32.dll")] 34 | static extern bool AttachConsole(int pid); 35 | 36 | #endregion 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /TConvert/TConvert.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | WinDebug 6 | AnyCPU 7 | {A0490315-2780-4572-BBA1-F56A7C2A5901} 8 | Properties 9 | TConvert 10 | TConvert 11 | v4.5.2 12 | 512 13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 4 15 | true 16 | App.ico 17 | TConvert.Startup 18 | 19 | 20 | 21 | 22 | WinExe 23 | AnyCPU 24 | true 25 | full 26 | false 27 | bin\WinDebug\ 28 | DEBUG;TRACE 29 | prompt 30 | 4 31 | 32 | 33 | WinExe 34 | AnyCPU 35 | pdbonly 36 | true 37 | bin\WinRelease\ 38 | TRACE 39 | prompt 40 | 2 41 | 42 | 43 | Exe 44 | true 45 | bin\ConDebug\ 46 | TRACE;DEBUG;CONSOLE 47 | full 48 | AnyCPU 49 | prompt 50 | MinimumRecommendedRules.ruleset 51 | true 52 | 53 | 54 | Exe 55 | bin\ConRelease\ 56 | TRACE;CONSOLE 57 | true 58 | 2 59 | pdbonly 60 | AnyCPU 61 | prompt 62 | MinimumRecommendedRules.ruleset 63 | true 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 4.0 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | MSBuild:Compile 86 | Designer 87 | 88 | 89 | MSBuild:Compile 90 | Designer 91 | 92 | 93 | MSBuild:Compile 94 | Designer 95 | 96 | 97 | MSBuild:Compile 98 | Designer 99 | 100 | 101 | Designer 102 | MSBuild:Compile 103 | 104 | 105 | Designer 106 | MSBuild:Compile 107 | 108 | 109 | MSBuild:Compile 110 | Designer 111 | 112 | 113 | MSBuild:Compile 114 | Designer 115 | 116 | 117 | App.xaml 118 | Code 119 | 120 | 121 | MainWindow.xaml 122 | Code 123 | 124 | 125 | AboutWindow.xaml 126 | 127 | 128 | CreditsWindow.xaml 129 | 130 | 131 | ErrorLogWindow.xaml 132 | 133 | 134 | 135 | 136 | ProgressWindow.xaml 137 | 138 | 139 | ErrorMessageBox.xaml 140 | 141 | 142 | TriggerMessageBox.xaml 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | Code 170 | 171 | 172 | True 173 | True 174 | Resources.resx 175 | 176 | 177 | True 178 | Settings.settings 179 | True 180 | 181 | 182 | ResXFileCodeGenerator 183 | Resources.Designer.cs 184 | 185 | 186 | SettingsSingleFileGenerator 187 | Settings.Designer.cs 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | %(Filename)%(Extension) 244 | 245 | 246 | 247 | 248 | 249 | 250 | -------------------------------------------------------------------------------- /TConvert/Util/EmbeddedResources.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Runtime.InteropServices; 6 | using System.IO; 7 | using System.Reflection; 8 | using System.Diagnostics; 9 | using System.ComponentModel; 10 | 11 | namespace TConvert.Util { 12 | /**Extract embedded resources.*/ 13 | public static class EmbeddedResources { 14 | //========== EXTRACTING ========== 15 | #region Extracting 16 | 17 | /**Extract an embedded resource from byte array.*/ 18 | public static void Extract(string resourcePath, byte[] resourceBytes) { 19 | string dirName = Path.GetDirectoryName(resourcePath); 20 | if (!Directory.Exists(dirName)) { 21 | Directory.CreateDirectory(dirName); 22 | } 23 | 24 | bool rewrite = true; 25 | if (File.Exists(resourcePath)) { 26 | byte[] existing = File.ReadAllBytes(resourcePath); 27 | if (resourceBytes.SequenceEqual(existing)) { 28 | rewrite = false; 29 | } 30 | } 31 | if (rewrite) { 32 | File.WriteAllBytes(resourcePath, resourceBytes); 33 | } 34 | } 35 | /**Extract an embedded resource from stream.*/ 36 | public static void Extract(string resourcePath, Stream resourceStream) { 37 | byte[] resourceBytes = new byte[resourceStream.Length]; 38 | resourceStream.Read(resourceBytes, 0, resourceBytes.Length); 39 | 40 | Extract(resourcePath, resourceBytes); 41 | } 42 | /**Extract an embedded resource from name.*/ 43 | public static void Extract(string resourcePath, string resourceName) { 44 | Stream resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName); 45 | Extract(resourcePath, resourceStream); 46 | } 47 | 48 | #endregion 49 | //=========== LOADING ============ 50 | #region Loading 51 | 52 | /**Load a dll.*/ 53 | public static void LoadDll(string dllPath) { 54 | IntPtr h = LoadLibrary(dllPath); 55 | if (h == IntPtr.Zero) { 56 | Exception e = new Win32Exception(); 57 | throw new DllNotFoundException("Unable to load library: " + dllPath, e); 58 | } 59 | } 60 | 61 | #endregion 62 | //============ NATIVE ============ 63 | #region Native 64 | 65 | [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] 66 | static extern IntPtr LoadLibrary(string lpFileName); 67 | 68 | #endregion 69 | } 70 | } -------------------------------------------------------------------------------- /TConvert/Util/Helpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace TConvert.Util { 9 | /**A class of static helpers.*/ 10 | public static class Helpers { 11 | 12 | /**Gets the output path relative to the input path.*/ 13 | public static string GetOutputPath(string inputPath, string inputDirectory, string outputDirectory) { 14 | string fullPath = Path.GetFullPath(inputPath); 15 | return Path.Combine(outputDirectory, fullPath.Substring(Math.Min(fullPath.Length, inputDirectory.Length + 1))); 16 | } 17 | /**Gets the relative path based on the input directory.*/ 18 | public static string GetRelativePath(string path, string inputDirectory) { 19 | string fullPath = Path.GetFullPath(path); 20 | return fullPath.Substring(Math.Min(fullPath.Length, inputDirectory.Length + 1)); 21 | } 22 | /**Gets the output paths relative to the input path.*/ 23 | public static string[] GetOutputFiles(string[] inputFiles, string inputDirectory, string outputDirectory) { 24 | string[] outputFiles = new string[inputFiles.Length]; 25 | for (int i = 0; i < inputFiles.Length; i++) { 26 | outputFiles[i] = GetOutputPath(inputFiles[i], inputDirectory, outputDirectory); 27 | } 28 | return outputFiles; 29 | } 30 | 31 | /**Finds all files in a directory and subdirectories.*/ 32 | public static string[] FindAllFiles(string path, bool excludeCurrent = false) { 33 | List files = new List(); 34 | try { 35 | foreach (string directory in Directory.EnumerateDirectories(path)) { 36 | files.AddRange(FindAllFiles(directory)); 37 | } 38 | if (!excludeCurrent) 39 | files.AddRange(Directory.GetFiles(path)); 40 | } 41 | catch { } 42 | return files.ToArray(); 43 | } 44 | /**Gets the file count in a directory and subdirectories.*/ 45 | public static int GetFileCount(string path, bool excludeCurrent = false) { 46 | int count = 0; 47 | try { 48 | foreach (string directory in Directory.EnumerateDirectories(path)) { 49 | count += GetFileCount(directory); 50 | } 51 | if (!excludeCurrent) 52 | count += Directory.GetFiles(path).Length; 53 | } 54 | catch { } 55 | return count; 56 | } 57 | 58 | /**Safely attempts to create a directory.*/ 59 | public static void CreateDirectorySafe(string directory) { 60 | try { 61 | if (!Directory.Exists(directory)) { 62 | Directory.CreateDirectory(directory); 63 | } 64 | } 65 | catch { } 66 | } 67 | /**Safely gets the full path.*/ 68 | public static string FixPathSafe(string path) { 69 | try { 70 | path = Path.GetFullPath(path); 71 | if (path != string.Empty && (path.Last() == '\\' || path.Last() == '/')) 72 | path = path.Remove(path.Length - 1); 73 | return path; 74 | } 75 | catch { 76 | return ""; 77 | } 78 | } 79 | /**Safely tests if a directory exists.*/ 80 | public static bool DirectoryExistsSafe(string path) { 81 | try { 82 | if (Directory.Exists(path)) 83 | return true; 84 | } 85 | catch { } 86 | return false; 87 | } 88 | /**Safely tests if a file exists.*/ 89 | public static bool FileExistsSafe(string path) { 90 | try { 91 | if (File.Exists(path)) 92 | return true; 93 | } 94 | catch { } 95 | return false; 96 | } 97 | /**Safely tests if a file exists.*/ 98 | public static bool IsPathValid(string path) { 99 | try { 100 | Path.GetFullPath(path); 101 | return true; 102 | } 103 | catch { 104 | return false; 105 | } 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /TConvert/Util/TerrariaLocator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Xml; 8 | using Microsoft.Win32; 9 | 10 | namespace TConvert.Util { 11 | /**Finds the Terraria Content folder.*/ 12 | public static class TerrariaLocator { 13 | //=========== MEMBERS ============ 14 | #region Members 15 | 16 | /**The located or empty Terraria Content folder.*/ 17 | public static readonly string TerrariaContentDirectory; 18 | /**The path to Terra Launcher's configuration file.*/ 19 | public static readonly string TerraLauncherConfigPath; 20 | 21 | #endregion 22 | //========= CONSTRUCTORS ========= 23 | #region Constructors 24 | 25 | /**Start looking for the Terraria Content folder.*/ 26 | static TerrariaLocator() { 27 | TerrariaContentDirectory = FindTerrariaContentDirectory(); 28 | } 29 | 30 | #endregion 31 | //========== SAVE PATHS ========== 32 | #region Save Paths 33 | 34 | /**Reads the specified executable's selected save directory from Terra Launcher's config.*/ 35 | public static string FindTerraLauncherSaveDirectory(string exePath) { 36 | string arguments = ""; 37 | if (!string.IsNullOrWhiteSpace(TerraLauncherConfigPath)) { 38 | string oldCurrentDirectory = Directory.GetCurrentDirectory(); 39 | try { 40 | // Set the current directory for relative paths 41 | Directory.SetCurrentDirectory(Path.GetDirectoryName(TerraLauncherConfigPath)); 42 | 43 | exePath = Path.GetFullPath(exePath).ToLower(); 44 | 45 | XmlDocument doc = new XmlDocument(); 46 | doc.Load(TerraLauncherConfigPath); 47 | 48 | // Check if the user disable Trigger Tool Integration 49 | bool boolValue; 50 | XmlNode integration = doc.SelectSingleNode("TerraLauncher/Integration"); 51 | if (integration != null && bool.TryParse(integration.InnerText, out boolValue) && boolValue) { 52 | XmlNode gamesNode = doc.SelectSingleNode("TerraLauncher/Games"); 53 | if (gamesNode != null) { 54 | string result = ReadConfigFolder(exePath, gamesNode); 55 | if (!string.IsNullOrWhiteSpace(result)) 56 | arguments = "-savedirectory \"" + result + "\""; 57 | } 58 | } 59 | } 60 | catch { } 61 | // Set the current directory back 62 | Directory.SetCurrentDirectory(oldCurrentDirectory); 63 | } 64 | return arguments; 65 | } 66 | /**Reads a Terra Launcher config folder and returns the save directory.*/ 67 | private static string ReadConfigFolder(string exePath, XmlNode folderNode) { 68 | XmlNodeList nodeList = folderNode.SelectNodes("Folder"); 69 | foreach (XmlNode node in nodeList) { 70 | string result = ReadConfigFolder(exePath, node); 71 | if (!string.IsNullOrWhiteSpace(result)) 72 | return result; 73 | } 74 | 75 | nodeList = folderNode.SelectNodes("Game"); 76 | 77 | foreach (XmlNode node in folderNode) { 78 | string result = null; 79 | if (node.Name == "Folder") { 80 | result = ReadConfigFolder(exePath, node); 81 | } 82 | else if (node.Name == "Game") { 83 | XmlNode exeNode = node.SelectSingleNode("ExePath"); 84 | if (exeNode != null && Path.GetFullPath(exeNode.InnerText).ToLower() == exePath) { 85 | XmlNode saveNode = node.SelectSingleNode("SaveDirectory"); 86 | if (saveNode != null && !string.IsNullOrWhiteSpace(saveNode.InnerText)) 87 | return saveNode.InnerText; 88 | } 89 | } 90 | if (!string.IsNullOrWhiteSpace(result)) 91 | return result; 92 | } 93 | foreach (XmlNode node in nodeList) { 94 | XmlNode exeNode = node.SelectSingleNode("ExePath"); 95 | if (exeNode != null && Path.GetFullPath(exeNode.InnerText).ToLower() == exePath) { 96 | XmlNode saveNode = node.SelectSingleNode("SaveDirectory"); 97 | if (saveNode != null && !string.IsNullOrWhiteSpace(saveNode.InnerText)) 98 | return saveNode.InnerText; 99 | } 100 | } 101 | return null; 102 | } 103 | 104 | #endregion 105 | //=========== LOCATORS =========== 106 | #region Locators 107 | 108 | /**Starts looking for the Terra Launcher config path.*/ 109 | private static string FindConfigPath() { 110 | return Registry.GetValue("HKEY_CURRENT_USER\\Software\\TriggersToolsGames\\TerraLauncher", "ConfigPath", null) as string; 111 | } 112 | /**Starts looking for the Terraria Content folder.*/ 113 | private static string FindTerrariaContentDirectory() { 114 | try { 115 | // Check the windows registry for steam installation path 116 | string steamPath = Registry.GetValue("HKEY_CURRENT_USER\\Software\\Valve\\Steam", "SteamPath", null) as string; 117 | string result = SeekDirectory(steamPath); 118 | if (result != null) { 119 | return result; 120 | } 121 | } 122 | catch { } 123 | try { 124 | // Try to find relevant environment variables 125 | foreach (KeyValuePair envVar in Environment.GetEnvironmentVariables()) { 126 | string result = null; 127 | if (envVar.Key.ToLower().Contains("terraria") || 128 | envVar.Key.ToLower().Contains("tapi")) { 129 | result = SeekDirectory(envVar.Value); 130 | } 131 | else if (envVar.Key.ToLower().Contains("steam")) { 132 | result = SeekDirectory(envVar.Value); 133 | } 134 | if (result != null) { 135 | return result; 136 | } 137 | } 138 | } 139 | catch { } 140 | 141 | // If nothing other works, then prompt the user 142 | return null; 143 | } 144 | 145 | /**Seeks a directory for the Terraria Content folder.*/ 146 | private static string SeekDirectory(string steamDirectory) { 147 | if (steamDirectory == null || !Directory.Exists(steamDirectory)) { 148 | return null; 149 | } 150 | 151 | string path = Path.Combine(steamDirectory, "SteamApps", "Common", "Terraria", "Content"); 152 | if (Directory.Exists(path)) { 153 | path = GetProperDirectoryCapitalization(new DirectoryInfo(path)); 154 | if (path.Length >= 2 && path[1] == ':') { 155 | path = char.ToUpper(path[0]) + path.Substring(1); 156 | return path; 157 | } 158 | } 159 | return null; 160 | } 161 | 162 | #endregion 163 | //=========== HELPERS ============ 164 | #region Helpers 165 | 166 | /**Gets the proper capitalization of a path so it looks nice.*/ 167 | private static string GetProperDirectoryCapitalization(DirectoryInfo dirInfo) { 168 | DirectoryInfo parentDirInfo = dirInfo.Parent; 169 | if (null == parentDirInfo) 170 | return dirInfo.Name; 171 | return Path.Combine(GetProperDirectoryCapitalization(parentDirInfo), 172 | parentDirInfo.GetDirectories(dirInfo.Name)[0].Name); 173 | } 174 | /**Recursively gets the proper capitalization of a path so it looks nice.*/ 175 | private static string GetProperFilePathCapitalization(string filename) { 176 | FileInfo fileInfo = new FileInfo(filename); 177 | DirectoryInfo dirInfo = fileInfo.Directory; 178 | return Path.Combine(GetProperDirectoryCapitalization(dirInfo), 179 | dirInfo.GetFiles(fileInfo.Name)[0].Name); 180 | } 181 | 182 | #endregion 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /TConvert/Util/Xnb.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace TConvert.Util { 9 | /**Xnb extensions for binary readers and writers.*/ 10 | public static class XnbExtensions { 11 | /**Reads an Xnb 7-bit encoded int.*/ 12 | public static int Read7BitEncodedInt(this BinaryReader reader) { 13 | int result = 0; 14 | int bitsRead = 0; 15 | int value; 16 | 17 | do { 18 | value = reader.ReadByte(); 19 | result |= (value & 0x7f) << bitsRead; 20 | bitsRead += 7; 21 | } while ((value & 0x80) != 0); 22 | 23 | return result; 24 | } 25 | /**Reads an Xnb 7-bit encoded string.*/ 26 | public static String Read7BitEncodedString(this BinaryReader reader) { 27 | int length = reader.Read7BitEncodedInt(); 28 | return Encoding.UTF8.GetString(reader.ReadBytes(length)); 29 | } 30 | /**Writes an Xnb 7-bit encoded int.*/ 31 | public static void Write7BitEncodedInt(this BinaryWriter writer, int i) { 32 | while (i >= 0x80) { 33 | writer.Write((byte)(i & 0xff)); 34 | i >>= 7; 35 | } 36 | writer.Write((byte)i); 37 | } 38 | /**Writes an Xnb 7-bit encoded string.*/ 39 | public static void Write7BitEncodedString(this BinaryWriter writer, string s) { 40 | writer.Write7BitEncodedInt(s.Length); 41 | writer.Write(Encoding.UTF8.GetBytes(s)); 42 | } 43 | /**Fills an array with a value.*/ 44 | public static void Fill(this T[] array, T with) { 45 | for (int i = 0; i < array.Length; i++) { 46 | array[i] = with; 47 | } 48 | } 49 | /**Checks if a byte array matches a string.*/ 50 | public static bool ReadAndCompareString(this BinaryReader reader, string s) { 51 | byte[] stringData = Encoding.UTF8.GetBytes(s); 52 | byte[] data = reader.ReadBytes(stringData.Length); 53 | if (data.Length != stringData.Length) 54 | return false; 55 | for (int i = 0; i < data.Length; i++) { 56 | if (data[i] != stringData[i]) 57 | return false; 58 | } 59 | return true; 60 | } 61 | } 62 | 63 | /**An exception thrown during Xnb extraction.*/ 64 | public class XnbException : Exception { 65 | public XnbException(string message) : base(message) { } 66 | public XnbException(string message, Exception innerException) 67 | : base(message, innerException) { } 68 | } 69 | /**An exception thrown during Wave Bank extraction.*/ 70 | public class XwbException : Exception { 71 | public XwbException(string message) : base(message) { } 72 | public XwbException(string message, Exception innerException) 73 | : base(message, innerException) { } 74 | } 75 | /**An exception thrown during Xnb to Png conversion.*/ 76 | public class PngException : Exception { 77 | public PngException(string message) : base(message) { } 78 | public PngException(string message, Exception innerException) 79 | : base(message, innerException) { } 80 | } 81 | /**An exception thrown during Xnb to Wav conversion.*/ 82 | public class WavException : Exception { 83 | public WavException(string message) : base(message) { } 84 | public WavException(string message, Exception innerException) 85 | : base(message, innerException) { } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /TConvert/Windows/AboutWindow.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 31 | 32 | 33 | 34 | 35 |