├── .gitignore
├── CHANGELOG.txt
├── LICENSE
├── README.md
├── Touhou Launcher.sln
└── Touhou Launcher
├── ConfigForm.Designer.cs
├── ConfigForm.cs
├── ConfigForm.resx
├── MainForm.Designer.cs
├── MainForm.cs
├── MainForm.resx
├── Program.cs
├── Properties
├── AssemblyInfo.cs
├── Resources.Designer.cs
├── Resources.resx
├── Settings.Designer.cs
└── Settings.settings
├── Resources_en.Designer.cs
├── Resources_en.resx
├── Resources_jp.Designer.cs
├── Resources_jp.resx
├── Resources_ru.Designer.cs
├── Resources_ru.resx
├── Touhou Launcher.csproj
├── app.config
├── jsonnet
├── LICENSE.md
├── Newtonsoft.Json.dll
└── Newtonsoft.Json.xml
├── thcrap.Designer.cs
├── thcrap.cs
├── thcrap.resx
└── thicon.ico
/.gitignore:
--------------------------------------------------------------------------------
1 | Touhou Launcher.v11.suo
2 | bin/
3 | obj/
4 | /.vs/
5 |
--------------------------------------------------------------------------------
/CHANGELOG.txt:
--------------------------------------------------------------------------------
1 | 1.03 (03/09/2023)
2 | Added: Touhou 19 support.
3 |
4 | 1.02 (14/09/2022)
5 | Added: Touhou 18.5 support.
6 | Added: Complete Japanese translation. (Courtesy of HoengSaan)
7 | Added: Error when adding custom game without a category.
8 | Added: Queue for fetching repos so servers aren't overloaded. Lowers refresh speed.
9 | Changed: Rearranged the game categories: Separated the PC-98 games into their own category and renamed the fighting category to games by Twilight Frontier.
10 | Changed: Moved Gouyoku Ibun to the Twilight Frontier category.
11 | Changed: Made instructions more clear when launching a game that isn't set up. (Russian translation pending)
12 | Changed: Updated .Net Framework target to 4.8
13 | Changed: Simplified repo search to use tasks.
14 | Changed: Changed default repo to the official server on the Touhou Patch Center.
15 | Removed: Upwards repository crawl.
16 |
17 | 1.01 (02/02/2022)
18 | Changed: Removed Royalflare's link in the replays tab in light of its approaching shutdown.
19 | Changed: Maribel Hearn's replay link now points to the site's top page.
20 | Changed: Switched to TLS 1.2 to fix thcrap/replay links that don't support older TLS versions.
21 | Changed: Added a check for repo crawling to prevent repeated requests.
22 | Fixed: The launcher creating another directory for thcrap sometimes.
23 |
24 | 1.0 (02/11/2021)
25 | Added: Touhou 17.5 support.
26 |
27 | 1.0-pre5 (04/06/2021)
28 | Added: Touhou 18 support.
29 |
30 | 1.0-pre4 (06/12/2019)
31 | Added: Tray icon for Touhou 17.
32 | Changed: The backwards compatibility code has been rewritten. Unfortunately this breaks compatibility with older versions. An intermediary version called pre3.5 is provided for conversion of settings.json to the new format.
33 | Changed: The browser will no longer start on a webpage.
34 | Changed: replays.gensokyo.org was changed to maribelhearn.com/gensokyo as the former is no longer accessible.
35 | Changed: Updated thcrap interaction to be compatible with the 2019-10-05 update. You may need to set your thcrap_loader path again.
36 | Changed: The profile editor will now fill in missing game profiles with paths that you have already filled automatically when launching it.
37 | Changed: You can now set arbitrary names for game profile IDs as long as they don't start with "th".
38 | Changed: Enlarged the custom games list.
39 | Changed: Upgraded to Visual Studio 2017 from 2012. Hopefully shouldn't change anything.
40 | Changed: Dependencies will now appear only above the patches that depend on them.
41 | Changed: Required thcrap directories will now be created automatically if they do not exist.
42 | Changed: Repository descriptor json files will now be saved upon visiting the patch menu.
43 | Changed: Patch descriptor json files will now be updated whenever they're fetched from the repositories.
44 | Changed: The patch list will no longer lose focus on every repository check.
45 | Fixed: The tray icon's Main Games menu not working (no idea when that broke).
46 | Fixed: thcrap's encoding for patches not using UTF-8.
47 | Fixed: Error if patch directory does not exist.
48 | Fixed: Error when games.js does not exist.
49 |
50 | 1.0-pre3 (13/08/2019)
51 | Added: Selected patches list to show the order of installed patches.
52 | Added: Touhou 17 support.
53 | Added: Dependency search for patches.
54 | Changed: You can now resize the window to smaller size than default. (buggy at the moment)
55 | Changed: Updates to the patch repositories are shown in real time.
56 | Fixed: Appdata/Replay folder being undetectable.
57 | Fixed: Infinite loop when searching for thcrap repositories.
58 | Fixed: local repositories having higher priority than thcrap.
59 | Fixed: thcrap complaining about patch.js not existing.
60 |
61 | 1.0-pre2 (17/04/2019)
62 | Added: thcrap Profile Editor. Lets you select patches from a list and configure the game list manually. The repository search starts at a configurable Url. Offline-only builds will also be released without this feature from now on.
63 | Added: Customizable text color for buttons + the ability to disable the text or banner entirely.
64 | Added: Saved states for the random games list.
65 | Changed: Custom game categories no longer save their key name in the config (hopefully since they are no longer needed).
66 | Changed: The File Select Dialog will now start from the last place a file was selected.
67 | Changed: Custom banners now stretch to fit the button.
68 | Changed: The settings in the settings tab will now only save when switching tabs or closing the program.
69 | Fixed: Background pictures for games being one pixel off.
70 | Fixed: Double Dealing Character typo.
71 | Fixed: Custom banner checkbox not saving.
72 | Fixed: Tab order for the controls.
73 | Fixed: Tray icon's custom games list adding games to their parent category.
74 | Fixed: Not changing the name while renaming custom games/categories would result in an error.
75 | Fixed: Adding the same custom game multiple times. (As long as the path is the exact same)
76 | Fixed: Expanding/Collapsing a custom game category deselecting it.
77 | Fixed: thcrap's files appearing in the launcher's directory.
78 | Fixed: Hisoutensoku and Double Spoiler having the wrong numbers.
79 | Fixed: The banner size label not showing up on the configuration form.
80 | Fixed: Smaller buttons will now show a tooltip with the full text when translated text does not fit in them.
81 | Optimized code
82 | Optimized resources. Should reduce file size by 1.40MBs
83 | Updated localization files.
84 |
85 | 1.0-pre (06/03/2019)
86 | Added: Replay downloader. Includes 3 websites + manual link input.
87 | Added: Tray icon including minimization to tray and always-on tray settings. Can be used to launch any game set up in the program.
88 | Added: thcrap directory setting.
89 | Added: Confirmation dialog when removing custom categories/games.
90 | Added: Drag/drop support to Neko Project II and thcrap's directory settings.
91 | Added: Support for IaMP's Config.exe
92 | Added: Complete localization support.
93 | Added: Russian language support. (courtesy of Lensrub)
94 | Changed: Game configuration dialog shows which game you're configuring.
95 | Changed: Normal buttons no longer use the hand cursor.
96 | Changed: The configuration form always shows at the center of the main window.
97 | Changed: Switched to the DD/MM/YYYY format.
98 | Changed: Custom banner group box now shows the supported dimensions.
99 | Changed: thcrap support is now handled through dropboxes with the name of the game and the configuration files.
100 | Fixed: Unformatted localization strings.
101 | Fixed: PC-98 games giving two messageboxes per error.
102 | Fixed: Possibility of Neko Project II's directory not being saved.
103 | Fixed: Colored banner throwing an exception when editing it manually.
104 | Fixed: Custom banner checkbox and text box not saving when the latter is edited manually.
105 | Fixed: Previously filled textboxes being re-filled.
106 | Fixed: Randomizer select buttons are symmetrical and fit more text.
107 | Fixed: The random button stretching by resizing the window.
108 | Fixed: IaMP's text color being black for some reason.
109 | Updated localization files.
110 | Code reorganization
111 |
112 | 0.8 (11/02/2019)
113 | Added: Actual launch code for PC-98 games (How did I forget that).
114 | Added: Drag/Drop support for game configuration.
115 | Changed: Launching PC-98 games now simply replaces the hdi directory instead of the entire ini file.
116 | Changed: Invalid textboxes turn red instead of giving you a message box/not doing anything.
117 | Fixed: PC-98 games not saving their status immediately.
118 | Fixed: Manually adding banners now checks if the image is valid/openable.
119 |
120 | 0.5 (10/02/2019)
121 | Initial Release
122 |
123 | 07/02/2019 (DD/MM/YYYY)
124 | Project Start
125 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 2-Clause License
2 |
3 | Copyright (c) 2019, David_JonesDVN
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Touhou-Launcher
2 | A rewrite of the Touhou Launcher created by Widdiful and an alternative to the thcrap configurator.\
3 | I tried making it more user friendly and added options wherever it was needed.
4 |
5 | The Touhou Launcher a program you can use and set up to launch any Touhou game (and even others if you're using the custom games tab) from the UI or the tray icon. It supports Neko Project II for PC-98 games, game exe files (the game itself, custom.exe or vpatch.exe), and thcrap.\
6 | In addition, it supports the addition and removal of patches from the thcrap patch repository using a checkbox and list format, with dependencies being added automatically.\
7 | There is also a "Replays" tab you can use to either navigate popular Touhou replay websites (Don't, actually. The .NET web browser is worse than Internet Explorer 8) or enter your own links to let the launcher automatically download and put them in the correct folder.\
8 | Finally, each game has a background picture that you can change to whatever you want.
9 |
10 | # Features
11 | Dynamic tray icon menu for custom games.\
12 | Proper thcrap support, including patch and game profile configuration. (The offline version ships without the configurator.)\
13 | No auto-updater. I know some of you probably hate things like that.\
14 | Customizability for how the games launch.\
15 | Russian language support (Thanks Lensrub).\
16 | Work-in-progress Japanese language support.\
17 | Custom language support for testing purposes if you're interested in translating it.\
18 | Almost all of the features from the original Touhou Launcher.
19 |
20 | # How To Use
21 | First of all, fill in Neko Project II/thcrap_loader's paths in the settings tab.\
22 | You can then fill in the games' paths by right-clicking on their buttons.\
23 | If you're not using the offline build, you can choose the "Custom" option from the thcrap dropdown menu on a game's configuration screen to configure patches for that game.
24 |
25 | This is a nonprofit project developed independently by a fan.\
26 | Touhou belongs to Team Shanghai Alice.\
27 | \
28 | Thank you for using this program.\
29 | I hope you'll enjoy it as much as I enjoyed making it.\
30 | Feel free to report any bugs, problems or feature requests on the Issues page.\
31 | \
32 | Json.NET used under the MIT license.
--------------------------------------------------------------------------------
/Touhou Launcher.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Touhou Launcher", "Touhou Launcher\Touhou Launcher.csproj", "{DC2E240A-725B-4A6C-83B0-73DBAAB13D1D}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Any CPU = Debug|Any CPU
9 | Release|Any CPU = Release|Any CPU
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {DC2E240A-725B-4A6C-83B0-73DBAAB13D1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13 | {DC2E240A-725B-4A6C-83B0-73DBAAB13D1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
14 | {DC2E240A-725B-4A6C-83B0-73DBAAB13D1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
15 | {DC2E240A-725B-4A6C-83B0-73DBAAB13D1D}.Release|Any CPU.Build.0 = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/Touhou Launcher/ConfigForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Touhou_Launcher
2 | {
3 | partial class ConfigForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ConfigForm));
32 | this.openFolder = new System.Windows.Forms.Button();
33 | this.openvpatch = new System.Windows.Forms.Button();
34 | this.jpDir = new System.Windows.Forms.TextBox();
35 | this.enDir = new System.Windows.Forms.TextBox();
36 | this.customDir = new System.Windows.Forms.TextBox();
37 | this.browseJP = new System.Windows.Forms.Button();
38 | this.jpLabel = new System.Windows.Forms.Label();
39 | this.enLabel = new System.Windows.Forms.Label();
40 | this.customLabel = new System.Windows.Forms.Label();
41 | this.openReplays = new System.Windows.Forms.Button();
42 | this.browseEN = new System.Windows.Forms.Button();
43 | this.browseCustom = new System.Windows.Forms.Button();
44 | this.jpApplocale = new System.Windows.Forms.CheckBox();
45 | this.defaultExec = new System.Windows.Forms.ComboBox();
46 | this.defaultLabel = new System.Windows.Forms.Label();
47 | this.launchCustom = new System.Windows.Forms.Button();
48 | this.launchEN = new System.Windows.Forms.Button();
49 | this.launchJP = new System.Windows.Forms.Button();
50 | this.launchcrap = new System.Windows.Forms.Button();
51 | this.crapLabel = new System.Windows.Forms.Label();
52 | this.customApplocale = new System.Windows.Forms.CheckBox();
53 | this.defaultApplocale = new System.Windows.Forms.CheckBox();
54 | this.crapApplocale = new System.Windows.Forms.CheckBox();
55 | this.enApplocale = new System.Windows.Forms.CheckBox();
56 | this.chkCustomBanner = new System.Windows.Forms.CheckBox();
57 | this.bannerOnLabel = new System.Windows.Forms.Label();
58 | this.browseBannerOn = new System.Windows.Forms.Button();
59 | this.bannerOnDir = new System.Windows.Forms.TextBox();
60 | this.bannerOffLabel = new System.Windows.Forms.Label();
61 | this.browseBannerOff = new System.Windows.Forms.Button();
62 | this.bannerOffDir = new System.Windows.Forms.TextBox();
63 | this.pc98Settings = new System.Windows.Forms.GroupBox();
64 | this.openNP2Folder = new System.Windows.Forms.Button();
65 | this.launchHDI = new System.Windows.Forms.Button();
66 | this.hdiLabel = new System.Windows.Forms.Label();
67 | this.browseHDI = new System.Windows.Forms.Button();
68 | this.hdiDir = new System.Windows.Forms.TextBox();
69 | this.bannerSettings = new System.Windows.Forms.GroupBox();
70 | this.chkCustomText = new System.Windows.Forms.CheckBox();
71 | this.btnCustomText = new System.Windows.Forms.Button();
72 | this.bannerSize = new System.Windows.Forms.Label();
73 | this.windowsSettings = new System.Windows.Forms.GroupBox();
74 | this.crapCfg = new System.Windows.Forms.ComboBox();
75 | this.crapGame = new System.Windows.Forms.ComboBox();
76 | this.openAppdata = new System.Windows.Forms.Button();
77 | this.pc98Settings.SuspendLayout();
78 | this.bannerSettings.SuspendLayout();
79 | this.windowsSettings.SuspendLayout();
80 | this.SuspendLayout();
81 | //
82 | // openFolder
83 | //
84 | this.openFolder.Location = new System.Drawing.Point(337, 235);
85 | this.openFolder.Name = "openFolder";
86 | this.openFolder.Size = new System.Drawing.Size(242, 23);
87 | this.openFolder.TabIndex = 3;
88 | this.openFolder.Text = "Open Folder";
89 | this.openFolder.UseVisualStyleBackColor = true;
90 | this.openFolder.Click += new System.EventHandler(this.openFolder_Click);
91 | //
92 | // openvpatch
93 | //
94 | this.openvpatch.AutoEllipsis = true;
95 | this.openvpatch.Location = new System.Drawing.Point(231, 227);
96 | this.openvpatch.Name = "openvpatch";
97 | this.openvpatch.Size = new System.Drawing.Size(91, 23);
98 | this.openvpatch.TabIndex = 21;
99 | this.openvpatch.Text = "Edit vpatch.ini";
100 | this.openvpatch.UseVisualStyleBackColor = true;
101 | this.openvpatch.Click += new System.EventHandler(this.openvpatch_Click);
102 | //
103 | // jpDir
104 | //
105 | this.jpDir.AllowDrop = true;
106 | this.jpDir.Location = new System.Drawing.Point(9, 32);
107 | this.jpDir.Name = "jpDir";
108 | this.jpDir.Size = new System.Drawing.Size(181, 20);
109 | this.jpDir.TabIndex = 1;
110 | this.jpDir.DragDrop += new System.Windows.Forms.DragEventHandler(this.Dir_DragDrop);
111 | this.jpDir.DragEnter += new System.Windows.Forms.DragEventHandler(this.Dir_DragEnter);
112 | this.jpDir.LostFocus += new System.EventHandler(this.Dir_LostFocus);
113 | //
114 | // enDir
115 | //
116 | this.enDir.AllowDrop = true;
117 | this.enDir.Location = new System.Drawing.Point(9, 80);
118 | this.enDir.Name = "enDir";
119 | this.enDir.Size = new System.Drawing.Size(181, 20);
120 | this.enDir.TabIndex = 5;
121 | this.enDir.DragDrop += new System.Windows.Forms.DragEventHandler(this.Dir_DragDrop);
122 | this.enDir.DragEnter += new System.Windows.Forms.DragEventHandler(this.Dir_DragEnter);
123 | this.enDir.LostFocus += new System.EventHandler(this.Dir_LostFocus);
124 | //
125 | // customDir
126 | //
127 | this.customDir.AllowDrop = true;
128 | this.customDir.Location = new System.Drawing.Point(9, 128);
129 | this.customDir.Name = "customDir";
130 | this.customDir.Size = new System.Drawing.Size(181, 20);
131 | this.customDir.TabIndex = 10;
132 | this.customDir.DragDrop += new System.Windows.Forms.DragEventHandler(this.Dir_DragDrop);
133 | this.customDir.DragEnter += new System.Windows.Forms.DragEventHandler(this.Dir_DragEnter);
134 | this.customDir.LostFocus += new System.EventHandler(this.Dir_LostFocus);
135 | //
136 | // browseJP
137 | //
138 | this.browseJP.Location = new System.Drawing.Point(196, 30);
139 | this.browseJP.Name = "browseJP";
140 | this.browseJP.Size = new System.Drawing.Size(62, 22);
141 | this.browseJP.TabIndex = 2;
142 | this.browseJP.Text = "Browse";
143 | this.browseJP.UseVisualStyleBackColor = true;
144 | this.browseJP.Click += new System.EventHandler(this.browse_Click);
145 | //
146 | // jpLabel
147 | //
148 | this.jpLabel.AutoSize = true;
149 | this.jpLabel.Location = new System.Drawing.Point(6, 16);
150 | this.jpLabel.Name = "jpLabel";
151 | this.jpLabel.Size = new System.Drawing.Size(150, 13);
152 | this.jpLabel.TabIndex = 6;
153 | this.jpLabel.Text = "Japanese/vpatch Executable:";
154 | //
155 | // enLabel
156 | //
157 | this.enLabel.AutoSize = true;
158 | this.enLabel.Location = new System.Drawing.Point(6, 64);
159 | this.enLabel.Name = "enLabel";
160 | this.enLabel.Size = new System.Drawing.Size(100, 13);
161 | this.enLabel.TabIndex = 7;
162 | this.enLabel.Text = "English Executable:";
163 | //
164 | // customLabel
165 | //
166 | this.customLabel.AutoSize = true;
167 | this.customLabel.Location = new System.Drawing.Point(6, 112);
168 | this.customLabel.Name = "customLabel";
169 | this.customLabel.Size = new System.Drawing.Size(65, 13);
170 | this.customLabel.TabIndex = 8;
171 | this.customLabel.Text = "Custom.exe:";
172 | //
173 | // openReplays
174 | //
175 | this.openReplays.AutoEllipsis = true;
176 | this.openReplays.Location = new System.Drawing.Point(106, 227);
177 | this.openReplays.Name = "openReplays";
178 | this.openReplays.Size = new System.Drawing.Size(119, 23);
179 | this.openReplays.TabIndex = 20;
180 | this.openReplays.Text = "Open Replays Folder";
181 | this.openReplays.UseVisualStyleBackColor = true;
182 | this.openReplays.Click += new System.EventHandler(this.openReplays_Click);
183 | //
184 | // browseEN
185 | //
186 | this.browseEN.Location = new System.Drawing.Point(196, 78);
187 | this.browseEN.Name = "browseEN";
188 | this.browseEN.Size = new System.Drawing.Size(62, 22);
189 | this.browseEN.TabIndex = 6;
190 | this.browseEN.Text = "Browse";
191 | this.browseEN.UseVisualStyleBackColor = true;
192 | this.browseEN.Click += new System.EventHandler(this.browse_Click);
193 | //
194 | // browseCustom
195 | //
196 | this.browseCustom.Location = new System.Drawing.Point(196, 126);
197 | this.browseCustom.Name = "browseCustom";
198 | this.browseCustom.Size = new System.Drawing.Size(62, 22);
199 | this.browseCustom.TabIndex = 11;
200 | this.browseCustom.Text = "Browse";
201 | this.browseCustom.UseVisualStyleBackColor = true;
202 | this.browseCustom.Click += new System.EventHandler(this.browse_Click);
203 | //
204 | // jpApplocale
205 | //
206 | this.jpApplocale.AutoSize = true;
207 | this.jpApplocale.Location = new System.Drawing.Point(221, 12);
208 | this.jpApplocale.Name = "jpApplocale";
209 | this.jpApplocale.Size = new System.Drawing.Size(98, 17);
210 | this.jpApplocale.TabIndex = 0;
211 | this.jpApplocale.Text = "With Applocale";
212 | this.jpApplocale.UseVisualStyleBackColor = true;
213 | this.jpApplocale.CheckedChanged += new System.EventHandler(this.Applocale_CheckedChanged);
214 | //
215 | // defaultExec
216 | //
217 | this.defaultExec.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
218 | this.defaultExec.FormattingEnabled = true;
219 | this.defaultExec.Items.AddRange(new object[] {
220 | "Japanese/vpatch.ini",
221 | "English (non-THCRAP)",
222 | "Custom.exe",
223 | "thcrap"});
224 | this.defaultExec.Location = new System.Drawing.Point(109, 198);
225 | this.defaultExec.Name = "defaultExec";
226 | this.defaultExec.Size = new System.Drawing.Size(113, 21);
227 | this.defaultExec.TabIndex = 17;
228 | this.defaultExec.SelectedIndexChanged += new System.EventHandler(this.defaultExec_SelectedIndexChanged);
229 | //
230 | // defaultLabel
231 | //
232 | this.defaultLabel.AutoSize = true;
233 | this.defaultLabel.Location = new System.Drawing.Point(6, 198);
234 | this.defaultLabel.Name = "defaultLabel";
235 | this.defaultLabel.Size = new System.Drawing.Size(100, 13);
236 | this.defaultLabel.TabIndex = 16;
237 | this.defaultLabel.Text = "Default Executable:";
238 | //
239 | // launchCustom
240 | //
241 | this.launchCustom.AutoEllipsis = true;
242 | this.launchCustom.Location = new System.Drawing.Point(264, 126);
243 | this.launchCustom.Name = "launchCustom";
244 | this.launchCustom.Size = new System.Drawing.Size(55, 22);
245 | this.launchCustom.TabIndex = 12;
246 | this.launchCustom.Text = "Launch";
247 | this.launchCustom.UseVisualStyleBackColor = true;
248 | this.launchCustom.Click += new System.EventHandler(this.launch_Click);
249 | //
250 | // launchEN
251 | //
252 | this.launchEN.AutoEllipsis = true;
253 | this.launchEN.Location = new System.Drawing.Point(264, 78);
254 | this.launchEN.Name = "launchEN";
255 | this.launchEN.Size = new System.Drawing.Size(55, 22);
256 | this.launchEN.TabIndex = 7;
257 | this.launchEN.Text = "Launch";
258 | this.launchEN.UseVisualStyleBackColor = true;
259 | this.launchEN.Click += new System.EventHandler(this.launch_Click);
260 | //
261 | // launchJP
262 | //
263 | this.launchJP.AutoEllipsis = true;
264 | this.launchJP.Location = new System.Drawing.Point(264, 30);
265 | this.launchJP.Name = "launchJP";
266 | this.launchJP.Size = new System.Drawing.Size(55, 22);
267 | this.launchJP.TabIndex = 3;
268 | this.launchJP.Text = "Launch";
269 | this.launchJP.UseVisualStyleBackColor = true;
270 | this.launchJP.Click += new System.EventHandler(this.launch_Click);
271 | //
272 | // launchcrap
273 | //
274 | this.launchcrap.AutoEllipsis = true;
275 | this.launchcrap.Location = new System.Drawing.Point(264, 171);
276 | this.launchcrap.Name = "launchcrap";
277 | this.launchcrap.Size = new System.Drawing.Size(55, 22);
278 | this.launchcrap.TabIndex = 16;
279 | this.launchcrap.Text = "Launch";
280 | this.launchcrap.UseVisualStyleBackColor = true;
281 | this.launchcrap.Click += new System.EventHandler(this.launchcrap_Click);
282 | //
283 | // crapLabel
284 | //
285 | this.crapLabel.AutoSize = true;
286 | this.crapLabel.Location = new System.Drawing.Point(6, 155);
287 | this.crapLabel.Name = "crapLabel";
288 | this.crapLabel.Size = new System.Drawing.Size(72, 13);
289 | this.crapLabel.TabIndex = 21;
290 | this.crapLabel.Text = "thcrap Profile:";
291 | //
292 | // customApplocale
293 | //
294 | this.customApplocale.AutoSize = true;
295 | this.customApplocale.Location = new System.Drawing.Point(221, 108);
296 | this.customApplocale.Name = "customApplocale";
297 | this.customApplocale.Size = new System.Drawing.Size(98, 17);
298 | this.customApplocale.TabIndex = 9;
299 | this.customApplocale.Text = "With Applocale";
300 | this.customApplocale.UseVisualStyleBackColor = true;
301 | this.customApplocale.CheckedChanged += new System.EventHandler(this.Applocale_CheckedChanged);
302 | //
303 | // defaultApplocale
304 | //
305 | this.defaultApplocale.AutoSize = true;
306 | this.defaultApplocale.Location = new System.Drawing.Point(228, 202);
307 | this.defaultApplocale.Name = "defaultApplocale";
308 | this.defaultApplocale.Size = new System.Drawing.Size(98, 17);
309 | this.defaultApplocale.TabIndex = 18;
310 | this.defaultApplocale.Text = "With Applocale";
311 | this.defaultApplocale.UseVisualStyleBackColor = true;
312 | this.defaultApplocale.CheckedChanged += new System.EventHandler(this.defaultApplocale_CheckedChanged);
313 | //
314 | // crapApplocale
315 | //
316 | this.crapApplocale.AutoSize = true;
317 | this.crapApplocale.Location = new System.Drawing.Point(221, 152);
318 | this.crapApplocale.Name = "crapApplocale";
319 | this.crapApplocale.Size = new System.Drawing.Size(98, 17);
320 | this.crapApplocale.TabIndex = 13;
321 | this.crapApplocale.Text = "With Applocale";
322 | this.crapApplocale.UseVisualStyleBackColor = true;
323 | this.crapApplocale.CheckedChanged += new System.EventHandler(this.Applocale_CheckedChanged);
324 | //
325 | // enApplocale
326 | //
327 | this.enApplocale.AutoSize = true;
328 | this.enApplocale.Location = new System.Drawing.Point(221, 60);
329 | this.enApplocale.Name = "enApplocale";
330 | this.enApplocale.Size = new System.Drawing.Size(98, 17);
331 | this.enApplocale.TabIndex = 4;
332 | this.enApplocale.Text = "With Applocale";
333 | this.enApplocale.UseVisualStyleBackColor = true;
334 | this.enApplocale.CheckedChanged += new System.EventHandler(this.Applocale_CheckedChanged);
335 | //
336 | // chkCustomBanner
337 | //
338 | this.chkCustomBanner.AutoSize = true;
339 | this.chkCustomBanner.Location = new System.Drawing.Point(120, 12);
340 | this.chkCustomBanner.Name = "chkCustomBanner";
341 | this.chkCustomBanner.Size = new System.Drawing.Size(118, 17);
342 | this.chkCustomBanner.TabIndex = 0;
343 | this.chkCustomBanner.Text = "Use custom banner";
344 | this.chkCustomBanner.UseVisualStyleBackColor = true;
345 | this.chkCustomBanner.CheckedChanged += new System.EventHandler(this.chkCustomBanner_CheckedChanged);
346 | //
347 | // bannerOnLabel
348 | //
349 | this.bannerOnLabel.AutoSize = true;
350 | this.bannerOnLabel.Location = new System.Drawing.Point(6, 16);
351 | this.bannerOnLabel.Name = "bannerOnLabel";
352 | this.bannerOnLabel.Size = new System.Drawing.Size(83, 13);
353 | this.bannerOnLabel.TabIndex = 31;
354 | this.bannerOnLabel.Text = "Colored Banner:";
355 | //
356 | // browseBannerOn
357 | //
358 | this.browseBannerOn.Location = new System.Drawing.Point(176, 30);
359 | this.browseBannerOn.Name = "browseBannerOn";
360 | this.browseBannerOn.Size = new System.Drawing.Size(62, 22);
361 | this.browseBannerOn.TabIndex = 2;
362 | this.browseBannerOn.Text = "Browse";
363 | this.browseBannerOn.UseVisualStyleBackColor = true;
364 | this.browseBannerOn.Click += new System.EventHandler(this.browseBannerOn_Click);
365 | //
366 | // bannerOnDir
367 | //
368 | this.bannerOnDir.AllowDrop = true;
369 | this.bannerOnDir.Location = new System.Drawing.Point(9, 32);
370 | this.bannerOnDir.Name = "bannerOnDir";
371 | this.bannerOnDir.Size = new System.Drawing.Size(161, 20);
372 | this.bannerOnDir.TabIndex = 1;
373 | this.bannerOnDir.DragDrop += new System.Windows.Forms.DragEventHandler(this.Dir_DragDrop);
374 | this.bannerOnDir.DragEnter += new System.Windows.Forms.DragEventHandler(this.Dir_DragEnter);
375 | this.bannerOnDir.LostFocus += new System.EventHandler(this.bannerDir_LostFocus);
376 | //
377 | // bannerOffLabel
378 | //
379 | this.bannerOffLabel.AutoSize = true;
380 | this.bannerOffLabel.Location = new System.Drawing.Point(6, 54);
381 | this.bannerOffLabel.Name = "bannerOffLabel";
382 | this.bannerOffLabel.Size = new System.Drawing.Size(69, 13);
383 | this.bannerOffLabel.TabIndex = 34;
384 | this.bannerOffLabel.Text = "Grey Banner:";
385 | //
386 | // browseBannerOff
387 | //
388 | this.browseBannerOff.Location = new System.Drawing.Point(176, 68);
389 | this.browseBannerOff.Name = "browseBannerOff";
390 | this.browseBannerOff.Size = new System.Drawing.Size(62, 22);
391 | this.browseBannerOff.TabIndex = 4;
392 | this.browseBannerOff.Text = "Browse";
393 | this.browseBannerOff.UseVisualStyleBackColor = true;
394 | this.browseBannerOff.Click += new System.EventHandler(this.browseBannerOff_Click);
395 | //
396 | // bannerOffDir
397 | //
398 | this.bannerOffDir.AllowDrop = true;
399 | this.bannerOffDir.Location = new System.Drawing.Point(9, 70);
400 | this.bannerOffDir.Name = "bannerOffDir";
401 | this.bannerOffDir.Size = new System.Drawing.Size(161, 20);
402 | this.bannerOffDir.TabIndex = 3;
403 | this.bannerOffDir.DragDrop += new System.Windows.Forms.DragEventHandler(this.Dir_DragDrop);
404 | this.bannerOffDir.DragEnter += new System.Windows.Forms.DragEventHandler(this.Dir_DragEnter);
405 | this.bannerOffDir.LostFocus += new System.EventHandler(this.bannerDir_LostFocus);
406 | //
407 | // pc98Settings
408 | //
409 | this.pc98Settings.Controls.Add(this.openNP2Folder);
410 | this.pc98Settings.Controls.Add(this.launchHDI);
411 | this.pc98Settings.Controls.Add(this.hdiLabel);
412 | this.pc98Settings.Controls.Add(this.browseHDI);
413 | this.pc98Settings.Controls.Add(this.hdiDir);
414 | this.pc98Settings.Location = new System.Drawing.Point(335, 127);
415 | this.pc98Settings.Name = "pc98Settings";
416 | this.pc98Settings.Size = new System.Drawing.Size(244, 107);
417 | this.pc98Settings.TabIndex = 2;
418 | this.pc98Settings.TabStop = false;
419 | this.pc98Settings.Text = "PC-98 Game Settings";
420 | //
421 | // openNP2Folder
422 | //
423 | this.openNP2Folder.AutoEllipsis = true;
424 | this.openNP2Folder.Location = new System.Drawing.Point(9, 80);
425 | this.openNP2Folder.Name = "openNP2Folder";
426 | this.openNP2Folder.Size = new System.Drawing.Size(229, 23);
427 | this.openNP2Folder.TabIndex = 3;
428 | this.openNP2Folder.Text = "Open Neko Project II Folder";
429 | this.openNP2Folder.UseVisualStyleBackColor = true;
430 | this.openNP2Folder.Click += new System.EventHandler(this.openNP2Folder_Click);
431 | //
432 | // launchHDI
433 | //
434 | this.launchHDI.AutoEllipsis = true;
435 | this.launchHDI.Location = new System.Drawing.Point(183, 58);
436 | this.launchHDI.Name = "launchHDI";
437 | this.launchHDI.Size = new System.Drawing.Size(55, 22);
438 | this.launchHDI.TabIndex = 2;
439 | this.launchHDI.Text = "Launch";
440 | this.launchHDI.UseVisualStyleBackColor = true;
441 | this.launchHDI.Click += new System.EventHandler(this.launchHDI_Click);
442 | //
443 | // hdiLabel
444 | //
445 | this.hdiLabel.AutoSize = true;
446 | this.hdiLabel.Location = new System.Drawing.Point(6, 16);
447 | this.hdiLabel.Name = "hdiLabel";
448 | this.hdiLabel.Size = new System.Drawing.Size(60, 13);
449 | this.hdiLabel.TabIndex = 22;
450 | this.hdiLabel.Text = "Game HDI:";
451 | //
452 | // browseHDI
453 | //
454 | this.browseHDI.Location = new System.Drawing.Point(9, 58);
455 | this.browseHDI.Name = "browseHDI";
456 | this.browseHDI.Size = new System.Drawing.Size(62, 22);
457 | this.browseHDI.TabIndex = 1;
458 | this.browseHDI.Text = "Browse";
459 | this.browseHDI.UseVisualStyleBackColor = true;
460 | this.browseHDI.Click += new System.EventHandler(this.browseHDI_Click);
461 | //
462 | // hdiDir
463 | //
464 | this.hdiDir.AllowDrop = true;
465 | this.hdiDir.Location = new System.Drawing.Point(9, 32);
466 | this.hdiDir.Name = "hdiDir";
467 | this.hdiDir.Size = new System.Drawing.Size(229, 20);
468 | this.hdiDir.TabIndex = 0;
469 | this.hdiDir.DragDrop += new System.Windows.Forms.DragEventHandler(this.Dir_DragDrop);
470 | this.hdiDir.DragEnter += new System.Windows.Forms.DragEventHandler(this.Dir_DragEnter);
471 | this.hdiDir.LostFocus += new System.EventHandler(this.Dir_LostFocus);
472 | //
473 | // bannerSettings
474 | //
475 | this.bannerSettings.Controls.Add(this.chkCustomText);
476 | this.bannerSettings.Controls.Add(this.btnCustomText);
477 | this.bannerSettings.Controls.Add(this.bannerSize);
478 | this.bannerSettings.Controls.Add(this.bannerOnLabel);
479 | this.bannerSettings.Controls.Add(this.chkCustomBanner);
480 | this.bannerSettings.Controls.Add(this.bannerOffLabel);
481 | this.bannerSettings.Controls.Add(this.bannerOnDir);
482 | this.bannerSettings.Controls.Add(this.browseBannerOff);
483 | this.bannerSettings.Controls.Add(this.browseBannerOn);
484 | this.bannerSettings.Controls.Add(this.bannerOffDir);
485 | this.bannerSettings.Location = new System.Drawing.Point(335, 3);
486 | this.bannerSettings.Name = "bannerSettings";
487 | this.bannerSettings.Size = new System.Drawing.Size(244, 120);
488 | this.bannerSettings.TabIndex = 1;
489 | this.bannerSettings.TabStop = false;
490 | this.bannerSettings.Text = "Banner Settings";
491 | //
492 | // chkCustomText
493 | //
494 | this.chkCustomText.AutoSize = true;
495 | this.chkCustomText.Location = new System.Drawing.Point(110, 97);
496 | this.chkCustomText.Name = "chkCustomText";
497 | this.chkCustomText.Size = new System.Drawing.Size(128, 17);
498 | this.chkCustomText.TabIndex = 6;
499 | this.chkCustomText.Text = "Use custom text color";
500 | this.chkCustomText.UseVisualStyleBackColor = true;
501 | this.chkCustomText.CheckedChanged += new System.EventHandler(this.chkCustomText_CheckedChanged);
502 | //
503 | // btnCustomText
504 | //
505 | this.btnCustomText.Location = new System.Drawing.Point(9, 93);
506 | this.btnCustomText.Name = "btnCustomText";
507 | this.btnCustomText.Size = new System.Drawing.Size(95, 22);
508 | this.btnCustomText.TabIndex = 5;
509 | this.btnCustomText.Text = "Set Color";
510 | this.btnCustomText.UseVisualStyleBackColor = true;
511 | this.btnCustomText.Click += new System.EventHandler(this.btnCustomText_Click);
512 | //
513 | // bannerSize
514 | //
515 | this.bannerSize.AutoSize = true;
516 | this.bannerSize.Location = new System.Drawing.Point(183, 54);
517 | this.bannerSize.Name = "bannerSize";
518 | this.bannerSize.Size = new System.Drawing.Size(55, 13);
519 | this.bannerSize.TabIndex = 35;
520 | this.bannerSize.Text = "* 120 x 44";
521 | //
522 | // windowsSettings
523 | //
524 | this.windowsSettings.Controls.Add(this.crapCfg);
525 | this.windowsSettings.Controls.Add(this.crapGame);
526 | this.windowsSettings.Controls.Add(this.openAppdata);
527 | this.windowsSettings.Controls.Add(this.jpLabel);
528 | this.windowsSettings.Controls.Add(this.openvpatch);
529 | this.windowsSettings.Controls.Add(this.enApplocale);
530 | this.windowsSettings.Controls.Add(this.jpDir);
531 | this.windowsSettings.Controls.Add(this.crapApplocale);
532 | this.windowsSettings.Controls.Add(this.enDir);
533 | this.windowsSettings.Controls.Add(this.defaultApplocale);
534 | this.windowsSettings.Controls.Add(this.customDir);
535 | this.windowsSettings.Controls.Add(this.customApplocale);
536 | this.windowsSettings.Controls.Add(this.browseJP);
537 | this.windowsSettings.Controls.Add(this.launchcrap);
538 | this.windowsSettings.Controls.Add(this.enLabel);
539 | this.windowsSettings.Controls.Add(this.customLabel);
540 | this.windowsSettings.Controls.Add(this.crapLabel);
541 | this.windowsSettings.Controls.Add(this.openReplays);
542 | this.windowsSettings.Controls.Add(this.browseEN);
543 | this.windowsSettings.Controls.Add(this.launchJP);
544 | this.windowsSettings.Controls.Add(this.browseCustom);
545 | this.windowsSettings.Controls.Add(this.launchEN);
546 | this.windowsSettings.Controls.Add(this.jpApplocale);
547 | this.windowsSettings.Controls.Add(this.launchCustom);
548 | this.windowsSettings.Controls.Add(this.defaultExec);
549 | this.windowsSettings.Controls.Add(this.defaultLabel);
550 | this.windowsSettings.Location = new System.Drawing.Point(3, 3);
551 | this.windowsSettings.Name = "windowsSettings";
552 | this.windowsSettings.Size = new System.Drawing.Size(328, 255);
553 | this.windowsSettings.TabIndex = 0;
554 | this.windowsSettings.TabStop = false;
555 | this.windowsSettings.Text = "Windows Game Settings";
556 | //
557 | // crapCfg
558 | //
559 | this.crapCfg.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
560 | this.crapCfg.FormattingEnabled = true;
561 | this.crapCfg.Items.AddRange(new object[] {
562 | "None"});
563 | this.crapCfg.Location = new System.Drawing.Point(128, 171);
564 | this.crapCfg.Name = "crapCfg";
565 | this.crapCfg.Size = new System.Drawing.Size(130, 21);
566 | this.crapCfg.TabIndex = 15;
567 | this.crapCfg.SelectedIndexChanged += new System.EventHandler(this.crapCfg_SelectedIndexChanged);
568 | //
569 | // crapGame
570 | //
571 | this.crapGame.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
572 | this.crapGame.FormattingEnabled = true;
573 | this.crapGame.Items.AddRange(new object[] {
574 | "None"});
575 | this.crapGame.Location = new System.Drawing.Point(6, 171);
576 | this.crapGame.Name = "crapGame";
577 | this.crapGame.Size = new System.Drawing.Size(116, 21);
578 | this.crapGame.TabIndex = 14;
579 | this.crapGame.SelectedIndexChanged += new System.EventHandler(this.crapCfg_SelectedIndexChanged);
580 | //
581 | // openAppdata
582 | //
583 | this.openAppdata.AutoEllipsis = true;
584 | this.openAppdata.Location = new System.Drawing.Point(9, 227);
585 | this.openAppdata.Name = "openAppdata";
586 | this.openAppdata.Size = new System.Drawing.Size(91, 23);
587 | this.openAppdata.TabIndex = 19;
588 | this.openAppdata.Text = "Appdata Folder";
589 | this.openAppdata.UseVisualStyleBackColor = true;
590 | this.openAppdata.Click += new System.EventHandler(this.openAppdata_Click);
591 | //
592 | // ConfigForm
593 | //
594 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
595 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
596 | this.ClientSize = new System.Drawing.Size(584, 262);
597 | this.Controls.Add(this.windowsSettings);
598 | this.Controls.Add(this.bannerSettings);
599 | this.Controls.Add(this.openFolder);
600 | this.Controls.Add(this.pc98Settings);
601 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
602 | this.Icon = global::Touhou_Launcher.Properties.Resources.thicon;
603 | this.MaximizeBox = false;
604 | this.Name = "ConfigForm";
605 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
606 | this.Text = "Game Configuration: ";
607 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ConfigForm_Closing);
608 | this.Load += new System.EventHandler(this.ConfigForm_Load);
609 | this.pc98Settings.ResumeLayout(false);
610 | this.pc98Settings.PerformLayout();
611 | this.bannerSettings.ResumeLayout(false);
612 | this.bannerSettings.PerformLayout();
613 | this.windowsSettings.ResumeLayout(false);
614 | this.windowsSettings.PerformLayout();
615 | this.ResumeLayout(false);
616 |
617 | }
618 |
619 | #endregion
620 |
621 | private System.Windows.Forms.Button openFolder;
622 | private System.Windows.Forms.Button openvpatch;
623 | private System.Windows.Forms.TextBox jpDir;
624 | private System.Windows.Forms.TextBox enDir;
625 | private System.Windows.Forms.TextBox customDir;
626 | private System.Windows.Forms.Button browseJP;
627 | private System.Windows.Forms.Label jpLabel;
628 | private System.Windows.Forms.Label enLabel;
629 | private System.Windows.Forms.Label customLabel;
630 | private System.Windows.Forms.Button openReplays;
631 | private System.Windows.Forms.Button browseEN;
632 | private System.Windows.Forms.Button browseCustom;
633 | private System.Windows.Forms.CheckBox jpApplocale;
634 | private System.Windows.Forms.ComboBox defaultExec;
635 | private System.Windows.Forms.Label defaultLabel;
636 | private System.Windows.Forms.Button launchCustom;
637 | private System.Windows.Forms.Button launchEN;
638 | private System.Windows.Forms.Button launchJP;
639 | private System.Windows.Forms.Button launchcrap;
640 | private System.Windows.Forms.Label crapLabel;
641 | private System.Windows.Forms.CheckBox customApplocale;
642 | private System.Windows.Forms.CheckBox defaultApplocale;
643 | private System.Windows.Forms.CheckBox crapApplocale;
644 | private System.Windows.Forms.CheckBox enApplocale;
645 | private System.Windows.Forms.CheckBox chkCustomBanner;
646 | private System.Windows.Forms.Label bannerOnLabel;
647 | private System.Windows.Forms.Button browseBannerOn;
648 | private System.Windows.Forms.TextBox bannerOnDir;
649 | private System.Windows.Forms.Label bannerOffLabel;
650 | private System.Windows.Forms.Button browseBannerOff;
651 | private System.Windows.Forms.TextBox bannerOffDir;
652 | private System.Windows.Forms.GroupBox pc98Settings;
653 | private System.Windows.Forms.Button launchHDI;
654 | private System.Windows.Forms.Label hdiLabel;
655 | private System.Windows.Forms.Button browseHDI;
656 | private System.Windows.Forms.TextBox hdiDir;
657 | private System.Windows.Forms.GroupBox bannerSettings;
658 | private System.Windows.Forms.GroupBox windowsSettings;
659 | private System.Windows.Forms.Button openAppdata;
660 | private System.Windows.Forms.Button openNP2Folder;
661 | private System.Windows.Forms.Label bannerSize;
662 | private System.Windows.Forms.ComboBox crapGame;
663 | private System.Windows.Forms.ComboBox crapCfg;
664 | private System.Windows.Forms.CheckBox chkCustomText;
665 | private System.Windows.Forms.Button btnCustomText;
666 | }
667 | }
668 |
--------------------------------------------------------------------------------
/Touhou Launcher/ConfigForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Windows.Forms;
9 | using System.IO;
10 | using System.Diagnostics;
11 | using Newtonsoft.Json;
12 |
13 | namespace Touhou_Launcher
14 | {
15 | public partial class ConfigForm : Form
16 | {
17 | public int game;
18 | Button parentButton;
19 | Dictionary crap = new Dictionary();
20 |
21 | public ConfigForm(Button parentBtn)
22 | {
23 | InitializeComponent();
24 | parentButton = parentBtn;
25 | game = MainForm.nameToID[parentBtn.Name.Substring(3)];
26 | InitializeLanguage();
27 | chkCustomBanner.Checked = MainForm.curCfg.gameCFG[game].customBanner;
28 | bannerOffDir.Text = MainForm.curCfg.gameCFG[game].bannerOff;
29 | bannerOnDir.Text = MainForm.curCfg.gameCFG[game].bannerOn;
30 | chkCustomText.Checked = MainForm.curCfg.gameCFG[game].customText;
31 | }
32 |
33 | private void ConfigForm_Load(object sender, EventArgs e)
34 | {
35 | if (game > 4)
36 | {
37 | foreach (Control ctrl in pc98Settings.Controls)
38 | ctrl.Enabled = false;
39 | jpDir.Text = MainForm.curCfg.gameCFG[game].GameDir[0];
40 | jpApplocale.Checked = MainForm.curCfg.gameCFG[game].appLocale[0];
41 | enDir.Text = MainForm.curCfg.gameCFG[game].GameDir[1];
42 | enApplocale.Checked = MainForm.curCfg.gameCFG[game].appLocale[1];
43 | customDir.Text = MainForm.curCfg.gameCFG[game].GameDir[2];
44 | customApplocale.Checked = MainForm.curCfg.gameCFG[game].appLocale[2];
45 | Refreshcrap();
46 | crapApplocale.Checked = MainForm.curCfg.gameCFG[game].appLocale[3];
47 | defaultExec.SelectedIndex = MainForm.curCfg.gameCFG[game].DefaultDir;
48 | defaultApplocale.Checked = MainForm.curCfg.gameCFG[game].DefaultApplocale;
49 | }
50 | else
51 | {
52 | foreach (Control ctrl in windowsSettings.Controls)
53 | {
54 | ctrl.Enabled = false;
55 | }
56 | hdiDir.Text = MainForm.curCfg.gameCFG[game].GameDir[0];
57 | }
58 | }
59 |
60 | public void Refreshcrap()
61 | {
62 | crapCfg.Items.Clear();
63 | crapCfg.Items.Add("None");
64 | crapGame.Items.Clear();
65 | crapGame.Items.Add("None");
66 | if (MainForm.curCfg.crapDir != "")
67 | {
68 | if (File.Exists(MainForm.curCfg.crapDir + "\\config\\games.js"))
69 | {
70 | crap = JsonConvert.DeserializeObject>(File.ReadAllText(MainForm.curCfg.crapDir + "\\config\\games.js"));
71 | foreach (KeyValuePair line in crap)
72 | {
73 | int number = Int32.TryParse(new String(line.Key.Where(Char.IsDigit).ToArray()), out number) ? number : 0;
74 | if (number == MainForm.idToNumber[game] || !line.Key.StartsWith("th"))
75 | {
76 | crapGame.Items.Add(line.Key);
77 | }
78 | }
79 | }
80 | foreach (FileInfo file in new DirectoryInfo(MainForm.curCfg.crapDir).CreateSubdirectory("config").GetFiles("*.js").Where(n => n.Name != "games.js" && n.Name != "config.js"))
81 | {
82 | crapCfg.Items.Add(file.Name);
83 | }
84 | }
85 | if (MainForm.curCfg.crapDir != "")
86 | crapCfg.Items.Add("Custom");
87 | crapGame.SelectedIndexChanged -= crapCfg_SelectedIndexChanged;
88 | crapCfg.SelectedIndexChanged -= crapCfg_SelectedIndexChanged;
89 | crapGame.SelectedItem = MainForm.curCfg.gameCFG[game].crapCFG[0];
90 | crapCfg.SelectedItem = MainForm.curCfg.gameCFG[game].crapCFG[1];
91 | crapGame.SelectedIndexChanged += crapCfg_SelectedIndexChanged;
92 | crapCfg.SelectedIndexChanged += crapCfg_SelectedIndexChanged;
93 | }
94 |
95 | private void InitializeLanguage()
96 | {
97 | foreach (Button btn in MainForm.GetAll(this, typeof(Button)))
98 | {
99 | if (btn.Name.Contains("browse"))
100 | btn.Text = MainForm.rm.GetString("browse");
101 | else if (btn.Name.Contains("launch"))
102 | btn.Text = MainForm.rm.GetString("launch");
103 | else
104 | btn.Text = MainForm.rm.GetString(btn.Name);
105 | }
106 | foreach (CheckBox chk in MainForm.GetAll(this, typeof(CheckBox)))
107 | {
108 | if (chk.Name.Contains("Applocale"))
109 | chk.Text = MainForm.rm.GetString("useApplocale");
110 | else
111 | chk.Text = MainForm.rm.GetString(chk.Name);
112 | }
113 | foreach (Label lbl in MainForm.GetAll(this, typeof(Label)))
114 | {
115 | lbl.Text = MainForm.rm.GetString(lbl.Name);
116 | }
117 | foreach (GroupBox box in MainForm.GetAll(this, typeof(GroupBox)))
118 | {
119 | box.Text = MainForm.rm.GetString(box.Name);
120 | }
121 | defaultExec.Items.Clear();
122 | defaultExec.Items.AddRange(MainForm.rm.GetString("defaultExec").Split(new string[] {", "}, 4, StringSplitOptions.None));
123 | this.Text = MainForm.rm.GetString("gameConfiguration") + MainForm.rm.GetString(MainForm.nameToID.FirstOrDefault(t => t.Value == game).Key);
124 | }
125 |
126 | private void ConfigForm_Closing(object sender, FormClosingEventArgs e)
127 | {
128 | this.Focus();
129 | if (MainForm.curCfg.gameCFG[game].GameDir[MainForm.curCfg.gameCFG[game].DefaultDir] == "")
130 | for (int i = 0; i < MainForm.curCfg.gameCFG[game].GameDir.Count; i++)
131 | {
132 | if (MainForm.curCfg.gameCFG[game].GameDir[i] != "")
133 | {
134 | MainForm.curCfg.gameCFG[game].DefaultDir = i;
135 | break;
136 | }
137 | }
138 | MainForm.RefreshButton(parentButton);
139 | MainForm.curCfg.Save();
140 | }
141 |
142 | private void Dir_LostFocus(object sender, EventArgs e)
143 | {
144 | if (File.Exists(((TextBox)sender).Text) || ((TextBox)sender).Text == "")
145 | {
146 | ((TextBox)sender).BackColor = SystemColors.Window;
147 | int dirID = game > 4 ? MainForm.dirToNumber[((TextBox)sender).Name.Replace("Dir", "")] : 0;
148 | MainForm.curCfg.gameCFG[game].GameDir[dirID] = ((TextBox)sender).Text;
149 | }
150 | else
151 | {
152 | ((TextBox)sender).BackColor = Color.Red;
153 | }
154 | }
155 |
156 | private void Dir_DragEnter(object sender, DragEventArgs e)
157 | {
158 | if (e.Data.GetDataPresent(DataFormats.FileDrop))
159 | e.Effect = DragDropEffects.Copy;
160 | }
161 |
162 | private void Dir_DragDrop(object sender, DragEventArgs e)
163 | {
164 | ((TextBox)sender).Text = ((string[])e.Data.GetData(DataFormats.FileDrop)).FirstOrDefault(n => File.Exists(n));
165 | if (((TextBox)sender).Name.Contains("banner"))
166 | bannerDir_LostFocus(sender, new EventArgs());
167 | else
168 | Dir_LostFocus(sender, new EventArgs());
169 | }
170 |
171 | private void Applocale_CheckedChanged(object sender, EventArgs e)
172 | {
173 | MainForm.curCfg.gameCFG[game].appLocale[MainForm.dirToNumber[((CheckBox)sender).Name.Replace("Applocale", "")]] = ((CheckBox)sender).Checked;
174 | }
175 |
176 | private void browse_Click(object sender, EventArgs e)
177 | {
178 | Control txtBox = windowsSettings.Controls.Find(((Button)sender).Name.ToLower().Substring(6) + "Dir", false).FirstOrDefault(n => n.GetType() == typeof(TextBox));
179 | foreach (string path in MainForm.FileBrowser(MainForm.rm.GetString("gameSelectTitle"), MainForm.rm.GetString("executableFilter") + " (*.exe, *.bat, *.lnk)|*.exe;*.bat;*.lnk|" + MainForm.rm.GetString("allFilter") + " (*.*)|*.*"))
180 | {
181 | int type = MainForm.dirToNumber[txtBox.Name.Replace("Dir", "")];
182 | txtBox.Text = path;
183 | MainForm.curCfg.gameCFG[game].GameDir[type] = path;
184 | string jpPath = Path.GetDirectoryName(path) + "\\th" + (MainForm.idToNumber[game]).ToString("00") + ".exe";
185 | string enPath = Path.GetDirectoryName(path) + "\\th" + (MainForm.idToNumber[game]).ToString("00") + "e.exe";
186 | string customPath = Path.GetDirectoryName(path);
187 | customPath += MainForm.idToNumber[game] == 75 ? "\\Config.exe" : "\\custom.exe";
188 | if (type != 0 && File.Exists(jpPath) && MainForm.curCfg.gameCFG[game].GameDir[0] == "")
189 | {
190 | jpDir.Text = jpPath;
191 | MainForm.curCfg.gameCFG[game].GameDir[0] = jpPath;
192 | }
193 | if (type != 1 && File.Exists(enPath) && MainForm.curCfg.gameCFG[game].GameDir[1] == "")
194 | {
195 | enDir.Text = enPath;
196 | MainForm.curCfg.gameCFG[game].GameDir[1] = enPath;
197 | }
198 | if (type != 2 && File.Exists(customPath) && MainForm.curCfg.gameCFG[game].GameDir[2] == "")
199 | {
200 | customDir.Text = customPath;
201 | MainForm.curCfg.gameCFG[game].GameDir[2] = customPath;
202 | }
203 | break;
204 | }
205 | }
206 |
207 | private void launch_Click(object sender, EventArgs e)
208 | {
209 | int dir = MainForm.dirToNumber[((Button)sender).Name.ToLower().Substring(6)];
210 | MainForm.launchGame(game, dir, MainForm.curCfg.gameCFG[game].appLocale[dir]);
211 | }
212 |
213 | private void crapCfg_SelectedIndexChanged(object sender, EventArgs e)
214 | {
215 | MainForm.curCfg.gameCFG[game].crapCFG[0] = crapGame.SelectedItem.ToString();
216 | if (crapCfg.SelectedItem.ToString() == "Custom")
217 | {
218 | thcrap profileConfig = new thcrap(this);
219 | profileConfig.ShowDialog();
220 | }
221 | else
222 | MainForm.curCfg.gameCFG[game].crapCFG[1] = crapCfg.SelectedItem.ToString();
223 | if (crap.ContainsKey(MainForm.curCfg.gameCFG[game].crapCFG[0]))
224 | MainForm.curCfg.gameCFG[game].GameDir[3] = MainForm.curCfg.gameCFG[game].crapCFG[0] != "None" ? crap[MainForm.curCfg.gameCFG[game].crapCFG[0]] : "";
225 | }
226 |
227 | private void launchcrap_Click(object sender, EventArgs e)
228 | {
229 | MainForm.launchcrap(game);
230 | }
231 |
232 | private void defaultExec_SelectedIndexChanged(object sender, EventArgs e)
233 | {
234 | MainForm.curCfg.gameCFG[game].DefaultDir = defaultExec.SelectedIndex;
235 | }
236 |
237 | private void defaultApplocale_CheckedChanged(object sender, EventArgs e)
238 | {
239 | MainForm.curCfg.gameCFG[game].DefaultApplocale = defaultApplocale.Checked;
240 | }
241 |
242 | private void browseBannerOn_Click(object sender, EventArgs e)
243 | {
244 | foreach (string file in MainForm.FileBrowser(MainForm.rm.GetString("bannerOnSelectTitle"), MainForm.rm.GetString("imageFilter") + " (*.png, *.jpg, *.bmp)|*.png;*.jpg;*.bmp|" + MainForm.rm.GetString("allFilter") + " (*.*)|*.*"))
245 | {
246 | try
247 | {
248 | Image.FromFile(file);
249 | MainForm.curCfg.gameCFG[game].bannerOn = file;
250 | bannerOnDir.Text = file;
251 | }
252 | catch (OutOfMemoryException ex)
253 | {
254 | MessageBox.Show(MainForm.rm.GetString("errorOpenImage") + ex);
255 | }
256 | }
257 | }
258 |
259 | private void browseBannerOff_Click(object sender, EventArgs e)
260 | {
261 | foreach (string file in MainForm.FileBrowser(MainForm.rm.GetString("bannerOffSelectTitle"), MainForm.rm.GetString("imageFilter") + " (*.png, *.jpg, *.bmp)|*.png;*.jpg;*.bmp|" + MainForm.rm.GetString("allFilter") + " (*.*)|*.*"))
262 | {
263 | try
264 | {
265 | Image.FromFile(file);
266 | MainForm.curCfg.gameCFG[game].bannerOff = file;
267 | bannerOffDir.Text = file;
268 | }
269 | catch (OutOfMemoryException ex)
270 | {
271 | MessageBox.Show(MainForm.rm.GetString("errorOpenImage") + ex);
272 | }
273 | }
274 | }
275 |
276 | private void bannerDir_LostFocus(object sender, EventArgs e)
277 | {
278 | bool onTxtBox = ((TextBox)sender).Name.Contains("On");
279 | if (((TextBox)sender).Text != "")
280 | {
281 | try
282 | {
283 | Image.FromFile(((TextBox)sender).Text);
284 | }
285 | catch (OutOfMemoryException ex)
286 | {
287 | ((TextBox)sender).BackColor = SystemColors.Window;
288 | MessageBox.Show(MainForm.rm.GetString("errorOpenImage") + ex);
289 | }
290 | catch (FileNotFoundException)
291 | {
292 | ((TextBox)sender).BackColor = Color.Red;
293 | }
294 | }
295 | else
296 | ((TextBox)sender).BackColor = SystemColors.Window;
297 | if (onTxtBox)
298 | MainForm.curCfg.gameCFG[game].bannerOn = ((TextBox)sender).Text;
299 | else
300 | MainForm.curCfg.gameCFG[game].bannerOff = ((TextBox)sender).Text;
301 | }
302 |
303 | private void chkCustomBanner_CheckedChanged(object sender, EventArgs e)
304 | {
305 | MainForm.curCfg.gameCFG[game].customBanner = chkCustomBanner.Checked;
306 | }
307 |
308 | private void chkCustomText_CheckedChanged(object sender, EventArgs e)
309 | {
310 | MainForm.curCfg.gameCFG[game].customText = chkCustomText.Checked;
311 | }
312 |
313 | private void btnCustomText_Click(object sender, EventArgs e)
314 | {
315 | ColorDialog colorSet = new ColorDialog();
316 | colorSet.Color = Color.FromArgb(MainForm.curCfg.gameCFG[game].textColor);
317 | if (colorSet.ShowDialog() == System.Windows.Forms.DialogResult.OK)
318 | MainForm.curCfg.gameCFG[game].textColor = colorSet.Color.ToArgb();
319 | }
320 |
321 | private void browseHDI_Click(object sender, EventArgs e)
322 | {
323 | foreach (string file in MainForm.FileBrowser(MainForm.rm.GetString("hdiSelectTitle"), MainForm.rm.GetString("hdiFilter") + " (*.hdi)|*.hdi|" + MainForm.rm.GetString("allFilter") + " (*.*)|*.*"))
324 | {
325 | hdiDir.Text = file;
326 | MainForm.curCfg.gameCFG[game].GameDir[0] = file;
327 | }
328 | }
329 |
330 | private void launchHDI_Click(object sender, EventArgs e)
331 | {
332 | MainForm.launchHDI(MainForm.curCfg.gameCFG[game].GameDir[0]);
333 | }
334 |
335 | private void openFolder_Click(object sender, EventArgs e)
336 | {
337 | string path = "";
338 | if (game > 4)
339 | {
340 | foreach (TextBox dir in MainForm.GetAll(windowsSettings, typeof(TextBox)))
341 | {
342 | if (dir.Text != "")
343 | {
344 | path = Path.GetDirectoryName(dir.Text);
345 | if (Directory.Exists(path))
346 | break;
347 | }
348 | }
349 | }
350 | else
351 | {
352 | if (hdiDir.Text != "")
353 | {
354 | if (Directory.Exists(Path.GetDirectoryName(hdiDir.Text)))
355 | path = Path.GetDirectoryName(hdiDir.Text);
356 | }
357 | }
358 | if (path != "")
359 | Process.Start(path);
360 | }
361 |
362 | private void openAppdata_Click(object sender, EventArgs e)
363 | {
364 | string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData, Environment.SpecialFolderOption.DoNotVerify) + "\\ShanghaiAlice\\th" + (MainForm.idToNumber[game]).ToString("00");
365 | if (Directory.Exists(path))
366 | Process.Start(path);
367 | else if (Directory.Exists(path + "tr"))
368 | Process.Start(path + "tr");
369 | else
370 | MessageBox.Show(MainForm.rm.GetString("errorAppdataNotFound"));
371 | }
372 |
373 | private void openReplays_Click(object sender, EventArgs e)
374 | {
375 | string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData, Environment.SpecialFolderOption.DoNotVerify) + "\\ShanghaiAlice\\th";
376 | if (Directory.Exists(path + MainForm.idToNumber[game].ToString("00") + "\\replay"))
377 | {
378 | Process.Start(path + MainForm.idToNumber[game].ToString("00") + "\\replay");
379 | return;
380 | }
381 | else if (Directory.Exists(path + MainForm.idToNumber[game].ToString("00") + "tr\\replay"))
382 | {
383 | Process.Start(path + MainForm.idToNumber[game].ToString("00") + "tr\\replay");
384 | return;
385 | }
386 | else
387 | {
388 | foreach (TextBox dir in MainForm.GetAll(windowsSettings, typeof(TextBox)))
389 | {
390 | if (dir.Text != "")
391 | {
392 | string path2 = Path.GetDirectoryName(dir.Text) + "\\replay";
393 | if (Directory.Exists(path2))
394 | {
395 | Process.Start(path2);
396 | return;
397 | }
398 | }
399 | }
400 | }
401 | MessageBox.Show(MainForm.rm.GetString("errorReplaysNotFound"));
402 | }
403 |
404 | private void openvpatch_Click(object sender, EventArgs e)
405 | {
406 | foreach (TextBox txt in windowsSettings.Controls.OfType())
407 | {
408 | if (txt.Text != "")
409 | {
410 | string path = Path.GetDirectoryName(txt.Text) + "\\vpatch.ini";
411 | if (File.Exists(path))
412 | {
413 | Process.Start(path);
414 | return;
415 | }
416 | }
417 | }
418 | MessageBox.Show(MainForm.rm.GetString("errorvpatchNotFound"));
419 | }
420 |
421 | private void openNP2Folder_Click(object sender, EventArgs e)
422 | {
423 | if (MainForm.curCfg.np2Dir != "")
424 | Process.Start(Path.GetDirectoryName(MainForm.curCfg.np2Dir));
425 | else
426 | MessageBox.Show(MainForm.rm.GetString("errorNP2NotFound"));
427 | }
428 | }
429 | }
430 |
--------------------------------------------------------------------------------
/Touhou Launcher/ConfigForm.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 |
--------------------------------------------------------------------------------
/Touhou Launcher/MainForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 17
122 |
123 |
124 | 469, 17
125 |
126 |
127 | 17, 56
128 |
129 |
130 | 269, 17
131 |
132 |
133 | 172, 17
134 |
135 |
136 | Created by: David_Jones (DVN) (Started: 07/02/2019) (DD/MM/YYYY)
137 | Original Touhou Launcher created by: Widdiful
138 | Russian translation by: Lensrub
139 |
140 | This is a nonprofit project developed independently by a fan
141 | Touhou belongs to Team Shanghai Alice
142 |
143 | Thank you for using this program.
144 | I hope you'll enjoy it as much as I enjoyed making it.
145 |
146 | I guess I have a github now: https://github.com/David-JonesDVN/Touhou-Relauncher
147 | Use that if you have any feature requests, bug reports, etc.
148 | You can also probably find me in the touhou-launcher Discord/IRC server:
149 |
150 |
151 | 148, 56
152 |
153 |
154 | 252, 56
155 |
156 |
--------------------------------------------------------------------------------
/Touhou Launcher/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Windows.Forms;
5 |
6 | namespace Touhou_Launcher
7 | {
8 | static class Program
9 | {
10 | ///
11 | /// The main entry point for the application.
12 | ///
13 | [STAThread]
14 | static void Main()
15 | {
16 | Application.EnableVisualStyles();
17 | Application.SetCompatibleTextRenderingDefault(false);
18 | AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
19 | Application.Run(new MainForm());
20 | }
21 |
22 | static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
23 | {
24 | string str = "";
25 | if (args.Name.Contains("Newtonsoft.Json"))
26 | str = "Touhou_Launcher.jsonnet.Newtonsoft.Json.dll";
27 | if (str != "")
28 | {
29 | using (var stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(str))
30 | {
31 | try
32 | {
33 | var assemblyData = new Byte[stream.Length];
34 | stream.Read(assemblyData, 0, assemblyData.Length);
35 | return System.Reflection.Assembly.Load(assemblyData);
36 | }
37 | catch (System.IO.IOException)
38 | {
39 | return null;
40 | }
41 | catch (BadImageFormatException)
42 | {
43 | return null;
44 | }
45 | }
46 | }
47 | else
48 | return null;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Touhou Launcher/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Touhou Launcher")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("DVN")]
12 | [assembly: AssemblyProduct("Touhou Launcher")]
13 | [assembly: AssemblyCopyright("")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("bfba53c3-6a74-48c2-b5a7-894e2aa7d442")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.3.0")]
36 | [assembly: AssemblyFileVersion("1.0.3.0")]
37 |
--------------------------------------------------------------------------------
/Touhou Launcher/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 Touhou_Launcher.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
16 | public 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 | }
27 |
--------------------------------------------------------------------------------
/Touhou Launcher/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Touhou Launcher/Resources_en.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 | Antinomy of Common Flowers
122 |
123 |
124 | Touhou 15.5: Antinomy of Common Flowers
125 |
126 |
127 | Double Dealing Character
128 |
129 |
130 | Touhou 14: Double Dealing Character
131 |
132 |
133 | Double Spoiler
134 |
135 |
136 | Touhou 12.5: Double Spoiler
137 |
138 |
139 | Embodiment of Scarlet Devil
140 |
141 |
142 | Touhou 06: the Embodiment of Scarlet Devil
143 |
144 |
145 | Great Fairy Wars
146 |
147 |
148 | Touhou 12.8: Great Fairy Wars
149 |
150 |
151 | Hopeless Masquerade
152 |
153 |
154 | Touhou 13.5: Hopeless Masquerade
155 |
156 |
157 | Highly Responsive to Prayers
158 |
159 |
160 | Touhou 01: Highly Responsive to Prayers
161 |
162 |
163 | Hidden Star in Four Seasons
164 |
165 |
166 | Touhou 16: Hidden Star in Four Seasons
167 |
168 |
169 | Immaterial and Missing Power
170 |
171 |
172 | Touhou 7.5: Immaterial and Missing Power
173 |
174 |
175 | Imperishable Night
176 |
177 |
178 | Touhou 08: Imperishable Night
179 |
180 |
181 | Impossible Spell Card
182 |
183 |
184 | Touhou 14.3: Impossible Spell Card
185 |
186 |
187 | Lotus Land Story
188 |
189 |
190 | Touhou 04: Lotus Land Story
191 |
192 |
193 | Legacy of Lunatic Kingdom
194 |
195 |
196 | Touhou 15: Legacy of Lunatic Kingdom
197 |
198 |
199 | Mountain of Faith
200 |
201 |
202 | Touhou 10: Mountain of Faith
203 |
204 |
205 | Mystic Square
206 |
207 |
208 | Touhou 05: Mystic Square
209 |
210 |
211 | Perfect Cherry Blossom
212 |
213 |
214 | Touhou 07: Perfect Cherry Blossom
215 |
216 |
217 | Phantasmagoria of Dim. Dream
218 |
219 |
220 | Touhou 03: Phantasmagoria of Dim. Dream
221 |
222 |
223 | Phantasmagoria of Flower View
224 |
225 |
226 | Touhou 09: Phantasmagoria of Flower View
227 |
228 |
229 | Subterranean Animism
230 |
231 |
232 | Touhou 11: Subterranean Animism
233 |
234 |
235 | Story of Eastern Wonderland
236 |
237 |
238 | Touhou 02: the Story of Eastern Wonderland
239 |
240 |
241 | Shoot the Bullet
242 |
243 |
244 | Touhou 9.5: Shoot the Bullet
245 |
246 |
247 | Scarlet Weather Rhapsody
248 |
249 |
250 | Touhou 10.5: Scarlet Weather Rhapsody
251 |
252 |
253 | Ten Desires
254 |
255 |
256 | Touhou 13: Ten Desires
257 |
258 |
259 | Undefined Fantastic Object
260 |
261 |
262 | Touhou 12: Undefined Fantastic Object
263 |
264 |
265 | Urban Legend in Limbo
266 |
267 |
268 | Touhou 14.5: Urban Legend in Limbo
269 |
270 |
271 | Hisoutensoku
272 |
273 |
274 | Touhou 12.3: Hisoutensoku
275 |
276 |
277 | Violet Detector
278 |
279 |
280 | Touhou 16.5: Violet Detector
281 |
282 |
283 | Random
284 |
285 |
286 | Run a Random Game
287 |
288 |
289 | Touhou Launcher
290 |
291 |
292 | Twilight Frontier Games
293 |
294 |
295 | Main Games
296 |
297 |
298 | PC-98 Games
299 |
300 |
301 | AoCF
302 |
303 |
304 | Auto-Close
305 |
306 |
307 | Automatically close the launcher after launching a game
308 |
309 |
310 | Grey Banner
311 |
312 |
313 | Colored Banner
314 |
315 |
316 | Banner Settings
317 |
318 |
319 | Browse
320 |
321 |
322 | Use custom banner
323 |
324 |
325 | Configure Game
326 |
327 |
328 | thcrap Profile:
329 |
330 |
331 | Add Game
332 |
333 |
334 | Custom Games
335 |
336 |
337 | Custom.exe:
338 |
339 |
340 | DDC
341 |
342 |
343 | Default Executable:
344 |
345 |
346 | Delete Category
347 |
348 |
349 | DS
350 |
351 |
352 | English Executable:
353 |
354 |
355 | EoSD
356 |
357 |
358 | Games
359 |
360 |
361 | GFW
362 |
363 |
364 | Game HDI:
365 |
366 |
367 | HM
368 |
369 |
370 | HRtP
371 |
372 |
373 | HSiFS
374 |
375 |
376 | IaMP
377 |
378 |
379 | Info
380 |
381 |
382 | IN
383 |
384 |
385 | ISC
386 |
387 |
388 | Japanese/vpatch Executable:
389 |
390 |
391 | Language:
392 |
393 |
394 | Launch
395 |
396 |
397 | Launcher Settings
398 |
399 |
400 | LLS
401 |
402 |
403 | LoLK
404 |
405 |
406 | MoF
407 |
408 |
409 | MS
410 |
411 |
412 | New Category
413 |
414 |
415 | Neko Project II Location:
416 |
417 |
418 | Open Folder
419 |
420 |
421 | Open Neko Project II Folder
422 |
423 |
424 | Open Replays Folder
425 |
426 |
427 | Edit vpatch.ini
428 |
429 |
430 | PC-98 Game Settings
431 |
432 |
433 | PCB
434 |
435 |
436 | PoDD
437 |
438 |
439 | PoFV
440 |
441 |
442 | Select All
443 |
444 |
445 | Games that will be included in the
446 | random game option:
447 |
448 |
449 | Select None
450 |
451 |
452 | Random Game Settings
453 |
454 |
455 | Rename Category
456 |
457 |
458 | Replays
459 |
460 |
461 | SA
462 |
463 |
464 | Settings
465 |
466 |
467 | SoEW
468 |
469 |
470 | StB
471 |
472 |
473 | SWR
474 |
475 |
476 | TD
477 |
478 |
479 | UFO
480 |
481 |
482 | ULiL
483 |
484 |
485 | Hisoutensoku
486 |
487 |
488 | With Applocale
489 |
490 |
491 | VD
492 |
493 |
494 | Windows Game Settings
495 |
496 |
497 | All Files
498 |
499 |
500 | Ascending
501 |
502 |
503 | Select the grey banner
504 |
505 |
506 | Select the colored banner
507 |
508 |
509 | Japanese/vpatch.ini, English (non-THCRAP), Custom.exe, thcrap
510 |
511 |
512 | Delete
513 |
514 |
515 | Descending
516 |
517 |
518 | Details
519 |
520 |
521 | Cannot find Appdata Folder
522 |
523 |
524 | File could not be found
525 |
526 |
527 | Please set Neko Project 2's location
528 |
529 |
530 | Cannot open file as image:
531 |
532 |
533 |
534 | Cannot find Replays folder
535 |
536 |
537 | Cannot find vpatch.ini
538 |
539 |
540 | Executable Files
541 |
542 |
543 | Select Executable
544 |
545 |
546 | Hard Disk Image Files
547 |
548 |
549 | Select the game's HDI
550 |
551 |
552 | Image Files
553 |
554 |
555 | Large Icons
556 |
557 |
558 | List
559 |
560 |
561 | Select Neko Project II's executable
562 |
563 |
564 | Appdata Folder
565 |
566 |
567 | Open Folder
568 |
569 |
570 | Open With Applocale
571 |
572 |
573 | Play Random
574 |
575 |
576 | Rename
577 |
578 |
579 | Small Icons
580 |
581 |
582 | Sort
583 |
584 |
585 | Tile
586 |
587 |
588 | View
589 |
590 |
591 | Neko Project II's configuration ini is not valid.
592 |
593 |
594 | Cannot find game. Please check the path in the right click menu.
595 |
596 |
597 | Replay Files
598 |
599 |
600 | Download '{0}' to:
601 | '{1}'
602 |
603 |
604 | Player replays full and Touhou 10 does not support user replays.
605 |
606 |
607 |
608 | Game Configuration:
609 |
610 |
611 | Minimize to tray
612 |
613 |
614 | Always show tray icon
615 |
616 |
617 | Delete Category '{0}' and all of its contents?
618 |
619 |
620 | Delete '{0}'?
621 |
622 |
623 | Please set thcrap's location
624 |
625 |
626 | Configure thcrap
627 |
628 |
629 | thcrap_loader Location:
630 |
631 |
632 | Please set thcrap's profile
633 |
634 |
635 | No Games Selected
636 |
637 |
638 | Download Replay?
639 |
640 |
641 | Exit
642 |
643 |
644 | Open
645 |
646 |
647 | Random Game
648 |
649 |
650 | Remove Game
651 |
652 |
653 | Description
654 |
655 |
656 | Game Profiles
657 |
658 |
659 | Game ID
660 |
661 |
662 | ID
663 |
664 |
665 | Patch
666 |
667 |
668 | Custom Profile
669 |
670 |
671 | Game Path
672 |
673 |
674 | Profile Configuration:
675 |
676 |
677 | Title
678 |
679 |
680 | Default
681 |
682 |
683 | thcrap Starting Repository:
684 |
685 |
686 | * 120 x 44
687 |
688 |
689 | Set Color
690 |
691 |
692 | Use custom text color
693 |
694 |
695 | Show banner?
696 |
697 |
698 | Edit Button
699 |
700 |
701 | Show Text?
702 |
703 |
704 | Selected Patches
705 |
706 |
707 | Wily Beast and Weakest Creature
708 |
709 |
710 | WBaWC
711 |
712 |
713 | Touhou 17: Wily Beast and Weakest Creature
714 |
715 |
716 | Unconnected Marketeers
717 |
718 |
719 | UM
720 |
721 |
722 | Touhou 18: Unconnected Marketeers
723 |
724 |
725 | Gouyoku Ibun
726 |
727 |
728 | GI
729 |
730 |
731 | Touhou 17.5: Gouyoku Ibun
732 |
733 |
734 | No Category Selected
735 |
736 |
737 | 100th Black Market
738 |
739 |
740 | 100BM
741 |
742 |
743 | Touhou 18.5: 100th Black Market
744 |
745 |
746 | Spinoffs
747 |
748 |
749 | Unfinished Dream of All Living Ghost
750 |
751 |
752 | UDoALG
753 |
754 |
755 | Touhou 19: Unfinished Dream of All Living Ghost
756 |
757 |
--------------------------------------------------------------------------------
/Touhou Launcher/Resources_jp.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 |
123 |
124 | 東方憑依華 ~ Antinomy of Common Flowers
125 |
126 |
127 | 東方輝針城
128 |
129 |
130 | 東方輝針城 ~ Double Dealing Character
131 |
132 |
133 | ダブルスポイラー
134 |
135 |
136 | ダブルスポイラー ~ 東方文花帖
137 |
138 |
139 | 東方紅魔郷
140 |
141 |
142 | 東方紅魔郷 ~ the Embodiment of Scarlet Devil
143 |
144 |
145 | 妖精大戦争
146 |
147 |
148 | 妖精大戦争 ~ 東方三月精
149 |
150 |
151 | 東方心綺楼
152 |
153 |
154 | 東方心綺楼 ~ Hopeless Masquerade
155 |
156 |
157 | 東方靈異伝
158 |
159 |
160 | 東方靈異伝 ~ Highly Responsive to Prayers
161 |
162 |
163 | 東方天空璋
164 |
165 |
166 | 東方天空璋 ~ Hidden Star in Four Seasons
167 |
168 |
169 | 東方萃夢想
170 |
171 |
172 | 東方萃夢想 ~ Immaterial and Missing Power
173 |
174 |
175 | 東方永夜抄
176 |
177 |
178 | 東方永夜抄 ~ Imperishable Night
179 |
180 |
181 | アマノジャク
182 |
183 |
184 | 弾幕アマノジャク ~ Impossible Spell Card
185 |
186 |
187 | 東方幻想郷
188 |
189 |
190 | 東方幻想郷 ~ Lotus Land Story
191 |
192 |
193 | 東方紺珠伝
194 |
195 |
196 | 東方紺珠伝 ~ Legacy of Lunatic Kingdom
197 |
198 |
199 | 東方風神録
200 |
201 |
202 | 東方風神録 ~ Mountain of Faith
203 |
204 |
205 | 東方怪綺談
206 |
207 |
208 | 東方怪綺談 ~ Mystic Square
209 |
210 |
211 | 東方妖々夢
212 |
213 |
214 | 東方妖々夢 ~ Perfect Cherry Blossom
215 |
216 |
217 | 東方夢時空
218 |
219 |
220 | 東方夢時空 ~ Phantasmagoria of Dim.Dream
221 |
222 |
223 | 東方花映塚
224 |
225 |
226 | 東方花映塚 ~ Phantasmagoria of Flower View
227 |
228 |
229 | 東方地霊殿
230 |
231 |
232 | 東方地霊殿 ~ Subterranean Animism
233 |
234 |
235 | 東方封魔録
236 |
237 |
238 | 東方封魔録 ~ the Story of Eastern Wonderland
239 |
240 |
241 | 東方文花帖
242 |
243 |
244 | 東方文花帖 ~ Shoot the Bullet
245 |
246 |
247 | 東方緋想天
248 |
249 |
250 | 東方緋想天 ~ Scarlet Weather Rhapsody
251 |
252 |
253 | 東方神霊廟
254 |
255 |
256 | 東方神霊廟 ~ Ten Desires
257 |
258 |
259 | 東方星蓮船
260 |
261 |
262 | 東方星蓮船 ~ Undefined Fantastic Object
263 |
264 |
265 | 東方深秘録
266 |
267 |
268 | 東方深秘録 ~ Urban Legend in Limbo
269 |
270 |
271 | 東方非想天則
272 |
273 |
274 | 東方非想天則 ~ 超弩級ギニョルの謎を追え
275 |
276 |
277 | 秘封ナイトメアダイアリー
278 |
279 |
280 | 秘封ナイトメアダイアリー 〜 Violet Detector
281 |
282 |
283 | ランダム
284 |
285 |
286 | ランダムでゲームを起動します
287 |
288 |
289 | 東方ランチャー
290 |
291 |
292 | 黄昏フロンティア作
293 |
294 |
295 | 整数作
296 |
297 |
298 | 旧作
299 |
300 |
301 | 憑依華
302 |
303 |
304 | 自動終了
305 |
306 |
307 | ゲームを起動した後、自動的にランチャーを閉じます
308 |
309 |
310 | バナー(白黒)
311 |
312 |
313 | バナー
314 |
315 |
316 | バナーの設定
317 |
318 |
319 | 参照
320 |
321 |
322 | カスタムバナーを使用
323 |
324 |
325 | 設定
326 |
327 |
328 | thcrapプロファイル:
329 |
330 |
331 | ゲームを追加
332 |
333 |
334 | 同人ゲーム
335 |
336 |
337 | Custom.exe:
338 |
339 |
340 | 輝針城
341 |
342 |
343 | デフォルトで開く:
344 |
345 |
346 | 削除
347 |
348 |
349 | ダブルスポイラー
350 |
351 |
352 | English Executable:
353 |
354 |
355 | 紅魔郷
356 |
357 |
358 | ゲーム
359 |
360 |
361 | 妖精大戦争
362 |
363 |
364 | HDIファイル:
365 |
366 |
367 | 心綺楼
368 |
369 |
370 | 靈異伝
371 |
372 |
373 | 天空璋
374 |
375 |
376 | 萃夢想
377 |
378 |
379 | 東方ランチャーについて
380 |
381 |
382 | 永夜抄
383 |
384 |
385 | アマノジャク
386 |
387 |
388 | 実行ファイルの場所:
389 |
390 |
391 | 言語:
392 |
393 |
394 | 起動
395 |
396 |
397 | 全般
398 |
399 |
400 | 幻想郷
401 |
402 |
403 | 紺珠伝
404 |
405 |
406 | 風神録
407 |
408 |
409 | 怪綺談
410 |
411 |
412 | 新規作成
413 |
414 |
415 | Neko Project IIの場所:
416 |
417 |
418 | フォルダを開く
419 |
420 |
421 | Neko Project IIのフォルダを開く
422 |
423 |
424 | replayフォルダ
425 |
426 |
427 | vpatch.iniを編集
428 |
429 |
430 | PC-98版用
431 |
432 |
433 | 妖々夢
434 |
435 |
436 | 夢時空
437 |
438 |
439 | 花映塚
440 |
441 |
442 | すべて
443 |
444 |
445 | ランダムで起動したいゲームを選んでください
446 |
447 |
448 | なし
449 |
450 |
451 | ランダム起動
452 |
453 |
454 | 名前の変更
455 |
456 |
457 | リプレイ
458 |
459 |
460 | 地霊殿
461 |
462 |
463 | 設定
464 |
465 |
466 | 封魔録
467 |
468 |
469 | 文花帖
470 |
471 |
472 | 緋想天
473 |
474 |
475 | 神霊廟
476 |
477 |
478 | 星蓮船
479 |
480 |
481 | 深秘録
482 |
483 |
484 | 非想天則
485 |
486 |
487 | AppLocaleで実行
488 |
489 |
490 | ナイトメアダイアリー
491 |
492 |
493 | Windows版用
494 |
495 |
496 | すべてのファイル
497 |
498 |
499 | 昇順
500 |
501 |
502 | バナー(白黒)を指定する
503 |
504 |
505 | バナーを指定する
506 |
507 |
508 | 日本語/vpatch.ini, 英語 (non-THCRAP), Custom.exe, thcrap
509 |
510 |
511 | 削除
512 |
513 |
514 | 降順
515 |
516 |
517 | 詳細
518 |
519 |
520 | Appdataフォルダが見つりません
521 |
522 |
523 | ファイルが見つかりません
524 |
525 |
526 | Neko Project 2のパスを指定してください
527 |
528 |
529 | 画像ファイルではありません:
530 |
531 |
532 |
533 | replayフォルダが見つかりません
534 |
535 |
536 | vpatch.iniが見つかりません
537 |
538 |
539 | 実行ファイル
540 |
541 |
542 | ゲームの実行ファイルを指定する
543 |
544 |
545 | HDIファイル
546 |
547 |
548 | ゲームのHDIファイルを指定する
549 |
550 |
551 | 画像ファイル
552 |
553 |
554 | 大アイコン
555 |
556 |
557 | 一覧
558 |
559 |
560 | Neko Project IIの実行ファイルを指定する
561 |
562 |
563 | Appdataフォルダ
564 |
565 |
566 | フォルダを開く
567 |
568 |
569 | Applocaleで開く
570 |
571 |
572 | ランダムでゲームを起動
573 |
574 |
575 | 名前の変更
576 |
577 |
578 | 小アイコン
579 |
580 |
581 | 並べ替え
582 |
583 |
584 | 並べて表示
585 |
586 |
587 | 表示
588 |
589 |
590 | Neko Project IIのコンフィグiniは有効ではありません。
591 |
592 |
593 | ゲームファイルが見つからない。右クリックメニューでパスを指定してください。
594 |
595 |
596 | リプレイファイル
597 |
598 |
599 | '{1}'に'{0}'をダウンロードします
600 |
601 |
602 | リプレイリストがいっぱいです。(風神録はユーザーリプレイをサポートしていません)
603 |
604 |
605 |
606 | ゲームの設定:
607 |
608 |
609 | トレイに最小化
610 |
611 |
612 | トレイアイコンを常に表示する
613 |
614 |
615 | 「{0}」とその中にいるすべてを削除しますか?
616 |
617 |
618 | 「{0}」を削除しますか?
619 |
620 |
621 | thcrapのパスを指定してください
622 |
623 |
624 | thcrapの設定
625 |
626 |
627 | thcrap_loaderの場所:
628 |
629 |
630 | thcrapのプロファイルを設定してください
631 |
632 |
633 | ゲームが選択されていません
634 |
635 |
636 | リプレイをダウンロードしますか?
637 |
638 |
639 | 終了
640 |
641 |
642 | 表示
643 |
644 |
645 | ランダムでゲームを起動
646 |
647 |
648 | ゲームを削除する
649 |
650 |
651 | 説明
652 |
653 |
654 | ゲームプロファイル
655 |
656 |
657 | ゲームID
658 |
659 |
660 | ID
661 |
662 |
663 | パッチ
664 |
665 |
666 | カスタムプロファイル
667 |
668 |
669 | ゲームパス
670 |
671 |
672 | プロファイルの設定:
673 |
674 |
675 | タイトル
676 |
677 |
678 | デフォルト
679 |
680 |
681 | thcrap起動用リポジトリ:
682 |
683 |
684 | * 120 x 44
685 |
686 |
687 | 色を指定
688 |
689 |
690 | 指定した色を使用
691 |
692 |
693 | バナーの表示
694 |
695 |
696 | 表示
697 |
698 |
699 | タイトルの表示
700 |
701 |
702 | 選択されたパッチ
703 |
704 |
705 | 東方鬼形獣
706 |
707 |
708 | 鬼形獣
709 |
710 |
711 | 東方鬼形獣 ~ Wily Beast and Weakest Creature
712 |
713 |
714 | 東方虹龍洞
715 |
716 |
717 | 虹龍洞
718 |
719 |
720 | 東方虹龍洞 ~ Unconnected Marketeers
721 |
722 |
723 | 東方剛欲異聞
724 |
725 |
726 | 剛欲異聞
727 |
728 |
729 | 東方剛欲異聞 ~ 水没した沈愁地獄
730 |
731 |
732 | カテゴリーが選択されていません
733 |
734 |
735 | バレットフィリア達の闇市場
736 |
737 |
738 | バレットフィリア
739 |
740 |
741 | バレットフィリア達の闇市場 〜 100th Black Market
742 |
743 |
744 | 小数点作
745 |
746 |
747 | 東方獣王園
748 |
749 |
750 | 獣王園
751 |
752 |
753 | 東方獣王園 〜 Unfinished Dream of All Living Ghost
754 |
755 |
--------------------------------------------------------------------------------
/Touhou Launcher/Resources_ru.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 | Antinomy of Common Flowers
122 |
123 |
124 | Touhou 15.5: Antinomy of Common Flowers
125 |
126 |
127 | Double Dealing Character
128 |
129 |
130 | Touhou 14: Double Dealing Character
131 |
132 |
133 | Double Spoiler
134 |
135 |
136 | Touhou 12.5: Double Spoiler
137 |
138 |
139 | Embodiment of Scarlet Devil
140 |
141 |
142 | Touhou 06: the Embodiment of Scarlet Devil
143 |
144 |
145 | Great Fairy Wars
146 |
147 |
148 | Touhou 12.8: Great Fairy Wars
149 |
150 |
151 | Hopeless Masquerade
152 |
153 |
154 | Touhou 13.5: Hopeless Masquerade
155 |
156 |
157 | Highly Responsive to Prayers
158 |
159 |
160 | Touhou 01: Highly Responsive to Prayers
161 |
162 |
163 | Hidden Star in Four Seasons
164 |
165 |
166 | Touhou 16: Hidden Star in Four Seasons
167 |
168 |
169 | Immaterial and Missing Power
170 |
171 |
172 | Touhou 7.5: Immaterial and Missing Power
173 |
174 |
175 | Imperishable Night
176 |
177 |
178 | Touhou 08: Imperishable Night
179 |
180 |
181 | Impossible Spell Card
182 |
183 |
184 | Touhou 14.3: Impossible Spell Card
185 |
186 |
187 | Lotus Land Story
188 |
189 |
190 | Touhou 04: Lotus Land Story
191 |
192 |
193 | Legacy of Lunatic Kingdom
194 |
195 |
196 | Touhou 15: Legacy of Lunatic Kingdom
197 |
198 |
199 | Mountain of Faith
200 |
201 |
202 | Touhou 10: Mountain of Faith
203 |
204 |
205 | Mystic Square
206 |
207 |
208 | Touhou 05: Mystic Square
209 |
210 |
211 | Perfect Cherry Blossom
212 |
213 |
214 | Touhou 07: Perfect Cherry Blossom
215 |
216 |
217 | Phantasmagoria of Dim. Dream
218 |
219 |
220 | Touhou 03: Phantasmagoria of Dim. Dream
221 |
222 |
223 | Phantasmagoria of Flower View
224 |
225 |
226 | Touhou 09: Phantasmagoria of Flower View
227 |
228 |
229 | Subterranean Animism
230 |
231 |
232 | Touhou 11: Subterranean Animism
233 |
234 |
235 | Story of Eastern Wonderland
236 |
237 |
238 | Touhou 02: the Story of Eastern Wonderland
239 |
240 |
241 | Shoot the Bullet
242 |
243 |
244 | Touhou 9.5: Shoot the Bullet
245 |
246 |
247 | Scarlet Weather Rhapsody
248 |
249 |
250 | Touhou 10.5: Scarlet Weather Rhapsody
251 |
252 |
253 | Ten Desires
254 |
255 |
256 | Touhou 13: Ten Desires
257 |
258 |
259 | Undefined Fantastic Object
260 |
261 |
262 | Touhou 12: Undefined Fantastic Object
263 |
264 |
265 | Urban Legend in Limbo
266 |
267 |
268 | Touhou 14.5: Urban Legend in Limbo
269 |
270 |
271 | Hisoutensoku
272 |
273 |
274 | Touhou 12.3: Hisoutensoku
275 |
276 |
277 | Violet Detector
278 |
279 |
280 | Touhou 16.5: Violet Detector
281 |
282 |
283 | Случайная
284 |
285 |
286 | Запуск случайной игры
287 |
288 |
289 | Touhou Launcher
290 |
291 |
292 | Игры от Tasogare Frontier
293 |
294 |
295 | Основные игры
296 |
297 |
298 | Игры PC-98
299 |
300 |
301 | AoCF
302 |
303 |
304 | Автозакрытие
305 |
306 |
307 | Автоматически закрывать лаучер после запуска игры
308 |
309 |
310 | Чёрно-белая обложка
311 |
312 |
313 | Цветная обложка
314 |
315 |
316 | Настройка обложек
317 |
318 |
319 | Обзор
320 |
321 |
322 | Кастомные обложки
323 |
324 |
325 | Настройка игры
326 |
327 |
328 | Профиль thcrap:
329 |
330 |
331 | Добавить игру
332 |
333 |
334 | Кастомные игры
335 |
336 |
337 | Custom.exe:
338 |
339 |
340 | DDC
341 |
342 |
343 | Запуск по умолч.
344 |
345 |
346 | Удалить категорию
347 |
348 |
349 | DS
350 |
351 |
352 | Английский файл запуска:
353 |
354 |
355 | EoSD
356 |
357 |
358 | Игры
359 |
360 |
361 | GFW
362 |
363 |
364 | Игра в .HDI:
365 |
366 |
367 | HM
368 |
369 |
370 | HRtP
371 |
372 |
373 | HSiFS
374 |
375 |
376 | IaMP
377 |
378 |
379 | Инфо
380 |
381 |
382 | IN
383 |
384 |
385 | ISC
386 |
387 |
388 | Японский/vpatch файл запуска:
389 |
390 |
391 | Язык:
392 |
393 |
394 | Запуск
395 |
396 |
397 | Настройка запуска
398 |
399 |
400 | LLS
401 |
402 |
403 | LoLK
404 |
405 |
406 | MoF
407 |
408 |
409 | MS
410 |
411 |
412 | Новая категория
413 |
414 |
415 | Путь к Neko Project II
416 |
417 |
418 | Открыть папку игры
419 |
420 |
421 | Открыть папку Neko Project II
422 |
423 |
424 | Папка повторов
425 |
426 |
427 | Изм. vpatch.ini
428 |
429 |
430 | Настройки игры PC-98
431 |
432 |
433 | PCB
434 |
435 |
436 | PoDD
437 |
438 |
439 | PoFV
440 |
441 |
442 | Добавить всё
443 |
444 |
445 | Игры которые участвуют в случайном запуске
446 |
447 |
448 | Убрать всё
449 |
450 |
451 | Настройка случайных игр
452 |
453 |
454 | Переименовать категорию
455 |
456 |
457 | Повторы
458 |
459 |
460 | SA
461 |
462 |
463 | Настройки
464 |
465 |
466 | SoEW
467 |
468 |
469 | StB
470 |
471 |
472 | SWR
473 |
474 |
475 | TD
476 |
477 |
478 | UFO
479 |
480 |
481 | ULiL
482 |
483 |
484 | Hisoutensoku
485 |
486 |
487 | Вкл. Applocale
488 |
489 |
490 | VD
491 |
492 |
493 | Настройка игры Windows
494 |
495 |
496 | Все файлы
497 |
498 |
499 | По возрастанию
500 |
501 |
502 | Выбор чёрно-белой обложки
503 |
504 |
505 | Выбор цветной обложки
506 |
507 |
508 | Япон./vpatch.ini, Англ. (non-THCRAP), Custom.exe, thcrap
509 |
510 |
511 | Удалить
512 |
513 |
514 | По убыванию
515 |
516 |
517 | Детали
518 |
519 |
520 | Не удаётся найти папку Appdata
521 |
522 |
523 | Файл не найден
524 |
525 |
526 | Пожалуйста, укажите путь к Neko Project II
527 |
528 |
529 | Не удаётся открыть изображение:
530 |
531 |
532 | Папка повторов не найдена
533 |
534 |
535 | vpatch.ini не найден
536 |
537 |
538 | Исполняемый файл
539 |
540 |
541 | Выберите исполняемы файл
542 |
543 |
544 | Файлы образов жесткого диска
545 |
546 |
547 | Выберите игры в .HDI
548 |
549 |
550 | Файл изображения
551 |
552 |
553 | Крупные иконки
554 |
555 |
556 | Список
557 |
558 |
559 | Укажите путь к Neko Project II
560 |
561 |
562 | Папка Appdata
563 |
564 |
565 | Открыть папку
566 |
567 |
568 | Открыть с Applocale
569 |
570 |
571 | Запустить случайно
572 |
573 |
574 | Переименовать
575 |
576 |
577 | Мелкие иконки
578 |
579 |
580 | Сортировка
581 |
582 |
583 | Плитка
584 |
585 |
586 | Просмотр
587 |
588 |
589 | Файлы "ini" Neko Project II недействителен
590 |
591 |
592 | Игра не найдена. Please check the path in the right click menu.
593 |
594 |
595 | Файл повтров
596 |
597 |
598 | Скачать '{0}' в:
599 | '{1}'
600 |
601 |
602 | Повторы игрока заполнены и Touhou 10 не поддерживает пользовательские повторы.
603 |
604 |
605 |
606 | Настройка игры:
607 |
608 |
609 | Сворачивать в трей
610 |
611 |
612 | Всегда отображать иконку в трее
613 |
614 |
615 | Удалить категорию '{0}' и весь контент в ней?
616 |
617 |
618 | Удалить '{0}'?
619 |
620 |
621 | Пожалуйста, укажите путь к thcrap
622 |
623 |
624 | Настройка thcrap
625 |
626 |
627 | Путь к thcrap_loader:
628 |
629 |
630 | Пожалуйста, укажите профиль thcrap
631 |
632 |
633 | Не одна игра не выбрана
634 |
635 |
636 | Скачать повтор?
637 |
638 |
639 | Выход
640 |
641 |
642 | Открыть
643 |
644 |
645 | Случайная игра
646 |
647 |
648 | Удалить игру
649 |
650 |
651 | Описание
652 |
653 |
654 | Игровые профили
655 |
656 |
657 | ID игры
658 |
659 |
660 | ID
661 |
662 |
663 | Патч
664 |
665 |
666 | Кастомный профиль
667 |
668 |
669 | Путь игры
670 |
671 |
672 | Конфигурация профиля:
673 |
674 |
675 | Заглавие
676 |
677 |
678 | По умолчанию
679 |
680 |
681 | thcrap исходная папка:
682 |
683 |
684 | * 120 x 44
685 |
686 |
687 | Задать цвет
688 |
689 |
690 | Кастомный цвет текста
691 |
692 |
693 | Отображать обложки?
694 |
695 |
696 | Кнопка Изменить
697 |
698 |
699 | Отображать текст?
700 |
701 |
702 | выбранные патчи
703 |
704 |
705 | Wily Beast and Weakest Creature
706 |
707 |
708 | WBaWC
709 |
710 |
711 | Touhou 17: Wily Beast and Weakest Creature
712 |
713 |
714 | Unconnected Marketeers
715 |
716 |
717 | UM
718 |
719 |
720 | Touhou 18: Unconnected Marketeers
721 |
722 |
723 | Gouyoku Ibun
724 |
725 |
726 | GI
727 |
728 |
729 | Touhou 17.5: Gouyoku Ibun
730 |
731 |
732 | Не выбрана ни одна категория
733 |
734 |
735 | 100th Black Market
736 |
737 |
738 | 100BM
739 |
740 |
741 | Touhou 18.5: 100th Black Market
742 |
743 |
744 | Спиноффы
745 |
746 |
747 | Unfinished Dream of All Living Ghost
748 |
749 |
750 | UDoALG
751 |
752 |
753 | Touhou 19: Unfinished Dream of All Living Ghost
754 |
755 |
--------------------------------------------------------------------------------
/Touhou Launcher/Touhou Launcher.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {DC2E240A-725B-4A6C-83B0-73DBAAB13D1D}
8 | WinExe
9 | Properties
10 | Touhou_Launcher
11 | Touhou Launcher
12 | v4.8
13 | 512
14 |
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 | true
26 | false
27 |
28 |
29 | AnyCPU
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 | false
37 |
38 |
39 | thicon.ico
40 |
41 |
42 |
43 | jsonnet\Newtonsoft.Json.dll
44 | False
45 | global
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | Form
62 |
63 |
64 | MainForm.cs
65 |
66 |
67 | Form
68 |
69 |
70 | ConfigForm.cs
71 |
72 |
73 |
74 |
75 | True
76 | True
77 | Resources_en.resx
78 |
79 |
80 | True
81 | True
82 | Resources_jp.resx
83 |
84 |
85 | True
86 | True
87 | Resources_ru.resx
88 |
89 |
90 | Form
91 |
92 |
93 | thcrap.cs
94 |
95 |
96 | ConfigForm.cs
97 |
98 |
99 | MainForm.cs
100 |
101 |
102 | PublicResXFileCodeGenerator
103 | Resources.Designer.cs
104 | Designer
105 |
106 |
107 | True
108 | Resources.resx
109 | True
110 |
111 |
112 | PublicResXFileCodeGenerator
113 | Resources_en.Designer.cs
114 |
115 |
116 | PublicResXFileCodeGenerator
117 | Resources_jp.Designer.cs
118 | Designer
119 |
120 |
121 | PublicResXFileCodeGenerator
122 | Resources_ru.Designer.cs
123 | Designer
124 |
125 |
126 | thcrap.cs
127 |
128 |
129 |
130 | PublicSettingsSingleFileGenerator
131 | Settings.Designer.cs
132 |
133 |
134 | True
135 | Settings.settings
136 | True
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
152 |
--------------------------------------------------------------------------------
/Touhou Launcher/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Touhou Launcher/jsonnet/LICENSE.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | The MIT License (MIT)
4 |
5 | Copyright (c) 2007 James Newton-King
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10 |
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 |
--------------------------------------------------------------------------------
/Touhou Launcher/jsonnet/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/David-JonesDVN/Touhou-Relauncher/cae8d10958177629af911af3bfae711019d64376/Touhou Launcher/jsonnet/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/Touhou Launcher/thcrap.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Touhou_Launcher
2 | {
3 | partial class thcrap
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(thcrap));
32 | this.repoList = new System.Windows.Forms.ListView();
33 | this.titleColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
34 | this.idColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
35 | this.gameList = new System.Windows.Forms.ListView();
36 | this.gameIDColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
37 | this.pathColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
38 | this.path = new System.Windows.Forms.TextBox();
39 | this.gameID = new System.Windows.Forms.Label();
40 | this.gamePath = new System.Windows.Forms.Label();
41 | this.gameGroup = new System.Windows.Forms.GroupBox();
42 | this.id = new System.Windows.Forms.TextBox();
43 | this.removeGame = new System.Windows.Forms.Button();
44 | this.addGame = new System.Windows.Forms.Button();
45 | this.browsePath = new System.Windows.Forms.Button();
46 | this.patchGroup = new System.Windows.Forms.GroupBox();
47 | this.patchList = new System.Windows.Forms.ListView();
48 | this.patchColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
49 | this.descriptionColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
50 | this.gameGroup.SuspendLayout();
51 | this.patchGroup.SuspendLayout();
52 | this.SuspendLayout();
53 | //
54 | // repoList
55 | //
56 | this.repoList.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
57 | | System.Windows.Forms.AnchorStyles.Left)));
58 | this.repoList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
59 | this.titleColumn,
60 | this.idColumn});
61 | this.repoList.FullRowSelect = true;
62 | this.repoList.GridLines = true;
63 | this.repoList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
64 | this.repoList.HideSelection = false;
65 | this.repoList.Location = new System.Drawing.Point(6, 19);
66 | this.repoList.MultiSelect = false;
67 | this.repoList.Name = "repoList";
68 | this.repoList.ShowItemToolTips = true;
69 | this.repoList.Size = new System.Drawing.Size(275, 319);
70 | this.repoList.TabIndex = 0;
71 | this.repoList.UseCompatibleStateImageBehavior = false;
72 | this.repoList.View = System.Windows.Forms.View.Details;
73 | this.repoList.SelectedIndexChanged += new System.EventHandler(this.repoList_SelectedIndexChanged);
74 | //
75 | // titleColumn
76 | //
77 | this.titleColumn.Name = "titleColumn";
78 | this.titleColumn.Text = "Title";
79 | this.titleColumn.Width = 175;
80 | //
81 | // idColumn
82 | //
83 | this.idColumn.Name = "idColumn";
84 | this.idColumn.Text = "ID";
85 | this.idColumn.Width = 95;
86 | //
87 | // gameList
88 | //
89 | this.gameList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
90 | this.gameIDColumn,
91 | this.pathColumn});
92 | this.gameList.FullRowSelect = true;
93 | this.gameList.GridLines = true;
94 | this.gameList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
95 | this.gameList.Location = new System.Drawing.Point(6, 19);
96 | this.gameList.Name = "gameList";
97 | this.gameList.Size = new System.Drawing.Size(275, 115);
98 | this.gameList.TabIndex = 0;
99 | this.gameList.UseCompatibleStateImageBehavior = false;
100 | this.gameList.View = System.Windows.Forms.View.Details;
101 | this.gameList.SelectedIndexChanged += new System.EventHandler(this.gameList_SelectedIndexChanged);
102 | //
103 | // gameIDColumn
104 | //
105 | this.gameIDColumn.Name = "gameIDColumn";
106 | this.gameIDColumn.Text = "Game ID";
107 | this.gameIDColumn.Width = 87;
108 | //
109 | // pathColumn
110 | //
111 | this.pathColumn.Name = "pathColumn";
112 | this.pathColumn.Text = "Game Path";
113 | this.pathColumn.Width = 183;
114 | //
115 | // path
116 | //
117 | this.path.Location = new System.Drawing.Point(287, 74);
118 | this.path.Name = "path";
119 | this.path.Size = new System.Drawing.Size(189, 20);
120 | this.path.TabIndex = 2;
121 | //
122 | // gameID
123 | //
124 | this.gameID.AutoSize = true;
125 | this.gameID.Location = new System.Drawing.Point(287, 19);
126 | this.gameID.Name = "gameID";
127 | this.gameID.Size = new System.Drawing.Size(52, 13);
128 | this.gameID.TabIndex = 5;
129 | this.gameID.Text = "Game ID:";
130 | //
131 | // gamePath
132 | //
133 | this.gamePath.AutoSize = true;
134 | this.gamePath.Location = new System.Drawing.Point(287, 58);
135 | this.gamePath.Name = "gamePath";
136 | this.gamePath.Size = new System.Drawing.Size(63, 13);
137 | this.gamePath.TabIndex = 6;
138 | this.gamePath.Text = "Game Path:";
139 | //
140 | // gameGroup
141 | //
142 | this.gameGroup.Controls.Add(this.id);
143 | this.gameGroup.Controls.Add(this.removeGame);
144 | this.gameGroup.Controls.Add(this.addGame);
145 | this.gameGroup.Controls.Add(this.browsePath);
146 | this.gameGroup.Controls.Add(this.gamePath);
147 | this.gameGroup.Controls.Add(this.gameList);
148 | this.gameGroup.Controls.Add(this.gameID);
149 | this.gameGroup.Controls.Add(this.path);
150 | this.gameGroup.Location = new System.Drawing.Point(9, 362);
151 | this.gameGroup.Margin = new System.Windows.Forms.Padding(0);
152 | this.gameGroup.Name = "gameGroup";
153 | this.gameGroup.Size = new System.Drawing.Size(563, 140);
154 | this.gameGroup.TabIndex = 1;
155 | this.gameGroup.TabStop = false;
156 | this.gameGroup.Text = "Game Profiles";
157 | //
158 | // id
159 | //
160 | this.id.Location = new System.Drawing.Point(290, 36);
161 | this.id.Name = "id";
162 | this.id.Size = new System.Drawing.Size(267, 20);
163 | this.id.TabIndex = 1;
164 | //
165 | // removeGame
166 | //
167 | this.removeGame.Location = new System.Drawing.Point(427, 111);
168 | this.removeGame.Name = "removeGame";
169 | this.removeGame.Size = new System.Drawing.Size(130, 23);
170 | this.removeGame.TabIndex = 5;
171 | this.removeGame.Text = "Remove Game";
172 | this.removeGame.UseVisualStyleBackColor = true;
173 | this.removeGame.Click += new System.EventHandler(this.removeGame_Click);
174 | //
175 | // addGame
176 | //
177 | this.addGame.Location = new System.Drawing.Point(290, 111);
178 | this.addGame.Name = "addGame";
179 | this.addGame.Size = new System.Drawing.Size(130, 23);
180 | this.addGame.TabIndex = 4;
181 | this.addGame.Text = "Add Game";
182 | this.addGame.UseVisualStyleBackColor = true;
183 | this.addGame.Click += new System.EventHandler(this.addGame_Click);
184 | //
185 | // browsePath
186 | //
187 | this.browsePath.Location = new System.Drawing.Point(482, 72);
188 | this.browsePath.Name = "browsePath";
189 | this.browsePath.Size = new System.Drawing.Size(75, 23);
190 | this.browsePath.TabIndex = 3;
191 | this.browsePath.Text = "Browse";
192 | this.browsePath.UseVisualStyleBackColor = true;
193 | this.browsePath.Click += new System.EventHandler(this.browsePath_Click);
194 | //
195 | // patchGroup
196 | //
197 | this.patchGroup.Controls.Add(this.patchList);
198 | this.patchGroup.Controls.Add(this.repoList);
199 | this.patchGroup.Location = new System.Drawing.Point(9, 9);
200 | this.patchGroup.Margin = new System.Windows.Forms.Padding(0);
201 | this.patchGroup.Name = "patchGroup";
202 | this.patchGroup.Size = new System.Drawing.Size(566, 347);
203 | this.patchGroup.TabIndex = 0;
204 | this.patchGroup.TabStop = false;
205 | this.patchGroup.Text = "Custom Profile";
206 | //
207 | // patchList
208 | //
209 | this.patchList.CheckBoxes = true;
210 | this.patchList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
211 | this.patchColumn,
212 | this.descriptionColumn});
213 | this.patchList.FullRowSelect = true;
214 | this.patchList.GridLines = true;
215 | this.patchList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
216 | this.patchList.HideSelection = false;
217 | this.patchList.Location = new System.Drawing.Point(287, 19);
218 | this.patchList.MultiSelect = false;
219 | this.patchList.Name = "patchList";
220 | this.patchList.ShowItemToolTips = true;
221 | this.patchList.Size = new System.Drawing.Size(273, 319);
222 | this.patchList.TabIndex = 1;
223 | this.patchList.UseCompatibleStateImageBehavior = false;
224 | this.patchList.View = System.Windows.Forms.View.Details;
225 | //
226 | // patchColumn
227 | //
228 | this.patchColumn.Name = "patchColumn";
229 | this.patchColumn.Text = "Patch";
230 | this.patchColumn.Width = 100;
231 | //
232 | // descriptionColumn
233 | //
234 | this.descriptionColumn.Name = "descriptionColumn";
235 | this.descriptionColumn.Text = "Description";
236 | this.descriptionColumn.Width = 169;
237 | //
238 | // thcrap
239 | //
240 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
241 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
242 | this.ClientSize = new System.Drawing.Size(584, 512);
243 | this.Controls.Add(this.patchGroup);
244 | this.Controls.Add(this.gameGroup);
245 | this.Icon = global::Touhou_Launcher.Properties.Resources.thicon;
246 | this.Name = "thcrap";
247 | this.Text = "Profile Configuration: ";
248 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.thcrap_Closing);
249 | this.Load += new System.EventHandler(this.thcrap_Load);
250 | this.gameGroup.ResumeLayout(false);
251 | this.gameGroup.PerformLayout();
252 | this.patchGroup.ResumeLayout(false);
253 | this.ResumeLayout(false);
254 |
255 | }
256 |
257 | #endregion
258 |
259 | private System.Windows.Forms.ListView repoList;
260 | private System.Windows.Forms.ColumnHeader titleColumn;
261 | private System.Windows.Forms.ColumnHeader idColumn;
262 | private System.Windows.Forms.ListView gameList;
263 | private System.Windows.Forms.ColumnHeader gameIDColumn;
264 | private System.Windows.Forms.ColumnHeader pathColumn;
265 | private System.Windows.Forms.TextBox path;
266 | private System.Windows.Forms.Label gameID;
267 | private System.Windows.Forms.Label gamePath;
268 | private System.Windows.Forms.GroupBox gameGroup;
269 | private System.Windows.Forms.Button removeGame;
270 | private System.Windows.Forms.Button addGame;
271 | private System.Windows.Forms.Button browsePath;
272 | private System.Windows.Forms.GroupBox patchGroup;
273 | private System.Windows.Forms.ListView patchList;
274 | private System.Windows.Forms.ColumnHeader patchColumn;
275 | private System.Windows.Forms.ColumnHeader descriptionColumn;
276 | private System.Windows.Forms.TextBox id;
277 |
278 | }
279 | }
--------------------------------------------------------------------------------
/Touhou Launcher/thcrap.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Windows.Forms;
6 | using System.IO;
7 | using System.Net;
8 | using Newtonsoft.Json;
9 |
10 | namespace Touhou_Launcher
11 | {
12 | public partial class thcrap : Form
13 | {
14 | internal class repoData
15 | {
16 | public string contact = "";
17 | public string id = "";
18 | public List neighbors = new List();
19 | public Dictionary patches = new Dictionary();
20 | public List servers = new List();
21 | public string title = "";
22 | }
23 |
24 | internal class patchData
25 | {
26 | public List dependencies = new List();
27 | public string id = "";
28 | public List servers = new List();
29 | public string title = "";
30 | public Dictionary fonts = new Dictionary();
31 | }
32 |
33 | internal class profileData
34 | {
35 | public bool console = false;
36 | public bool dat_dump = false;
37 | public List> patches = new List>();
38 | }
39 |
40 | ConfigForm cfgForm;
41 | string gamejs;
42 | Dictionary repos = new Dictionary();
43 | List checkedRepos = new List();
44 | List patchStates = new List();
45 | Dictionary games = new Dictionary();
46 | Queue repoQueue = new Queue();
47 |
48 | private void InitializeLanguage()
49 | {
50 | this.Text = MainForm.rm.GetString("thcrapTitle") + MainForm.rm.GetString(MainForm.nameToID.FirstOrDefault(t => t.Value == cfgForm.game).Key);
51 | foreach (ListView list in MainForm.GetAll(this, typeof(ListView)))
52 | {
53 | foreach (ColumnHeader column in list.Columns)
54 | {
55 | column.Text = MainForm.rm.GetString(column.Name);
56 | }
57 | }
58 | gameGroup.Text = MainForm.rm.GetString("gameGroup");
59 | patchGroup.Text = MainForm.rm.GetString("patchGroup");
60 | gameID.Text = MainForm.rm.GetString("gameIDColumn") + ":";
61 | gamePath.Text = MainForm.rm.GetString("pathColumn") + ":";
62 | browsePath.Text = MainForm.rm.GetString("browse");
63 | addGame.Text = MainForm.rm.GetString("customAdd");
64 | removeGame.Text = MainForm.rm.GetString("customRemove");
65 | }
66 |
67 | private void RefreshProfiles()
68 | {
69 | gameList.Items.Clear();
70 | foreach (KeyValuePair game in games)
71 | {
72 | ListViewItem gameID = gameList.Items.Add(game.Key);
73 | gameID.SubItems.Add(game.Value);
74 | }
75 | }
76 |
77 | public thcrap(ConfigForm cfg)
78 | {
79 | cfgForm = cfg;
80 | gamejs = MainForm.curCfg.crapDir + "\\config\\launcher" + MainForm.idToNumber[cfg.game] + ".js";
81 | InitializeComponent();
82 | InitializeLanguage();
83 | }
84 |
85 | private void thcrap_Load(object sender, EventArgs e)
86 | {
87 | repoList.Items.Add(MainForm.rm.GetString("selectedPatches"));
88 | if (File.Exists(gamejs))
89 | {
90 | profileData profile = JsonConvert.DeserializeObject(File.ReadAllText(gamejs));
91 | foreach (Dictionary patch in profile.patches)
92 | {
93 | if (!patchStates.Contains(patch["archive"]))
94 | patchStates.Add(patch["archive"].Substring(6));
95 | }
96 | }
97 | foreach (FileInfo localRepo in new DirectoryInfo(MainForm.curCfg.crapDir).CreateSubdirectory("repos").GetFiles("repo.js", SearchOption.AllDirectories))
98 | {
99 | addRepo(File.ReadAllText(localRepo.FullName), true);
100 | }
101 | searchRepo(MainForm.curCfg.StartingRepo);
102 | if (File.Exists(MainForm.curCfg.crapDir + "\\config\\games.js"))
103 | games = JsonConvert.DeserializeObject>(File.ReadAllText(MainForm.curCfg.crapDir + "\\config\\games.js"));
104 | for (int i = 0; i < 3; i += 2)
105 | {
106 | if (MainForm.curCfg.gameCFG[cfgForm.game].GameDir[i] != "" && !games.ContainsValue(MainForm.curCfg.gameCFG[cfgForm.game].GameDir[i].Replace("\\", "/")))
107 | {
108 | string augment = i == 2 ? "_custom" : "";
109 | games.Add("th" + (MainForm.idToNumber[cfgForm.game]).ToString("00") + augment, MainForm.curCfg.gameCFG[cfgForm.game].GameDir[i].Replace("\\", "/"));
110 | }
111 | }
112 | RefreshProfiles();
113 | }
114 |
115 | private async void searchRepo(string address)
116 | {
117 | WebClient wc = new WebClient();
118 | wc.Encoding = Encoding.UTF8;
119 | while (true)
120 | {
121 | if (!checkedRepos.Contains(address))
122 | {
123 | try
124 | {
125 | addRepo(await wc.DownloadStringTaskAsync(address + "/repo.js"));
126 | checkedRepos.Add(address);
127 | }
128 | catch (Exception ex)
129 | {
130 | /* Code for exploring the thcrap mirror manually.
131 | using (var reader = new StreamReader(WebRequest.Create(address).GetResponse().GetResponseStream()))
132 | {
133 | string result = reader.ReadToEnd();
134 | System.Text.RegularExpressions.MatchCollection matches = new System.Text.RegularExpressions.Regex("(?.*)").Matches(result);
135 | //Alt Regex: ]*?\s+)?href=(["'])(.*?)\1
136 | foreach (System.Text.RegularExpressions.Match match in matches)
137 | {
138 | if (!match.Success) { continue; }
139 | if (match.Groups["name"].Value.EndsWith("/"))
140 | searchRepo(address + match.Groups["name"].Value, true);
141 | }
142 | }
143 | */
144 | }
145 | }
146 | if (repoQueue.Count > 0)
147 | {
148 | address = repoQueue.Dequeue();
149 | }
150 | else break;
151 | }
152 | }
153 |
154 | private void addRepo(string repojs, bool offline = false)
155 | {
156 | try
157 | {
158 | repoData data = JsonConvert.DeserializeObject(repojs);
159 | FileInfo jsPath = new FileInfo(MainForm.curCfg.crapDir + "\\repos\\" + data.id + "\\repo.js");
160 | jsPath.Directory.Create();
161 | File.WriteAllText(jsPath.FullName, repojs);
162 | if (!repoList.Items.ContainsKey(data.id) || (bool)repoList.Items[data.id].Tag == true)
163 | {
164 | foreach (string neighbor in data.neighbors)
165 | {
166 | repoQueue.Enqueue(neighbor);
167 | }
168 | repos[data.id] = data;
169 | if (!repoList.Items.ContainsKey(data.id))
170 | {
171 | ListViewItem title = repoList.Items.Add(data.title);
172 | title.Name = data.id;
173 | title.Tag = offline;
174 | title.SubItems.Add(data.id);
175 | }
176 | else
177 | {
178 | ListViewItem title = repoList.Items[data.id];
179 | title.Tag = offline;
180 | }
181 | repoList_SelectedIndexChanged(repoList.Items[data.id], new EventArgs());
182 | }
183 | }
184 | catch (Exception ex)
185 | {
186 | MessageBox.Show(ex.ToString());
187 | }
188 | }
189 |
190 | private void onPatchGet(object sender, DownloadStringCompletedEventArgs e)
191 | {
192 | if (e.Error == null)
193 | {
194 | patchData patch = JsonConvert.DeserializeObject(e.Result);
195 | FileInfo jsPath = new FileInfo(MainForm.curCfg.crapDir + "\\repos\\" + (string)e.UserState + "\\" + patch.id + "\\patch.js");
196 | jsPath.Directory.Create();
197 | File.WriteAllText(jsPath.FullName, e.Result);
198 | foreach (string dependency in patch.dependencies)
199 | {
200 | string[] dependencySet = dependency.Split('/');
201 | string repository = "";
202 | if (dependencySet.Length == 1)
203 | {
204 | foreach (KeyValuePair repo in repos)
205 | {
206 | if (repo.Value.patches.ContainsKey(dependencySet[0]))
207 | {
208 | repository = repo.Key;
209 | }
210 | }
211 | }
212 | else
213 | repository = dependencySet[0];
214 | addPatch(repository, dependencySet[dependencySet.Length - 1], patchStates.IndexOf((string)e.UserState + "/" + patch.id + "/"));
215 | }
216 | }
217 | }
218 |
219 | private void addPatch(string repo, string patch, int dependent = -1)
220 | {
221 | if (!patchStates.Contains(repo + "/" + patch + "/"))
222 | {
223 | patchStates.Insert(dependent == -1 ? patchStates.Count : dependent, repo + "/" + patch + "/");
224 | repoList_SelectedIndexChanged(repoList.Items[repo], new EventArgs());
225 | }
226 | WebClient wc = new WebClient();
227 | wc.Encoding = Encoding.UTF8;
228 | wc.DownloadStringCompleted += onPatchGet;
229 | wc.DownloadStringAsync(new Uri(repos[repo].servers[0] + "/" + patch + "/patch.js"), repo);
230 | }
231 |
232 | private void thcrap_Closing(object sender, FormClosingEventArgs e)
233 | {
234 | profileData profile = new profileData();
235 | foreach (string patch in patchStates)
236 | {
237 | profile.patches.Add(new Dictionary { {"archive", "repos/" + patch} });
238 | }
239 | File.WriteAllText(gamejs, JsonConvert.SerializeObject(profile, Formatting.Indented));
240 | Dictionary games = new Dictionary();
241 | foreach (ListViewItem game in gameList.Items)
242 | {
243 | games[game.Text] = game.SubItems[1].Text;
244 | }
245 | File.WriteAllText(MainForm.curCfg.crapDir + "\\config\\games.js", JsonConvert.SerializeObject(games, Formatting.Indented));
246 | cfgForm.Refreshcrap();
247 | }
248 |
249 | private void repoList_SelectedIndexChanged(object sender, EventArgs e)
250 | {
251 | if (sender == repoList || repoList.SelectedItems.Contains((ListViewItem)sender) || repoList.SelectedIndices.Contains(0))
252 | {
253 | patchList.Items.Clear();
254 | if (repoList.SelectedItems.Count > 0)
255 | {
256 | patchList.ItemChecked -= patchList_ItemChecked;
257 | if (repoList.SelectedIndices[0] == 0)
258 | {
259 | foreach (string patch in patchStates)
260 | {
261 | string[] patchSet = patch.Split('/');
262 | ListViewItem title = patchList.Items.Add(patch);
263 | title.SubItems.Add(repos[patchSet[0]].patches[patchSet[1]]);
264 | title.Checked = true;
265 | }
266 | }
267 | else
268 | {
269 | foreach (KeyValuePair patch in repos[repoList.SelectedItems[0].SubItems[1].Text].patches)
270 | {
271 | ListViewItem title = patchList.Items.Add(patch.Key);
272 | title.SubItems.Add(patch.Value);
273 | title.Checked = patchStates.Contains(repoList.SelectedItems[0].SubItems[1].Text + "/" + patch.Key + "/");
274 | }
275 | }
276 | patchList.ItemChecked += patchList_ItemChecked;
277 | }
278 | }
279 | }
280 |
281 | private void patchList_ItemChecked(object sender, ItemCheckedEventArgs e)
282 | {
283 | string id = repoList.SelectedIndices[0] == 0 ? e.Item.Text : repoList.SelectedItems[0].SubItems[1].Text + "/" + e.Item.Text + "/";
284 | if (e.Item.Checked)
285 | {
286 | addPatch(repoList.SelectedItems[0].SubItems[1].Text, e.Item.Text);
287 | }
288 | else
289 | {
290 | patchStates.Remove(id);
291 | if (repoList.SelectedIndices[0] == 0)
292 | e.Item.Remove();
293 | }
294 | }
295 |
296 | private void browsePath_Click(object sender, EventArgs e)
297 | {
298 | foreach (string file in MainForm.FileBrowser(MainForm.rm.GetString("gameSelectTitle"), MainForm.rm.GetString("executableFilter") + " (*.exe, *.bat, *.lnk)|*.exe;*.bat;*.lnk|" + MainForm.rm.GetString("allFilter") + " (*.*)|*.*"))
299 | path.Text = file;
300 | }
301 |
302 | private void addGame_Click(object sender, EventArgs e)
303 | {
304 | if (File.Exists(path.Text))
305 | {
306 | games[id.Text] = path.Text.Replace("\\", "/");
307 | RefreshProfiles();
308 | }
309 | }
310 |
311 | private void removeGame_Click(object sender, EventArgs e)
312 | {
313 | games.Remove(id.Text);
314 | RefreshProfiles();
315 | }
316 |
317 | private void gameList_SelectedIndexChanged(object sender, EventArgs e)
318 | {
319 | if (gameList.SelectedItems.Count > 0)
320 | {
321 | id.Text = gameList.SelectedItems[0].Text;
322 | path.Text = gameList.SelectedItems[0].SubItems[1].Text.Replace("/", "\\");
323 | }
324 | }
325 | }
326 | }
327 |
--------------------------------------------------------------------------------
/Touhou Launcher/thcrap.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 |
--------------------------------------------------------------------------------
/Touhou Launcher/thicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/David-JonesDVN/Touhou-Relauncher/cae8d10958177629af911af3bfae711019d64376/Touhou Launcher/thicon.ico
--------------------------------------------------------------------------------