├── .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 |
--------------------------------------------------------------------------------