├── .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 
 2 | 
 3 | [](https://github.com/trigger-death/TConvert/releases/latest)
 4 | [](https://github.com/trigger-death/TConvert/releases/latest)
 5 | [](https://github.com/trigger-death/TConvert/releases)
 6 | [](https://github.com/trigger-death/TConvert/commit/81d10e01975c1974f73ee90089fa30d85e71370e)
 7 | [](https://forums.terraria.org/index.php?threads/61706/)
 8 | [](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 | 
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 | ### [](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 |                 
22 |                 
23 |                 
26 |                 
27 |                 
28 |                 
29 |                 
30 |             
31 |         
32 |         
33 |             
34 |         
35 |         
36 | 
37 |     
38 | 
39 | 
--------------------------------------------------------------------------------
/TConvert/Windows/AboutWindow.xaml.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 | using System.Windows;
 9 | using System.Windows.Controls;
10 | using System.Windows.Data;
11 | using System.Windows.Documents;
12 | using System.Windows.Input;
13 | using System.Windows.Media;
14 | using System.Windows.Media.Imaging;
15 | using System.Windows.Shapes;
16 | 
17 | namespace TConvert.Windows {
18 | 	/**The window showing information about the program.*/
19 | 	public partial class AboutWindow : Window {
20 | 		//========= CONSTRUCTORS =========
21 | 		#region Constructors
22 | 
23 | 		/**Constructs the about window.*/
24 | 		public AboutWindow() {
25 | 			InitializeComponent();
26 | 
27 | 			DateTime buildDate = GetLinkerTime(Assembly.GetExecutingAssembly());
28 | 			this.labelVersion.Content = Assembly.GetExecutingAssembly().GetName().Version.ToString() + " Release";
29 | 			this.labelBuildDate.Content = buildDate.ToShortDateString() + " (" + buildDate.ToShortTimeString() + ")";
30 | 		}
31 | 
32 | 		#endregion
33 | 		//=========== HELPERS ============
34 | 		#region Helpers
35 | 
36 | 		/**Gets the build date of the program.*/
37 | 		private DateTime GetLinkerTime(Assembly assembly, TimeZoneInfo target = null) {
38 | 			var filePath = assembly.Location;
39 | 			const int c_PeHeaderOffset = 60;
40 | 			const int c_LinkerTimestampOffset = 8;
41 | 
42 | 			var buffer = new byte[2048];
43 | 
44 | 			using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
45 | 				stream.Read(buffer, 0, 2048);
46 | 
47 | 			var offset = BitConverter.ToInt32(buffer, c_PeHeaderOffset);
48 | 			var secondsSince1970 = BitConverter.ToInt32(buffer, offset + c_LinkerTimestampOffset);
49 | 			var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
50 | 
51 | 			var linkTimeUtc = epoch.AddSeconds(secondsSince1970);
52 | 
53 | 			var tz = target ?? TimeZoneInfo.Local;
54 | 			var localTime = TimeZoneInfo.ConvertTimeFromUtc(linkTimeUtc, tz);
55 | 
56 | 			return localTime;
57 | 		}
58 | 
59 | 		#endregion
60 | 		//============ EVENTS ============
61 | 		#region Events
62 | 
63 | 		private void OnWindowLoaded(object sender, RoutedEventArgs e) {
64 | 			clientArea.Height = 214 + textBlockDescription.ActualHeight;
65 | 		}
66 | 
67 | 		#endregion
68 | 		//=========== SHOWING ============
69 | 		#region Showing
70 | 
71 | 		/**Shows the window.*/
72 | 		public static void Show(Window owner) {
73 | 			AboutWindow window = new AboutWindow();
74 | 			window.Owner = owner;
75 | 			window.ShowDialog();
76 | 		}
77 | 
78 | 		#endregion
79 | 	}
80 | }
81 | 
--------------------------------------------------------------------------------
/TConvert/Windows/CreditsWindow.xaml:
--------------------------------------------------------------------------------
 1 | 
 6 | 
 7 |     
 8 |         
 9 |             
10 |                 Image/Sound extraction capabilities thanks to  TExtract.
11 |             
12 |             
13 |                 
14 |                     
15 |                         
16 |                         
17 |                     
18 |                 
19 |             
20 | 
21 |             
22 |                 Wave conversion thanks to  WAVToXNBSoundConverter.
23 |             
24 |             
25 |                 
26 |                     
27 |                         
28 |                         
29 |                     
30 |                 
31 |             
32 | 
33 |             
34 |                 Png conversion thanks to  png_to_xnb.
35 |             
36 |             
37 |                 
38 |                     
39 |                         
40 |                         
41 |                     
42 |                 
43 |             
44 | 
45 |             
46 |                 Font extraction thanks to  FNA-XNA.
47 |             
48 |             
49 |                 
50 |                     
51 |                         
52 |                         
53 |                     
54 |                 
55 |             
56 |             
57 |             
58 |                 Wave bank song conversion thanks to FFmpeg, which is under GNU Lesser General Public License version 2.1.
59 |             
60 |             
61 |                 
62 |                     
63 |                         
64 |                         
65 |                     
66 |                 
67 |             
68 | 
69 |             
70 |                 Most icons from or modified from Fugue Icon Pack.
71 |             
72 |         
73 | 
74 |         
75 |     
76 | 
77 | 
--------------------------------------------------------------------------------
/TConvert/Windows/CreditsWindow.xaml.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.Diagnostics;
 3 | using System.Windows;
 4 | using System.Windows.Documents;
 5 | using System.Windows.Navigation;
 6 | 
 7 | namespace TConvert.Windows {
 8 | 	/**A window to display credits for the program.*/
 9 | 	public partial class CreditsWindow : Window {
10 | 		//========= CONSTRUCTORS =========
11 | 		#region Constructors
12 | 
13 | 		/**Constructs the credits window.*/
14 | 		public CreditsWindow() {
15 | 			InitializeComponent();
16 | 		}
17 | 
18 | 		#endregion
19 | 		//============ EVENTS ============
20 | 		#region Events
21 | 
22 | 		private void OnRequestNavigate(object sender, RequestNavigateEventArgs e) {
23 | 			Process.Start((sender as Hyperlink).NavigateUri.ToString());
24 | 		}
25 | 
26 | 		#endregion
27 | 		//=========== SHOWING ============
28 | 		#region Showing
29 | 
30 | 		/**Shows the credits window.*/
31 | 		public static void Show(Window owner) {
32 | 			CreditsWindow window = new CreditsWindow();
33 | 			window.Owner = owner;
34 | 			window.ShowDialog();
35 | 		}
36 | 
37 | 		#endregion
38 | 	}
39 | }
40 | 
--------------------------------------------------------------------------------
/TConvert/Windows/ErrorLogWindow.xaml:
--------------------------------------------------------------------------------
 1 | 
10 |     
11 |         
12 |     
13 |     
14 |         
17 | 
18 |         
19 |             
20 |                 
21 |             
22 |         
23 | 
24 |         
25 |         
26 |         
27 |         
28 |         
29 |     
30 | 
31 | 
--------------------------------------------------------------------------------
/TConvert/Windows/ErrorLogWindow.xaml.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.Collections.Generic;
 3 | using System.Diagnostics;
 4 | using System.Linq;
 5 | using System.Text;
 6 | using System.Threading.Tasks;
 7 | using System.Windows;
 8 | using System.Windows.Controls;
 9 | using System.Windows.Data;
10 | using System.Windows.Documents;
11 | using System.Windows.Input;
12 | using System.Windows.Media;
13 | using System.Windows.Media.Imaging;
14 | using System.Windows.Shapes;
15 | using System.Windows.Shell;
16 | 
17 | namespace TConvert.Windows {
18 | 	/**The log window for showing errors that occurred during file processing.*/
19 | 	public partial class ErrorLogWindow : Window {
20 | 		//=========== MEMBERS ============
21 | 		#region Members
22 | 
23 | 		/**The number of lines written so far.*/
24 | 		int lines;
25 | 
26 | 		#endregion
27 | 		//========= CONSTRUCTORS =========
28 | 		#region Constructors
29 | 
30 | 		/**Constructs and sets up the error log window.*/
31 | 		private ErrorLogWindow(LogError[] errors) {
32 | 			InitializeComponent();
33 | 
34 | 			lines = 0;
35 | 			textBlockMessage.Text = "";
36 | 			foreach (LogError log in errors) {
37 | 				if (lines >= 300) {
38 | 					textBlockMessage.Inlines.Add(new Run("Issues continued in log file..."));
39 | 					textBlockMessage.Inlines.Add(new LineBreak());
40 | 					break;
41 | 				}
42 | 				AddError(log);
43 | 			}
44 | 		}
45 | 
46 | 		#endregion
47 | 		//=========== HELPERS ============
48 | 		#region Helpers
49 | 
50 | 		/**Adds an error.*/
51 | 		private void AddError(LogError log) {
52 | 			Run run = new Run((log.IsWarning ? "Warning: " : "Error: ") + log.Message);
53 | 			ColorRun(log.IsWarning, run);
54 | 			textBlockMessage.Inlines.Add(run);
55 | 			textBlockMessage.Inlines.Add(new LineBreak());
56 | 			lines++;
57 | 			if (log.Reason != String.Empty) {
58 | 				run = new Run("    Reason: " + log.Reason);
59 | 				ColorRun(log.IsWarning, run);
60 | 				textBlockMessage.Inlines.Add(run);
61 | 				textBlockMessage.Inlines.Add(new LineBreak());
62 | 				lines++;
63 | 			}
64 | 		}
65 | 		/**Adds a Run with color based on if it is a warning or error.*/
66 | 		private void ColorRun(bool isWarning, Run run) {
67 | 			if (isWarning)
68 | 				run.Foreground = new SolidColorBrush(Colors.Orange);
69 | 			else
70 | 				run.Foreground = new SolidColorBrush(Colors.Red);
71 | 		}
72 | 
73 | 		#endregion
74 | 		//============ EVENTS ============
75 | 		#region Events
76 | 
77 | 		private void OnOpenLogFile(object sender, RoutedEventArgs e) {
78 | 			Process.Start(ErrorLogger.LogPath);
79 | 		}
80 | 
81 | 		#endregion
82 | 		//=========== SHOWING ============
83 | 		#region Showing
84 | 
85 | 		public static void Show(Window owner, LogError[] errors) {
86 | 			ErrorLogWindow window = new ErrorLogWindow(errors);
87 | 			if (owner == null || owner.Visibility != Visibility.Visible)
88 | 				window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
89 | 			else
90 | 				window.Owner = owner;
91 | 			window.ShowDialog();
92 | 		}
93 | 
94 | 		#endregion
95 | 	}
96 | }
97 | 
--------------------------------------------------------------------------------
/TConvert/Windows/ErrorMessageBox.xaml:
--------------------------------------------------------------------------------
 1 | 
 5 | 
 6 |     
 7 |         
10 |         
15 | 
16 |         
17 |             
18 |                 
19 |             
20 |         
21 | 
22 |         
23 |         
24 | 
25 |         
26 |         
27 |         
28 |             
29 |             
30 |         
31 |     
32 | 
33 | 
--------------------------------------------------------------------------------
/TConvert/Windows/ErrorMessageBox.xaml.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.Diagnostics;
  3 | using System.Timers;
  4 | using System.Windows;
  5 | using System.Windows.Documents;
  6 | using System.Windows.Input;
  7 | using System.Windows.Navigation;
  8 | 
  9 | namespace TConvert.Windows {
 10 | 	/**Shows an error that occured in the program.*/
 11 | 	public partial class ErrorMessageBox : Window {
 12 | 		//=========== MEMBERS ============
 13 | 		#region Members
 14 | 
 15 | 		/**The exception that was raised.*/
 16 | 		private Exception exception = null;
 17 | 		/**The non-exception object that was raised.*/
 18 | 		private object exceptionObject = null;
 19 | 		/**True if viewing the full exception.*/
 20 | 		private bool viewingFull = false;
 21 | 		/**The timer for changing the copy button back to its original text.*/
 22 | 		private Timer copyTimer = new Timer(1000);
 23 | 		/**The text of the copy to clipboard button.*/
 24 | 		private readonly string copyText;
 25 | 
 26 | 		#endregion
 27 | 		//========= CONSTRUCTORS =========
 28 | 		#region Constructors
 29 | 
 30 | 		/**Constructs the error message box with an exception.*/
 31 | 		public ErrorMessageBox(Exception exception, bool alwaysContinue) {
 32 | 			InitializeComponent();
 33 | 
 34 | 			this.textBlockMessage.Text = "Exception:\n" + exception.Message;
 35 | 			this.exception = exception;
 36 | 			this.copyTimer.Elapsed += OnCopyTimer;
 37 | 			this.copyTimer.AutoReset = false;
 38 | 			this.copyText = buttonCopy.Content as string;
 39 | 			if (alwaysContinue) {
 40 | 				this.buttonExit.Visibility = Visibility.Collapsed;
 41 | 				this.buttonContinue.IsDefault = true;
 42 | 			}
 43 | 		}
 44 | 		/**Constructs the error message box with an exception object.*/
 45 | 		public ErrorMessageBox(object exceptionObject, bool alwaysContinue) {
 46 | 			InitializeComponent();
 47 | 
 48 | 			this.textBlockMessage.Text = "Exception:\n" + (exceptionObject is Exception ? (exceptionObject as Exception).Message : exceptionObject.ToString());
 49 | 			this.exception = (exceptionObject is Exception ? exceptionObject as Exception : null);
 50 | 			this.exceptionObject = (exceptionObject is Exception ? null : exceptionObject);
 51 | 			this.copyTimer.Elapsed += OnCopyTimer;
 52 | 			this.copyTimer.AutoReset = false;
 53 | 			this.copyText = buttonCopy.Content as string;
 54 | 			if (!(exceptionObject is Exception)) {
 55 | 				this.buttonException.IsEnabled = false;
 56 | 			}
 57 | 			if (alwaysContinue) {
 58 | 				this.buttonExit.Visibility = Visibility.Collapsed;
 59 | 				this.buttonContinue.IsDefault = true;
 60 | 			}
 61 | 		}
 62 | 
 63 | 
 64 | 		#endregion
 65 | 		//============ EVENTS ============
 66 | 		#region Events
 67 | 
 68 | 		private void OnWindowClosing(object sender, System.ComponentModel.CancelEventArgs e) {
 69 | 			copyTimer.Stop();
 70 | 		}
 71 | 		private void OnExit(object sender, RoutedEventArgs e) {
 72 | 			DialogResult = true;
 73 | 			Close();
 74 | 		}
 75 | 		private void OnCopyTimer(object sender, ElapsedEventArgs e) {
 76 | 			Dispatcher.Invoke(() => {
 77 | 				buttonCopy.Content = copyText;
 78 | 			});
 79 | 		}
 80 | 		private void OnCopyToClipboard(object sender, RoutedEventArgs e) {
 81 | 			Clipboard.SetText(exception != null ? exception.ToString() : exceptionObject.ToString());
 82 | 			buttonCopy.Content = "Exception Copied!";
 83 | 			copyTimer.Stop();
 84 | 			copyTimer.Start();
 85 | 		}
 86 | 		private void OnSeeFullException(object sender, RoutedEventArgs e) {
 87 | 			viewingFull = !viewingFull;
 88 | 			if (!viewingFull) {
 89 | 				buttonException.Content = "See Full Exception";
 90 | 				textBlockMessage.Text = "Exception:\n" + exception.Message;
 91 | 				clientArea.Height = 230;
 92 | 				scrollViewer.ScrollToTop();
 93 | 			}
 94 | 			else {
 95 | 				buttonException.Content = "Hide Full Exception";
 96 | 				// Size may not be changed yet so just incase we also have OnMessageSizeChanged
 97 | 				textBlockMessage.Text = "Exception:\n" + exception.ToString();
 98 | 				clientArea.Height = Math.Min(480, Math.Max(230, textBlockMessage.ActualHeight + 102));
 99 | 				scrollViewer.ScrollToTop();
100 | 			}
101 | 		}
102 | 		private void OnMessageSizeChanged(object sender, SizeChangedEventArgs e) {
103 | 			if (viewingFull) {
104 | 				clientArea.Height = Math.Min(480, Math.Max(230, textBlockMessage.ActualHeight + 102));
105 | 				scrollViewer.ScrollToTop();
106 | 			}
107 | 		}
108 | 		private void OnPreviewKeyDown(object sender, KeyEventArgs e) {
109 | 			var focused = FocusManager.GetFocusedElement(this);
110 | 			switch (e.Key) {
111 | 			case Key.Right:
112 | 				if (focused == buttonContinue && buttonExit.Visibility == Visibility.Visible)
113 | 					buttonExit.Focus();
114 | 				else if (focused == buttonCopy)
115 | 					buttonContinue.Focus();
116 | 				else if (focused == buttonException)
117 | 					buttonCopy.Focus();
118 | 				e.Handled = true;
119 | 				break;
120 | 			case Key.Left:
121 | 				if (focused == null) {
122 | 					if (buttonExit.Visibility == Visibility.Visible)
123 | 						buttonContinue.Focus();
124 | 					else
125 | 						buttonCopy.Focus();
126 | 				}
127 | 				else if (focused == buttonExit)
128 | 					buttonContinue.Focus();
129 | 				else if (focused == buttonContinue)
130 | 					buttonCopy.Focus();
131 | 				else if (focused == buttonCopy && buttonException.IsEnabled)
132 | 					buttonException.Focus();
133 | 				e.Handled = true;
134 | 				break;
135 | 			}
136 | 		}
137 | 		private void OnRequestNavigate(object sender, RequestNavigateEventArgs e) {
138 | 			Process.Start((sender as Hyperlink).NavigateUri.ToString());
139 | 		}
140 | 
141 | 		#endregion
142 | 		//=========== SHOWING ============
143 | 		#region Showing
144 | 
145 | 		/**Shows an error message box with an exception.*/
146 | 		public static bool Show(Exception exception, bool alwaysContinue = false) {
147 | 			ErrorMessageBox messageBox = new ErrorMessageBox(exception, alwaysContinue);
148 | 			var result = messageBox.ShowDialog();
149 | 			return result.HasValue && result.Value;
150 | 		}
151 | 		/**Shows an error message box with an exception object.*/
152 | 		public static bool Show(object exceptionObject, bool alwaysContinue = false) {
153 | 			ErrorMessageBox messageBox = new ErrorMessageBox(exceptionObject, alwaysContinue);
154 | 			var result = messageBox.ShowDialog();
155 | 			return result.HasValue && result.Value;
156 | 		}
157 | 
158 | 		#endregion
159 | 	}
160 | }
161 | 
--------------------------------------------------------------------------------
/TConvert/Windows/FlashWindow.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.Tasks;
 7 | using System.Windows;
 8 | using System.Windows.Interop;
 9 | 
10 | namespace TConvert.Windows {
11 | 	//https://stackoverflow.com/questions/5118226/how-to-make-a-wpf-window-to-blink-on-the-taskbar
12 | 	public static class FlashWindow {
13 | 		private const UInt32 FLASHW_STOP = 0; //Stop flashing. The system restores the window to its original state.        private const UInt32 FLASHW_CAPTION = 1; //Flash the window caption.        
14 | 		private const UInt32 FLASHW_TRAY = 2; //Flash the taskbar button.        
15 | 		private const UInt32 FLASHW_ALL = 3; //Flash both the window caption and taskbar button.        
16 | 		private const UInt32 FLASHW_TIMER = 4; //Flash continuously, until the FLASHW_STOP flag is set.        
17 | 		private const UInt32 FLASHW_TIMERNOFG = 12; //Flash continuously until the window comes to the foreground.  
18 | 		
19 | 		[StructLayout(LayoutKind.Sequential)]
20 | 		private struct FLASHWINFO {
21 | 			public uint cbSize; //The size of the structure in bytes.            
22 | 			public IntPtr hwnd; //A Handle to the Window to be Flashed. The window can be either opened or minimized.
23 | 
24 | 
25 | 			public uint dwFlags; //The Flash Status.            
26 | 			public uint uCount; // number of times to flash the window            
27 | 			public uint dwTimeout; //The rate at which the Window is to be flashed, in milliseconds. If Zero, the function uses the default cursor blink rate.        
28 | 		}
29 | 
30 | 		[DllImport("user32.dll")]
31 | 		[return: MarshalAs(UnmanagedType.Bool)]
32 | 		private static extern bool FlashWindowEx(ref FLASHWINFO pwfi);
33 | 
34 | 		[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
35 | 		private static extern IntPtr GetForegroundWindow();
36 | 
37 | 		public static void Flash(this Window win, uint count = uint.MaxValue) {
38 | 			WindowInteropHelper h = new WindowInteropHelper(win);
39 | 			if (GetForegroundWindow() == h.Handle) return;
40 | 			FLASHWINFO info = new FLASHWINFO
41 | 			{
42 | 				cbSize = System.Convert.ToUInt32(Marshal.SizeOf(typeof(FLASHWINFO))),
43 | 				hwnd = h.Handle,
44 | 				dwFlags = FLASHW_ALL | FLASHW_TIMERNOFG,
45 | 				uCount = count,
46 | 				dwTimeout = 0
47 | 			};
48 | 		
49 | 			FlashWindowEx(ref info);
50 | 		}
51 | 
52 | 		public static void StopFlashing(this Window win) {
53 | 			WindowInteropHelper h = new WindowInteropHelper(win);
54 | 			FLASHWINFO info = new FLASHWINFO();
55 | 			info.hwnd = h.Handle;
56 | 			info.cbSize = System.Convert.ToUInt32(Marshal.SizeOf(info));
57 | 			info.dwFlags = FLASHW_STOP;
58 | 			info.uCount = UInt32.MaxValue;
59 | 			info.dwTimeout = 0;
60 | 			FlashWindowEx(ref info);
61 | 		}
62 | 	}
63 | }
64 | 
--------------------------------------------------------------------------------
/TConvert/Windows/FolderBrowserLauncher.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.Runtime.InteropServices;
  3 | using System.Windows.Forms;
  4 | 
  5 | namespace TConvert.Windows {
  6 | 	//https://stackoverflow.com/questions/6942150/why-folderbrowserdialog-dialog-does-not-scroll-to-selected-folder
  7 | 	/**Launch a folder browser and make sure it scrolls to the selected folder open opening.*/
  8 | 	public static class FolderBrowserLauncher {
  9 | 		/// 
 10 | 		/// Using title text to look for the top level dialog window is fragile.
 11 | 		/// In particular, this will fail in non-English applications.
 12 | 		/// 
 13 | 		const string _topLevelSearchString = "Browse For Folder";
 14 | 
 15 | 		/// 
 16 | 		/// These should be more robust.  We find the correct child controls in the dialog
 17 | 		/// by using the GetDlgItem method, rather than the FindWindow(Ex) method,
 18 | 		/// because the dialog item IDs should be constant.
 19 | 		/// 
 20 | 		const int _dlgItemBrowseControl = 0;
 21 | 		const int _dlgItemTreeView = 100;
 22 | 
 23 | 		[DllImport("user32.dll", SetLastError = true)]
 24 | 		static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
 25 | 
 26 | 		[DllImport("user32.dll")]
 27 | 		static extern IntPtr GetDlgItem(IntPtr hDlg, int nIDDlgItem);
 28 | 
 29 | 		[DllImport("user32.dll", CharSet = CharSet.Auto)]
 30 | 		static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
 31 | 
 32 | 		/// 
 33 | 		/// Some of the messages that the Tree View control will respond to
 34 | 		/// 
 35 | 		private const int TV_FIRST = 0x1100;
 36 | 		private const int TVM_SELECTITEM = (TV_FIRST + 11);
 37 | 		private const int TVM_GETNEXTITEM = (TV_FIRST + 10);
 38 | 		private const int TVM_GETITEM = (TV_FIRST + 12);
 39 | 		private const int TVM_ENSUREVISIBLE = (TV_FIRST + 20);
 40 | 
 41 | 		/// 
 42 | 		/// Constants used to identity specific items in the Tree View control
 43 | 		/// 
 44 | 		private const int TVGN_ROOT = 0x0;
 45 | 		private const int TVGN_NEXT = 0x1;
 46 | 		private const int TVGN_CHILD = 0x4;
 47 | 		private const int TVGN_FIRSTVISIBLE = 0x5;
 48 | 		private const int TVGN_NEXTVISIBLE = 0x6;
 49 | 		private const int TVGN_CARET = 0x9;
 50 | 		
 51 | 		/// 
 52 | 		/// Calling this method is identical to calling the ShowDialog method of the provided
 53 | 		/// FolderBrowserDialog, except that an attempt will be made to scroll the Tree View
 54 | 		/// to make the currently selected folder visible in the dialog window.
 55 | 		/// 
 56 | 		/// 
 57 | 		/// 
 58 | 		/// 
 59 | 		public static DialogResult ShowFolderBrowser(FolderBrowserDialog dlg, IWin32Window parent = null) {
 60 | 			DialogResult result = DialogResult.Cancel;
 61 | 			int retries = 40;
 62 | 			try {
 63 | 				if (dlg.SelectedPath != "")
 64 | 					dlg.SelectedPath = System.IO.Path.GetFullPath(dlg.SelectedPath);
 65 | 			}
 66 | 			catch { }
 67 | 
 68 | 			using (Timer t = new Timer()) {
 69 | 				t.Tick += (s, a) => {
 70 | 					if (retries > 0) {
 71 | 						--retries;
 72 | 						IntPtr hwndDlg = FindWindow((string)null, _topLevelSearchString);
 73 | 						if (hwndDlg != IntPtr.Zero) {
 74 | 							IntPtr hwndFolderCtrl = GetDlgItem(hwndDlg, _dlgItemBrowseControl);
 75 | 							if (hwndFolderCtrl != IntPtr.Zero) {
 76 | 								IntPtr hwndTV = GetDlgItem(hwndFolderCtrl, _dlgItemTreeView);
 77 | 
 78 | 								if (hwndTV != IntPtr.Zero) {
 79 | 									IntPtr item = SendMessage(hwndTV, (uint)TVM_GETNEXTITEM, new IntPtr(TVGN_CARET), IntPtr.Zero);
 80 | 									if (item != IntPtr.Zero) {
 81 | 										// Let's send this 40 times until we drill it into the folder browser's thick skull.
 82 | 										// Otherwise it will just go back to the beginning.
 83 | 										SendMessage(hwndTV, TVM_ENSUREVISIBLE, IntPtr.Zero, item);
 84 | 										//retries = 0;
 85 | 										//t.Stop();
 86 | 									}
 87 | 								}
 88 | 							}
 89 | 						}
 90 | 					}
 91 | 
 92 | 					else {
 93 | 						//
 94 | 						//  We failed to find the Tree View control.
 95 | 						//
 96 | 						//  As a fall back (and this is an UberUgly hack), we will send
 97 | 						//  some fake keystrokes to the application in an attempt to force
 98 | 						//  the Tree View to scroll to the selected item.
 99 | 						//
100 | 						t.Stop();
101 | 						//SendKeys.Send("{TAB}{TAB}{DOWN}{DOWN}{UP}{UP}");
102 | 					}
103 | 				};
104 | 
105 | 				t.Interval = 10;
106 | 				t.Start();
107 | 
108 | 				result = dlg.ShowDialog(parent);
109 | 			}
110 | 
111 | 			return result;
112 | 		}
113 | 	}
114 | }
--------------------------------------------------------------------------------
/TConvert/Windows/ProgressWindow.xaml:
--------------------------------------------------------------------------------
 1 | 
 9 |     
10 |         
11 |     
12 |     
13 |         
14 |         
15 |         
16 |         
17 |         
18 |         
19 |             
20 |                 
21 |                 
22 |             
23 |             
24 |             
25 |         
26 | 
27 |     
28 | 
29 | 
--------------------------------------------------------------------------------
/TConvert/Windows/ProgressWindow.xaml.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.Collections.Generic;
  3 | using System.Linq;
  4 | using System.Text;
  5 | using System.Threading;
  6 | using System.Threading.Tasks;
  7 | using System.Timers;
  8 | using System.Windows;
  9 | using System.Windows.Controls;
 10 | using System.Windows.Data;
 11 | using System.Windows.Documents;
 12 | using System.Windows.Input;
 13 | using System.Windows.Media;
 14 | using System.Windows.Media.Imaging;
 15 | using System.Windows.Shapes;
 16 | using System.Windows.Shell;
 17 | using Timer = System.Timers.Timer;
 18 | using TConvert.Util;
 19 | 
 20 | namespace TConvert.Windows {
 21 | 	/**The TConvert progress window.*/
 22 | 	public partial class ProgressWindow : Window {
 23 | 		//=========== MEMBERS ============
 24 | 		#region Members
 25 | 			
 26 | 		/**The thread being run.*/
 27 | 		private Thread thread;
 28 | 		/**The start time of the operation.*/
 29 | 		private DateTime startTime;
 30 | 		/**The timer to update the time taken.*/
 31 | 		private Timer timer;
 32 | 		/**The action to call when canceled.*/
 33 | 		private Action cancel;
 34 | 
 35 | 		#endregion
 36 | 		//========= CONSTRUCTORS =========
 37 | 		#region Constructors
 38 | 
 39 | 		/**Constructs the progress window.*/
 40 | 		public ProgressWindow(Thread thread, Action cancel) {
 41 | 			InitializeComponent();
 42 | 
 43 | 			this.thread = thread;
 44 | 			this.cancel = cancel;
 45 | 			this.timer = new Timer();
 46 | 			timer.Interval = 200;
 47 | 			timer.AutoReset = true;
 48 | 			timer.Elapsed += TimerEllapsed;
 49 | 		}
 50 | 
 51 | 		#endregion
 52 | 		//=========== PROGRESS ===========
 53 | 		#region Progress
 54 | 
 55 | 		/**Updates the progress on the window.*/
 56 | 		public void Update(string status, double progress) {
 57 | 			labelStatus.Content = status;
 58 | 			progressBar.Value = progress;
 59 | 			TaskbarItemInfo.ProgressValue = progress;
 60 | 		}
 61 | 		/**Tells the window the progress is finished.*/
 62 | 		public void Finish(string status, bool error) {
 63 | 			timer.Stop();
 64 | 			labelStatus.Content = status;
 65 | 			progressBar.Value = 1.0;
 66 | 			TaskbarItemInfo.ProgressValue = 1.0;
 67 | 			labelTime.Content = "Total Time: " + (DateTime.Now - startTime).ToString(@"m\:ss");
 68 | 			buttonFinish.IsEnabled = true;
 69 | 			buttonCancel.Visibility = Visibility.Hidden;
 70 | 			buttonFinish.Margin = new Thickness(0, 0, 10, 10);
 71 | 			buttonFinish.IsDefault = true;
 72 | 			buttonFinish.Focus();
 73 | 			if (error) {
 74 | 				TaskbarItemInfo.ProgressState = TaskbarItemProgressState.Error;
 75 | 			}
 76 | 			else {
 77 | 				TaskbarItemInfo.ProgressState = TaskbarItemProgressState.None;
 78 | 			}
 79 | 			this.Flash();
 80 | 		}
 81 | 
 82 | 		#endregion
 83 | 		//============ EVENTS ============
 84 | 		#region Events
 85 | 
 86 | 		private void TimerEllapsed(object sender, ElapsedEventArgs e) {
 87 | 			Dispatcher.Invoke(() => {
 88 | 				labelTime.Content = "Time: " + (DateTime.Now - startTime).ToString(@"m\:ss");
 89 | 			});
 90 | 		}
 91 | 		private void OnWindowLoaded(object sender, RoutedEventArgs e) {
 92 | 			startTime = DateTime.Now;
 93 | 			TaskbarItemInfo.ProgressState = TaskbarItemProgressState.Normal;
 94 | 			TaskbarItemInfo.ProgressValue = 0;
 95 | 			timer.Start();
 96 | 			thread.Start();
 97 | 		}
 98 | 		private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e) {
 99 | 			if (thread.ThreadState != ThreadState.Stopped) {
100 | 				try {
101 | 					thread.Abort();
102 | 				}
103 | 				catch { }
104 | 			}
105 | 		}
106 | 		private void OnCancel(object sender, RoutedEventArgs e) {
107 | 			if (thread.ThreadState != ThreadState.Stopped) {
108 | 				try {
109 | 					thread.Abort();
110 | 				}
111 | 				catch { }
112 | 			}
113 | 			DialogResult = false;
114 | 			if (cancel != null)
115 | 				cancel();
116 | 		}
117 | 		private void OnFinish(object sender, RoutedEventArgs e) {
118 | 			DialogResult = true;
119 | 		}
120 | 
121 | 		#endregion
122 | 	}
123 | }
124 | 
--------------------------------------------------------------------------------
/TConvert/Windows/TriggerMessageBox.xaml:
--------------------------------------------------------------------------------
 1 | 
 5 | 
 6 |     
 7 |         
10 | 
11 |         
12 |         
13 |         
14 |             
15 |             
16 |             
17 |         
18 |     
19 | 
20 | 
--------------------------------------------------------------------------------
/TConvert/Windows/TriggerMessageBox.xaml.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.Media;
  3 | using System.Windows;
  4 | using System.Windows.Controls;
  5 | using System.Windows.Input;
  6 | using System.Windows.Media.Imaging;
  7 | 
  8 | namespace TConvert.Windows {
  9 | 	/**The different types of icons available for message boxes.*/
 10 | 	public enum MessageIcon {
 11 | 		/**A blue (i) icon.*/
 12 | 		Info,
 13 | 		/**A blue (?) icon.*/
 14 | 		Question,
 15 | 		/**A yellow /!\ icon.*/
 16 | 		Warning,
 17 | 		/**A red (!) icon.*/
 18 | 		Error
 19 | 	}
 20 | 
 21 | 	/**A custom message box that doesn't look like shite.*/
 22 | 	public partial class TriggerMessageBox : Window {
 23 | 		//=========== MEMBERS ============
 24 | 		#region Members
 25 | 
 26 | 		/**The result of from pressing one of the message box buttons.*/
 27 | 		private MessageBoxResult result;
 28 | 		/**The minimum width of the message box.*/
 29 | 		private int minWidth;
 30 | 		/**The message box buttons setup.*/
 31 | 		private MessageBoxButton buttons;
 32 | 		/**The icon of the message.*/
 33 | 		private MessageIcon icon;
 34 | 
 35 | 		#endregion
 36 | 		//========= CONSTRUCTORS =========
 37 | 		#region Constructors
 38 | 
 39 | 		/**Constructs and sets up the message box.*/
 40 | 		private TriggerMessageBox(MessageIcon icon, string title, string message, MessageBoxButton buttons, string buttonName1 = null, string buttonName2 = null, string buttonName3 = null) {
 41 | 			InitializeComponent();
 42 | 			this.buttons = buttons;
 43 | 			this.icon = icon;
 44 | 			this.minWidth = 280;
 45 | 
 46 | 			#region Load Message Icons
 47 | 			switch (icon) {
 48 | 			case MessageIcon.Info:
 49 | 				this.Icon = new BitmapImage(new Uri("pack://application:,,,/Resources/Icons/InfoIcon.png"));
 50 | 				break;
 51 | 			case MessageIcon.Question:
 52 | 				this.Icon = new BitmapImage(new Uri("pack://application:,,,/Resources/Icons/QuestionIcon.png"));
 53 | 				break;
 54 | 			case MessageIcon.Warning:
 55 | 				this.Icon = new BitmapImage(new Uri("pack://application:,,,/Resources/Icons/WarningIcon.png"));
 56 | 				break;
 57 | 			case MessageIcon.Error:
 58 | 				this.Icon = new BitmapImage(new Uri("pack://application:,,,/Resources/Icons/ErrorIcon.png"));
 59 | 				break;
 60 | 			}
 61 | 			#endregion
 62 | 
 63 | 			// Setup the buttons
 64 | 			switch (buttons) {
 65 | 			#region MessageBoxButton.OK
 66 | 			case MessageBoxButton.OK:
 67 | 				button1.IsDefault = true;
 68 | 				button1.Content = "OK";
 69 | 				button1.Tag = MessageBoxResult.OK;
 70 | 				button2.Visibility = Visibility.Collapsed;
 71 | 				button3.Visibility = Visibility.Collapsed;
 72 | 				minWidth -= 85 * 2;
 73 | 				result = MessageBoxResult.OK;
 74 | 				if (buttonName1 != null)
 75 | 					button1.Content = buttonName1;
 76 | 				break;
 77 | 			#endregion
 78 | 			#region MessageBoxButton.OKCancel
 79 | 			case MessageBoxButton.OKCancel:
 80 | 				button1.IsDefault = true;
 81 | 				button1.Content = "OK";
 82 | 				button1.Tag = MessageBoxResult.OK;
 83 | 				button2.IsCancel = true;
 84 | 				button2.Content = "Cancel";
 85 | 				button2.Tag = MessageBoxResult.Cancel;
 86 | 				button3.Visibility = Visibility.Collapsed;
 87 | 				minWidth -= 85;
 88 | 				result = MessageBoxResult.Cancel;
 89 | 				if (buttonName1 != null)
 90 | 					button1.Content = buttonName1;
 91 | 				if (buttonName2 != null)
 92 | 					button2.Content = buttonName2;
 93 | 				break;
 94 | 			#endregion
 95 | 			#region MessageBoxButton.YesNo
 96 | 			case MessageBoxButton.YesNo:
 97 | 				button1.IsDefault = true;
 98 | 				button1.Content = "Yes";
 99 | 				button1.Tag = MessageBoxResult.Yes;
100 | 				button2.IsCancel = true;
101 | 				button2.Content = "No";
102 | 				button2.Tag = MessageBoxResult.No;
103 | 				button3.Visibility = Visibility.Collapsed;
104 | 				minWidth -= 85;
105 | 				result = MessageBoxResult.No;
106 | 				if (buttonName1 != null)
107 | 					button1.Content = buttonName1;
108 | 				if (buttonName2 != null)
109 | 					button2.Content = buttonName2;
110 | 				break;
111 | 			#endregion
112 | 			#region MessageBoxButton.YesNoCancel
113 | 			case MessageBoxButton.YesNoCancel:
114 | 				button1.IsDefault = true;
115 | 				button1.Content = "Yes";
116 | 				button1.Tag = MessageBoxResult.Yes;
117 | 				button2.Content = "No";
118 | 				button2.Tag = MessageBoxResult.No;
119 | 				button3.IsCancel = true;
120 | 				button3.Content = "Cancel";
121 | 				button3.Tag = MessageBoxResult.Cancel;
122 | 				result = MessageBoxResult.Cancel;
123 | 				if (buttonName1 != null)
124 | 					button1.Content = buttonName1;
125 | 				if (buttonName2 != null)
126 | 					button2.Content = buttonName2;
127 | 				if (buttonName3 != null)
128 | 					button3.Content = buttonName3;
129 | 				break;
130 | 				#endregion
131 | 			}
132 | 
133 | 			this.Title = title;
134 | 			this.textBlockMessage.Text = message;
135 | 		}
136 | 
137 | 		#endregion
138 | 		//=========== HELPERS ============
139 | 		#region Helpers
140 | 
141 | 		/**Gets the number of message box buttons.*/
142 | 		private int ButtonCount {
143 | 			get {
144 | 				switch (buttons) {
145 | 				case MessageBoxButton.OK:
146 | 					return 1;
147 | 				case MessageBoxButton.OKCancel:
148 | 				case MessageBoxButton.YesNo:
149 | 					return 2;
150 | 				case MessageBoxButton.YesNoCancel:
151 | 					return 3;
152 | 				}
153 | 				return 3;
154 | 			}
155 | 		}
156 | 		/**Gets the button at the specified index.*/
157 | 		private Button GetButtonAt(int index) {
158 | 			switch (index) {
159 | 			case 0: return button1;
160 | 			case 1: return button2;
161 | 			case 2: return button3;
162 | 			}
163 | 			return null;
164 | 		}
165 | 		/**Gets the index of the button.*/
166 | 		private int IndexOfButton(Button button) {
167 | 			if (button == button1)
168 | 				return 0;
169 | 			else if (button == button2)
170 | 				return 1;
171 | 			else if (button == button3)
172 | 				return 2;
173 | 			return -1;
174 | 		}
175 | 
176 | 		#endregion
177 | 		//============ EVENTS ============
178 | 		#region Events
179 | 
180 | 		private void OnWindowLoaded(object sender, RoutedEventArgs e) {
181 | 			clientArea.Width = Math.Max(minWidth, Math.Max(textBlockMessage.ActualWidth + 60, stackPanelButtons.ActualWidth + 10));
182 | 			clientArea.Height += textBlockMessage.ActualHeight - 16;
183 | 
184 | 			#region Load Message Sounds
185 | 			switch (icon) {
186 | 			case MessageIcon.Info: SystemSounds.Asterisk.Play(); break;
187 | 			case MessageIcon.Question: SystemSounds.Asterisk.Play(); break;
188 | 			case MessageIcon.Warning: SystemSounds.Exclamation.Play(); break;
189 | 			case MessageIcon.Error: SystemSounds.Hand.Play(); break;
190 | 			}
191 | 			#endregion
192 | 		}
193 | 		private void OnButtonClicked(object sender, RoutedEventArgs e) {
194 | 			result = (MessageBoxResult)((Button)sender).Tag;
195 | 			Close();
196 | 		}
197 | 		private void OnPreviewKeyDown(object sender, KeyEventArgs e) {
198 | 			var button = FocusManager.GetFocusedElement(this) as Button;
199 | 			switch (e.Key) {
200 | 			case Key.Right:
201 | 				if (button == null && ButtonCount > 1)
202 | 					GetButtonAt(1).Focus();
203 | 				else if (button != null && IndexOfButton(button) < ButtonCount - 1)
204 | 					button.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
205 | 				e.Handled = true;
206 | 				break;
207 | 			case Key.Left:
208 | 				if (button != null && IndexOfButton(button) > 0)
209 | 					button.MoveFocus(new TraversalRequest(FocusNavigationDirection.Previous));
210 | 				e.Handled = true;
211 | 				break;
212 | 			}
213 | 		}
214 | 
215 | 		#endregion
216 | 		//=========== SHOWING ============
217 | 		#region Showing
218 | 
219 | 		/**Shows the message box.*/
220 | 		public static MessageBoxResult Show(Window window, MessageIcon icon, string message) {
221 | 			return Show(window, icon, message, "", MessageBoxButton.OK);
222 | 		}
223 | 		/**Shows the message box.*/
224 | 		public static MessageBoxResult Show(Window window, MessageIcon icon, string message, string title) {
225 | 			return Show(window, icon, message, title, MessageBoxButton.OK);
226 | 		}
227 | 		/**Shows the message box.*/
228 | 		public static MessageBoxResult Show(Window window, MessageIcon icon, string message, MessageBoxButton buttons) {
229 | 			return Show(window, icon, message, "", buttons);
230 | 		}
231 | 		/**Shows the message box.*/
232 | 		public static MessageBoxResult Show(Window window, MessageIcon icon, string message, string title, MessageBoxButton buttons, string buttonName1 = null, string buttonName2 = null, string buttonName3 = null) {
233 | 			TriggerMessageBox messageBox = new TriggerMessageBox(icon, title, message, buttons, buttonName1, buttonName2, buttonName3);
234 | 			if (window == null || window.Visibility != Visibility.Visible)
235 | 				messageBox.WindowStartupLocation = WindowStartupLocation.CenterScreen;
236 | 			else
237 | 				messageBox.Owner = window;
238 | 			messageBox.ShowDialog();
239 | 			return messageBox.result;
240 | 		}
241 | 
242 | 		#endregion
243 | 	}
244 | }
245 | 
--------------------------------------------------------------------------------