├── .gitignore
├── Asmodean
├── Asmodean.vcxproj
├── Asmodean.vcxproj.filters
├── asmodean.h
├── blowfish.cpp
├── blowfish.h
├── exkifint.cpp
├── exkifint.h
├── hgx2bmp.cpp
└── hgx2bmp.h
├── GrisaiaExtractor.sln
├── GrisaiaExtractor
├── AnimationHelper.cs
├── Asmodean
│ ├── Exkifint.MersenneTwister.cs
│ ├── Exkifint.PInvoke.cs
│ ├── Exkifint.Structs.cs
│ ├── Exkifint.cs
│ ├── Hgx2png.PInvoke.cs
│ ├── Hgx2png.Structs.cs
│ └── Hgx2png.cs
├── Attributes.cs
├── Exceptions.cs
├── Extensions
│ ├── BinaryExtensions.cs
│ ├── StringExtensions.Surround.cs
│ └── StringExtensions.cs
├── Extracting.cs
├── GrisaiaExtractor.csproj
├── Identifying
│ ├── Backgrounds.cs
│ ├── Character.cs
│ ├── Effect.cs
│ ├── ImageIdentification.cs
│ ├── ImageIdentifier.cs
│ ├── Item.cs
│ ├── Logo.cs
│ ├── MiscChibi.cs
│ ├── StoryCGChibi.cs
│ ├── TmbIcon.cs
│ ├── Transition.cs
│ ├── Unidentified.cs
│ └── UserInterface.cs
├── Locator.cs
├── PathHelper.cs
├── Properties
│ └── AssemblyInfo.cs
├── Unused
│ ├── Exkifint.Blowfish.Tables.cs
│ ├── Exkifint.Blowfish.cs
│ └── Hgx2png.BitBuffer.cs
└── zlib1.dll
├── GrisaiaExtractorConsole
├── App.ico
├── AsciiImage.cs
├── GrisaiaExtractorConsole.csproj
├── Ini
│ ├── IniDocument.cs
│ ├── IniEnums.cs
│ ├── IniProperty.cs
│ ├── IniReflectionSettings.cs
│ ├── IniSection.cs
│ ├── ReflectionHelper.cs
│ └── TypeHelper.cs
├── Program.Classes.cs
├── Program.Input.cs
├── Program.Output.cs
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── UserSettings.cs
└── grisaia.ascii
├── License.md
├── Readme.md
└── zlib
├── bin
└── zlib1.dll
├── include
├── zconf.h
└── zlib.h
├── lib
├── libz.a
├── libz.dll.a
├── zlib-bcc.lib
├── zlib.def
└── zlib.lib
└── manifest
├── zlib-1.2.3-lib.mft
└── zlib-1.2.3-lib.ver
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | !zlib/bin
25 | [Oo]bj/
26 | [Ll]og/
27 |
28 | # Visual Studio 2015/2017 cache/options directory
29 | .vs/
30 | # Uncomment if you have tasks that create the project's static files in wwwroot
31 | #wwwroot/
32 |
33 | # Visual Studio 2017 auto generated files
34 | Generated\ Files/
35 |
36 | # MSTest test Results
37 | [Tt]est[Rr]esult*/
38 | [Bb]uild[Ll]og.*
39 |
40 | # NUNIT
41 | *.VisualState.xml
42 | TestResult.xml
43 |
44 | # Build Results of an ATL Project
45 | [Dd]ebugPS/
46 | [Rr]eleasePS/
47 | dlldata.c
48 |
49 | # Benchmark Results
50 | BenchmarkDotNet.Artifacts/
51 |
52 | # .NET Core
53 | project.lock.json
54 | project.fragment.lock.json
55 | artifacts/
56 | **/Properties/launchSettings.json
57 |
58 | # StyleCop
59 | StyleCopReport.xml
60 |
61 | # Files built by Visual Studio
62 | *_i.c
63 | *_p.c
64 | *_i.h
65 | *.ilk
66 | *.meta
67 | *.obj
68 | *.iobj
69 | *.pch
70 | *.pdb
71 | *.ipdb
72 | *.pgc
73 | *.pgd
74 | *.rsp
75 | *.sbr
76 | *.tlb
77 | *.tli
78 | *.tlh
79 | *.tmp
80 | *.tmp_proj
81 | *.log
82 | *.vspscc
83 | *.vssscc
84 | .builds
85 | *.pidb
86 | *.svclog
87 | *.scc
88 |
89 | # Chutzpah Test files
90 | _Chutzpah*
91 |
92 | # Visual C++ cache files
93 | ipch/
94 | *.aps
95 | *.ncb
96 | *.opendb
97 | *.opensdf
98 | *.sdf
99 | *.cachefile
100 | *.VC.db
101 | *.VC.VC.opendb
102 |
103 | # Visual Studio profiler
104 | *.psess
105 | *.vsp
106 | *.vspx
107 | *.sap
108 |
109 | # Visual Studio Trace Files
110 | *.e2e
111 |
112 | # TFS 2012 Local Workspace
113 | $tf/
114 |
115 | # Guidance Automation Toolkit
116 | *.gpState
117 |
118 | # ReSharper is a .NET coding add-in
119 | _ReSharper*/
120 | *.[Rr]e[Ss]harper
121 | *.DotSettings.user
122 |
123 | # JustCode is a .NET coding add-in
124 | .JustCode
125 |
126 | # TeamCity is a build add-in
127 | _TeamCity*
128 |
129 | # DotCover is a Code Coverage Tool
130 | *.dotCover
131 |
132 | # AxoCover is a Code Coverage Tool
133 | .axoCover/*
134 | !.axoCover/settings.json
135 |
136 | # Visual Studio code coverage results
137 | *.coverage
138 | *.coveragexml
139 |
140 | # NCrunch
141 | _NCrunch_*
142 | .*crunch*.local.xml
143 | nCrunchTemp_*
144 |
145 | # MightyMoose
146 | *.mm.*
147 | AutoTest.Net/
148 |
149 | # Web workbench (sass)
150 | .sass-cache/
151 |
152 | # Installshield output folder
153 | [Ee]xpress/
154 |
155 | # DocProject is a documentation generator add-in
156 | DocProject/buildhelp/
157 | DocProject/Help/*.HxT
158 | DocProject/Help/*.HxC
159 | DocProject/Help/*.hhc
160 | DocProject/Help/*.hhk
161 | DocProject/Help/*.hhp
162 | DocProject/Help/Html2
163 | DocProject/Help/html
164 |
165 | # Click-Once directory
166 | publish/
167 |
168 | # Publish Web Output
169 | *.[Pp]ublish.xml
170 | *.azurePubxml
171 | # Note: Comment the next line if you want to checkin your web deploy settings,
172 | # but database connection strings (with potential passwords) will be unencrypted
173 | *.pubxml
174 | *.publishproj
175 |
176 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
177 | # checkin your Azure Web App publish settings, but sensitive information contained
178 | # in these scripts will be unencrypted
179 | PublishScripts/
180 |
181 | # NuGet Packages
182 | *.nupkg
183 | # The packages folder can be ignored because of Package Restore
184 | **/[Pp]ackages/*
185 | # except build/, which is used as an MSBuild target.
186 | !**/[Pp]ackages/build/
187 | # Uncomment if necessary however generally it will be regenerated when needed
188 | #!**/[Pp]ackages/repositories.config
189 | # NuGet v3's project.json files produces more ignorable files
190 | *.nuget.props
191 | *.nuget.targets
192 |
193 | # Microsoft Azure Build Output
194 | csx/
195 | *.build.csdef
196 |
197 | # Microsoft Azure Emulator
198 | ecf/
199 | rcf/
200 |
201 | # Windows Store app package directories and files
202 | AppPackages/
203 | BundleArtifacts/
204 | Package.StoreAssociation.xml
205 | _pkginfo.txt
206 | *.appx
207 |
208 | # Visual Studio cache files
209 | # files ending in .cache can be ignored
210 | *.[Cc]ache
211 | # but keep track of directories ending in .cache
212 | !*.[Cc]ache/
213 |
214 | # Others
215 | ClientBin/
216 | ~$*
217 | *~
218 | *.dbmdl
219 | *.dbproj.schemaview
220 | *.jfm
221 | *.pfx
222 | *.publishsettings
223 | orleans.codegen.cs
224 |
225 | # Including strong name files can present a security risk
226 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
227 | #*.snk
228 |
229 | # Since there are multiple workflows, uncomment next line to ignore bower_components
230 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
231 | #bower_components/
232 |
233 | # RIA/Silverlight projects
234 | Generated_Code/
235 |
236 | # Backup & report files from converting an old project file
237 | # to a newer Visual Studio version. Backup files are not needed,
238 | # because we have git ;-)
239 | _UpgradeReport_Files/
240 | Backup*/
241 | UpgradeLog*.XML
242 | UpgradeLog*.htm
243 | ServiceFabricBackup/
244 | *.rptproj.bak
245 |
246 | # SQL Server files
247 | *.mdf
248 | *.ldf
249 | *.ndf
250 |
251 | # Business Intelligence projects
252 | *.rdl.data
253 | *.bim.layout
254 | *.bim_*.settings
255 | *.rptproj.rsuser
256 |
257 | # Microsoft Fakes
258 | FakesAssemblies/
259 |
260 | # GhostDoc plugin setting file
261 | *.GhostDoc.xml
262 |
263 | # Node.js Tools for Visual Studio
264 | .ntvs_analysis.dat
265 | node_modules/
266 |
267 | # Visual Studio 6 build log
268 | *.plg
269 |
270 | # Visual Studio 6 workspace options file
271 | *.opt
272 |
273 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
274 | *.vbw
275 |
276 | # Visual Studio LightSwitch build output
277 | **/*.HTMLClient/GeneratedArtifacts
278 | **/*.DesktopClient/GeneratedArtifacts
279 | **/*.DesktopClient/ModelManifest.xml
280 | **/*.Server/GeneratedArtifacts
281 | **/*.Server/ModelManifest.xml
282 | _Pvt_Extensions
283 |
284 | # Paket dependency manager
285 | .paket/paket.exe
286 | paket-files/
287 |
288 | # FAKE - F# Make
289 | .fake/
290 |
291 | # JetBrains Rider
292 | .idea/
293 | *.sln.iml
294 |
295 | # CodeRush
296 | .cr/
297 |
298 | # Python Tools for Visual Studio (PTVS)
299 | __pycache__/
300 | *.pyc
301 |
302 | # Cake - Uncomment if you are using it
303 | # tools/**
304 | # !tools/packages.config
305 |
306 | # Tabs Studio
307 | *.tss
308 |
309 | # Telerik's JustMock configuration file
310 | *.jmconfig
311 |
312 | # BizTalk build output
313 | *.btp.cs
314 | *.btm.cs
315 | *.odx.cs
316 | *.xsd.cs
317 |
318 | # OpenCover UI analysis results
319 | OpenCover/
320 |
321 | # Azure Stream Analytics local run output
322 | ASALocalRun/
323 |
324 | # MSBuild Binary and Structured Log
325 | *.binlog
326 |
327 | # NVidia Nsight GPU debugger configuration file
328 | *.nvuser
329 |
330 | # MFractors (Xamarin productivity tool) working folder
331 | .mfractor/
332 |
--------------------------------------------------------------------------------
/Asmodean/Asmodean.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | 15.0
34 | {5D227B71-C303-400C-8E99-DF63C79E3613}
35 | Asmodean
36 | 10.0.16299.0
37 | asmodean
38 |
39 |
40 |
41 | DynamicLibrary
42 | true
43 | v141
44 | MultiByte
45 |
46 |
47 | DynamicLibrary
48 | false
49 | v141
50 | true
51 | MultiByte
52 |
53 |
54 | Application
55 | true
56 | v141
57 | MultiByte
58 |
59 |
60 | Application
61 | false
62 | v141
63 | true
64 | MultiByte
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | .dll
86 | $(ProjectDir)bin\$(Configuration)\
87 | obj\$(Configuration)\
88 |
89 |
90 | .dll
91 | $(ProjectDir)bin\$(Configuration)\
92 | obj\$(Configuration)\
93 |
94 |
95 |
96 | Level3
97 | MaxSpeed
98 | true
99 | true
100 | true
101 | true
102 | $(SolutionDir)zlib\include;%(AdditionalIncludeDirectories)
103 |
104 |
105 | true
106 | true
107 | $(SolutionDir)zlib\lib\zlib.lib;%(AdditionalDependencies)
108 |
109 |
110 | xcopy /y /d "$(SolutionDir)zlib\bin\zlib1.dll" "$(OutDir)"
111 |
112 |
113 | Copy zlib1.dll to the output folder
114 |
115 |
116 |
117 |
118 | Level3
119 | Disabled
120 | true
121 | true
122 | $(SolutionDir)zlib\include;%(AdditionalIncludeDirectories)
123 | ProgramDatabase
124 |
125 |
126 | $(SolutionDir)zlib\lib\zlib.lib;%(AdditionalDependencies)
127 |
128 |
129 | xcopy /y /d "$(SolutionDir)zlib\bin\zlib1.dll" "$(OutDir)"
130 | Copy zlib1.dll to the output folder
131 |
132 |
133 |
134 |
135 | Level3
136 | Disabled
137 | true
138 | true
139 |
140 |
141 |
142 |
143 | Level3
144 | MaxSpeed
145 | true
146 | true
147 | true
148 | true
149 |
150 |
151 | true
152 | true
153 |
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/Asmodean/Asmodean.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Header Files
20 |
21 |
22 | Header Files
23 |
24 |
25 | Header Files
26 |
27 |
28 | Header Files
29 |
30 |
31 |
32 |
33 | Source Files
34 |
35 |
36 | Source Files
37 |
38 |
39 | Source Files
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Asmodean/asmodean.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #ifndef ASMODEAN_DLL_H
4 | #define ASMODEAN_DLL_H
5 |
6 | #define ASMODEAN_API extern "C" __declspec(dllexport)
7 |
8 | #endif /* ASMODEAN_DLL */
--------------------------------------------------------------------------------
/Asmodean/blowfish.cpp:
--------------------------------------------------------------------------------
1 | // blowfish.cpp C++ class implementation of the BLOWFISH encryption algorithm
2 | // _THE BLOWFISH ENCRYPTION ALGORITHM_
3 | // by Bruce Schneier
4 | // Revised code--3/20/94
5 | // Converted to C++ class 5/96, Jim Conger
6 |
7 | #include "blowfish.h"
8 |
9 | #define S(x,i) (SBoxes[i][x.w.byte##i])
10 | #define bf_F(x) (((S(x,0) + S(x,1)) ^ S(x,2)) + S(x,3))
11 | #define ROUND(a,b,n) (a.dword ^= bf_F(b) ^ PArray[n])
12 |
13 |
14 | Blowfish::Blowfish() {
15 | PArray = new DWORD[18];
16 | SBoxes = new DWORD[4][256];
17 | }
18 |
19 | Blowfish::~Blowfish() {
20 | delete PArray;
21 | delete[] SBoxes;
22 | }
23 |
24 | // the low level (private) encryption function
25 | void Blowfish::Blowfish_encipher(DWORD *xl, DWORD *xr) {
26 | union aword Xl, Xr;
27 |
28 | Xl.dword = *xl;
29 | Xr.dword = *xr;
30 |
31 | Xl.dword ^= PArray[0];
32 | ROUND(Xr, Xl, 1); ROUND(Xl, Xr, 2);
33 | ROUND(Xr, Xl, 3); ROUND(Xl, Xr, 4);
34 | ROUND(Xr, Xl, 5); ROUND(Xl, Xr, 6);
35 | ROUND(Xr, Xl, 7); ROUND(Xl, Xr, 8);
36 | ROUND(Xr, Xl, 9); ROUND(Xl, Xr, 10);
37 | ROUND(Xr, Xl, 11); ROUND(Xl, Xr, 12);
38 | ROUND(Xr, Xl, 13); ROUND(Xl, Xr, 14);
39 | ROUND(Xr, Xl, 15); ROUND(Xl, Xr, 16);
40 | Xr.dword ^= PArray[17];
41 |
42 | *xr = Xl.dword;
43 | *xl = Xr.dword;
44 | }
45 |
46 | // the low level (private) decryption function
47 | void Blowfish::Blowfish_decipher(DWORD *xl, DWORD *xr) {
48 | union aword Xl;
49 | union aword Xr;
50 |
51 | Xl.dword = *xl;
52 | Xr.dword = *xr;
53 |
54 | Xl.dword ^= PArray[17];
55 | ROUND(Xr, Xl, 16); ROUND(Xl, Xr, 15);
56 | ROUND(Xr, Xl, 14); ROUND(Xl, Xr, 13);
57 | ROUND(Xr, Xl, 12); ROUND(Xl, Xr, 11);
58 | ROUND(Xr, Xl, 10); ROUND(Xl, Xr, 9);
59 | ROUND(Xr, Xl, 8); ROUND(Xl, Xr, 7);
60 | ROUND(Xr, Xl, 6); ROUND(Xl, Xr, 5);
61 | ROUND(Xr, Xl, 4); ROUND(Xl, Xr, 3);
62 | ROUND(Xr, Xl, 2); ROUND(Xl, Xr, 1);
63 | Xr.dword ^= PArray[0];
64 |
65 | *xl = Xr.dword;
66 | *xr = Xl.dword;
67 | }
68 |
69 |
70 | // constructs the enctryption sieve
71 | void Blowfish::Initialize(BYTE key[], int keybytes) {
72 | int i, j;
73 | DWORD data, datal, datar;
74 | union aword temp;
75 |
76 | // first fill arrays from data tables
77 | for (i = 0; i < 18; i++)
78 | PArray[i] = bf_P[i];
79 |
80 | for (i = 0; i < 4; i++) {
81 | for (j = 0; j < 256; j++)
82 | SBoxes[i][j] = bf_S[i][j];
83 | }
84 |
85 |
86 | j = 0;
87 | for (i = 0; i < NPASS + 2; ++i) {
88 | temp.dword = 0;
89 | temp.w.byte0 = key[j];
90 | temp.w.byte1 = key[(j + 1) % keybytes];
91 | temp.w.byte2 = key[(j + 2) % keybytes];
92 | temp.w.byte3 = key[(j + 3) % keybytes];
93 | data = temp.dword;
94 | PArray[i] ^= data;
95 | j = (j + 4) % keybytes;
96 | }
97 |
98 | datal = 0;
99 | datar = 0;
100 |
101 | for (i = 0; i < NPASS + 2; i += 2) {
102 | Blowfish_encipher(&datal, &datar);
103 | PArray[i] = datal;
104 | PArray[i + 1] = datar;
105 | }
106 |
107 | for (i = 0; i < 4; ++i) {
108 | for (j = 0; j < 256; j += 2) {
109 | Blowfish_encipher(&datal, &datar);
110 | SBoxes[i][j] = datal;
111 | SBoxes[i][j + 1] = datar;
112 | }
113 | }
114 | }
115 |
116 | // get output length, which must be even MOD 8
117 | DWORD Blowfish::GetOutputLength(DWORD lInputLong) {
118 | DWORD lVal;
119 |
120 | lVal = lInputLong % 8; // find out if uneven number of bytes atthe end
121 | if (lVal != 0)
122 | return lInputLong + 8 - lVal;
123 | else
124 | return lInputLong;
125 | }
126 |
127 | // Encode pIntput into pOutput. Input length in lSize. Returned value
128 | // is length of output which will be even MOD 8 bytes. Inputbuffer and
129 | // output buffer can be the same, but be sure buffer length is even MOD8.
130 | DWORD Blowfish::Encode(BYTE * pInput, BYTE * pOutput, DWORD lSize) {
131 | DWORD lCount, lOutSize, lGoodBytes;
132 | BYTE *pi, *po;
133 | int i, j;
134 | int SameDest = (pInput == pOutput ? 1 : 0);
135 |
136 | lOutSize = GetOutputLength(lSize);
137 | for (lCount = 0; lCount < lOutSize; lCount += 8) {
138 | if (SameDest) // if encoded data is being written into inputbuffer
139 | {
140 | if (lCount < lSize - 7) // if not dealing with unevenbytes at end
141 | {
142 | Blowfish_encipher((DWORD *)pInput,
143 | (DWORD *)(pInput + 4));
144 | }
145 | else // pad end of data with null bytes tocomplete encryption
146 | {
147 | po = pInput + lSize; // point at bytepast theend of actual data
148 | j = (int)(lOutSize - lSize); // number ofbytes to set to null
149 | for (i = 0; i < j; i++)
150 | *po++ = 0;
151 | Blowfish_encipher((DWORD *)pInput,
152 | (DWORD *)(pInput + 4));
153 | }
154 | pInput += 8;
155 | }
156 | else // output buffer not equal to inputbuffer, so must copy
157 | { // input to output buffer prior to encrypting
158 | if (lCount < lSize - 7) // if not dealing with unevenbytes at end
159 | {
160 | pi = pInput;
161 | po = pOutput;
162 | for (i = 0; i < 8; i++)
163 | // copy bytes to output
164 | *po++ = *pi++;
165 | Blowfish_encipher((DWORD *)pOutput, // nowencrypt them
166 | (DWORD *)(pOutput + 4));
167 | }
168 | else // pad end of data with null bytes tocomplete encryption
169 | {
170 | lGoodBytes = lSize - lCount; // number ofremaining data bytes
171 | po = pOutput;
172 | for (i = 0; i < (int)lGoodBytes; i++)
173 | *po++ = *pInput++;
174 | for (j = i; j < 8; j++)
175 | *po++ = 0;
176 | Blowfish_encipher((DWORD *)pOutput,
177 | (DWORD *)(pOutput + 4));
178 | }
179 | pInput += 8;
180 | pOutput += 8;
181 | }
182 | }
183 | return lOutSize;
184 | }
185 |
186 | // Decode pIntput into pOutput. Input length in lSize. Inputbuffer and
187 | // output buffer can be the same, but be sure buffer length is even MOD8.
188 | void Blowfish::Decode(BYTE * pInput, BYTE * pOutput, DWORD lSize) {
189 | DWORD lCount;
190 | BYTE *pi, *po;
191 | int i;
192 | int SameDest = (pInput == pOutput ? 1 : 0);
193 |
194 | for (lCount = 0; lCount < lSize; lCount += 8) {
195 | if (SameDest) // if encoded data is being written into inputbuffer
196 | {
197 | Blowfish_decipher((DWORD *)pInput,
198 | (DWORD *)(pInput + 4));
199 | pInput += 8;
200 | }
201 | else // output buffer not equal to inputbuffer
202 | { // so copy input to output before decoding
203 | pi = pInput;
204 | po = pOutput;
205 | for (i = 0; i < 8; i++)
206 | *po++ = *pi++;
207 | Blowfish_decipher((DWORD *)pOutput,
208 | (DWORD *)(pOutput + 4));
209 | pInput += 8;
210 | pOutput += 8;
211 | }
212 | }
213 | }
214 |
215 |
216 | void Blowfish::Set_Key(BYTE key[], int keybytes) {
217 | Initialize(key, keybytes);
218 | }
219 |
220 | DWORD Blowfish::Encrypt(BYTE * pInput, DWORD lSize) {
221 | if (lSize != GetOutputLength(lSize))
222 | printf("%s", "Input len != Output len");
223 |
224 | BYTE *pOutput = new BYTE[lSize];
225 | DWORD ret = Encode(pInput, pOutput, lSize);
226 |
227 | memcpy(pInput, pOutput, lSize);
228 | delete[] pOutput;
229 |
230 | return ret;
231 | }
232 |
233 | void Blowfish::Decrypt(BYTE * pInput, DWORD lSize) {
234 | if (lSize != GetOutputLength(lSize))
235 | printf("%s", "Input len != Output len");
236 |
237 | BYTE *pOutput = new BYTE[lSize];
238 | Decode(pInput, pOutput, lSize);
239 |
240 | memcpy(pInput, pOutput, lSize);
241 | delete[] pOutput;
242 | }
243 |
244 |
245 |
--------------------------------------------------------------------------------
/Asmodean/exkifint.cpp:
--------------------------------------------------------------------------------
1 | // exkifint.cpp (for P/Invoke), 2018/6/5
2 | // originally code by asmodean
3 |
4 | // contact:
5 | // web: http://asmodean.reverse.net
6 | // email: asmodean [at] hush.com
7 | // irc: asmodean on efnet (irc.efnet.net)
8 |
9 | // This code helps extracts data from Windmill's encrypted KIF (*.int) archives.
10 | #include "exkifint.h"
11 | #include "blowfish.h"
12 |
13 | void DecryptVCode2(
14 | unsigned char* keyBuffer,
15 | unsigned long keyLength,
16 | unsigned char* vcode2Buffer,
17 | unsigned long vcode2Length)
18 | {
19 | Blowfish bf;
20 | bf.Set_Key(keyBuffer, keyLength);
21 | bf.Decrypt(vcode2Buffer, (vcode2Length + 7) & ~7);
22 | }
23 |
24 | void DecryptEntry(
25 | KIFENTRYINFO& entry,
26 | unsigned long fileKey)
27 | {
28 | Blowfish bf;
29 | bf.Set_Key((unsigned char*)&fileKey, 4);
30 | bf.Decrypt((unsigned char*)&entry.offset, 8);
31 | }
32 |
33 | void DecryptData(
34 | unsigned char* buffer,
35 | unsigned long length,
36 | unsigned long fileKey)
37 | {
38 | Blowfish bf;
39 | bf.Set_Key((unsigned char*)&fileKey, 4);
40 | bf.Decrypt(buffer, (length / 8) * 8);
41 | }
42 |
--------------------------------------------------------------------------------
/Asmodean/exkifint.h:
--------------------------------------------------------------------------------
1 | // exkifint.h (for P/Invoke), 2018/6/5
2 | // originally code by asmodean
3 |
4 | // contact:
5 | // web: http://asmodean.reverse.net
6 | // email: asmodean [at] hush.com
7 | // irc: asmodean on efnet (irc.efnet.net)
8 |
9 | // This code helps extracts data from Windmill's encrypted KIF (*.int) archives.
10 | #pragma once
11 |
12 | #ifndef EXKIFINT_H
13 | #define EXKIFINT_H
14 |
15 | #include "asmodean.h"
16 |
17 | struct KIFENTRYINFO {
18 | unsigned long offset;
19 | unsigned long length;
20 | };
21 |
22 | ASMODEAN_API void DecryptVCode2(
23 | unsigned char* keyBuffer,
24 | unsigned long keyLength,
25 | unsigned char* vcode2Buffer,
26 | unsigned long vcode2Length);
27 |
28 | ASMODEAN_API void DecryptEntry(
29 | KIFENTRYINFO& entry,
30 | unsigned long fileKey);
31 |
32 | ASMODEAN_API void DecryptData(
33 | unsigned char* buffer,
34 | unsigned long length,
35 | unsigned long fileKey);
36 |
37 | #endif /* EXKIFINT_H */
--------------------------------------------------------------------------------
/Asmodean/hgx2bmp.cpp:
--------------------------------------------------------------------------------
1 | // hgx2bmp.cpp, (for P/Invoke), 2018/6/5
2 | // originally code by asmodean
3 |
4 | // contact:
5 | // web: http://asmodean.reverse.net
6 | // email: asmodean [at] hush.com
7 | // irc: asmodean on efnet (irc.efnet.net)
8 |
9 | // This code helps decompress Windmill's HG-3 (*.hg3) and HG-2 (*.hg2) images.
10 | #include "hgx2bmp.h"
11 | #include
12 | #include
13 | #include
14 | #include "zlib.h"
15 |
16 | class bitbuff_t {
17 | public:
18 | bitbuff_t(unsigned char* buff, unsigned long len)
19 | : buff(buff),
20 | len(len),
21 | index(0) {
22 | }
23 |
24 | bool get_bit(void) {
25 | if (index > 7) {
26 | buff++;
27 | len--;
28 | index = 0;
29 | }
30 |
31 | return (*buff >> index++) & 1;
32 | }
33 |
34 | // Didn't expect to see this in the wild...
35 | unsigned long get_elias_gamma_value(void) {
36 | unsigned long value = 0;
37 | unsigned long digits = 0;
38 |
39 | while (!get_bit()) digits++;
40 |
41 | value = 1 << digits;
42 |
43 | while (digits--) {
44 | if (get_bit()) {
45 | value |= 1 << digits;
46 | }
47 | }
48 |
49 | return value;
50 | }
51 |
52 | private:
53 | unsigned long index;
54 | unsigned char* buff;
55 | unsigned long len;
56 | };
57 |
58 | // This encoding tries to optimize for lots of zeros. I think. :)
59 | unsigned char unpack_val(unsigned char c) {
60 | unsigned char z = c & 1 ? 0xFF : 0;
61 | return (c >> 1) ^ z;
62 | }
63 |
64 | void unrle(
65 | unsigned char* buffer,
66 | unsigned long length,
67 | unsigned char* cmdBuffer,
68 | unsigned long cmdLength,
69 | unsigned char*& outBuffer,
70 | unsigned long& outLength)
71 | {
72 | bitbuff_t cmdBits(cmdBuffer, cmdLength);
73 |
74 | bool copyFlag = cmdBits.get_bit();
75 |
76 | outLength = cmdBits.get_elias_gamma_value();
77 | outBuffer = new unsigned char[outLength];
78 |
79 | unsigned long n = 0;
80 | for (unsigned long i = 0; i < outLength; i += n) {
81 | n = cmdBits.get_elias_gamma_value();
82 |
83 | if (copyFlag) {
84 | memcpy(outBuffer + i, buffer, n);
85 | buffer += n;
86 | }
87 | else {
88 | memset(outBuffer + i, 0, n);
89 | }
90 |
91 | copyFlag = !copyFlag;
92 | }
93 | }
94 |
95 | void undeltafilter(
96 | unsigned char* buffer,
97 | unsigned long length,
98 | unsigned char* outBuffer,
99 | unsigned long width,
100 | unsigned long height,
101 | unsigned long depthBytes)
102 | {
103 | unsigned long table1[256] = { 0 };
104 | unsigned long table2[256] = { 0 };
105 | unsigned long table3[256] = { 0 };
106 | unsigned long table4[256] = { 0 };
107 |
108 | for (unsigned long i = 0; i < 256; i++) {
109 | unsigned long val = i & 0xC0;
110 |
111 | val <<= 6;
112 | val |= i & 0x30;
113 |
114 | val <<= 6;
115 | val |= i & 0x0C;
116 |
117 | val <<= 6;
118 | val |= i & 0x03;
119 |
120 | table4[i] = val;
121 | table3[i] = val << 2;
122 | table2[i] = val << 4;
123 | table1[i] = val << 6;
124 | }
125 |
126 | unsigned long sect_len = length / 4;
127 | unsigned char* sect1 = buffer;
128 | unsigned char* sect2 = sect1 + sect_len;
129 | unsigned char* sect3 = sect2 + sect_len;
130 | unsigned char* sect4 = sect3 + sect_len;
131 |
132 | unsigned char* outP = outBuffer;
133 | unsigned char* outEnd = outBuffer + length;
134 |
135 | while (outP < outEnd) {
136 | unsigned long val = table1[*sect1++] | table2[*sect2++] | table3[*sect3++] | table4[*sect4++];
137 |
138 | *outP++ = unpack_val((unsigned char)(val >> 0));
139 | *outP++ = unpack_val((unsigned char)(val >> 8));
140 | *outP++ = unpack_val((unsigned char)(val >> 16));
141 | *outP++ = unpack_val((unsigned char)(val >> 24));
142 | }
143 |
144 | unsigned long stride = width * depthBytes;
145 |
146 | for (unsigned long x = depthBytes; x < stride; x++) {
147 | outBuffer[x] += outBuffer[x - depthBytes];
148 | }
149 |
150 | for (unsigned long y = 1; y < height; y++) {
151 | unsigned char* line = outBuffer + y * stride;
152 | unsigned char* prev = outBuffer + (y - 1) * stride;
153 |
154 | for (unsigned long x = 0; x < stride; x++) {
155 | line[x] += prev[x];
156 | }
157 | }
158 | }
159 |
160 | void ProcessImage(
161 | unsigned char* bufferTmp,
162 | unsigned long length,
163 | unsigned long origLength,
164 | unsigned char* cmdBufferTmp,
165 | unsigned long cmdLength,
166 | unsigned long origCmdLength,
167 | unsigned char*& rgbaBuffer,
168 | unsigned long& rgbaLength,
169 | unsigned long width,
170 | unsigned long height,
171 | unsigned long depthBytes)
172 | {
173 | unsigned char* buffer = new unsigned char[origLength];
174 | uncompress(buffer, &origLength, bufferTmp, length);
175 |
176 | unsigned char* cmdBuffer = new unsigned char[origCmdLength];
177 | uncompress(cmdBuffer, &origCmdLength, cmdBufferTmp, cmdLength);
178 |
179 | unsigned long outLength = 0;
180 | unsigned char* outBuffer = nullptr;
181 | unrle(buffer, origLength, cmdBuffer, origCmdLength, outBuffer, outLength);
182 |
183 | rgbaLength = outLength;
184 | rgbaBuffer = (unsigned char*)GlobalAlloc(GMEM_FIXED, rgbaLength);
185 | //rgbaBuffer = new unsigned char[rgbaLength];
186 | /*if (outLength == width * height * 4) {
187 | undeltafilter(outBuffer, outLength, rgbaBuffer, width, height, depthBytes);
188 | //printf("\n%i ", (outLength - width * height * 4));
189 | //Beep(500, 2000);
190 | }*/
191 | undeltafilter(outBuffer, outLength, rgbaBuffer, width, height, depthBytes);
192 |
193 | delete[] outBuffer;
194 | delete[] cmdBuffer;
195 | delete[] buffer;
196 | }
197 |
--------------------------------------------------------------------------------
/Asmodean/hgx2bmp.h:
--------------------------------------------------------------------------------
1 | // hgx2bmp.h, (for P/Invoke), 2018/6/5
2 | // originally code by asmodean
3 |
4 | // contact:
5 | // web: http://asmodean.reverse.net
6 | // email: asmodean [at] hush.com
7 | // irc: asmodean on efnet (irc.efnet.net)
8 |
9 | // This code helps decompress Windmill's HG-3 (*.hg3) and HG-2 (*.hg2) images.
10 | #pragma once
11 |
12 | #ifndef HGX2BMP_H
13 | #define HGX2BMP_H
14 |
15 | #include "asmodean.h"
16 |
17 | /* Make sure to free returned rgbaBuffer! */
18 | ASMODEAN_API void ProcessImage(
19 | unsigned char* bufferTmp,
20 | unsigned long length,
21 | unsigned long origLength,
22 | unsigned char* cmdBufferTmp,
23 | unsigned long cmdLength,
24 | unsigned long origCmdLength,
25 | unsigned char*& rgbaBuffer,
26 | unsigned long& rgbaLength,
27 | unsigned long width,
28 | unsigned long height,
29 | unsigned long depthBytes);
30 |
31 | #endif /* HGX2BMP_H */
--------------------------------------------------------------------------------
/GrisaiaExtractor.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27130.2027
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GrisaiaExtractor", "GrisaiaExtractor\GrisaiaExtractor.csproj", "{B9E8EA56-874B-4CEB-A703-DCA3A307A4D3}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GrisaiaExtractorConsole", "GrisaiaExtractorConsole\GrisaiaExtractorConsole.csproj", "{1B2D824A-DD0D-4019-B234-54E5543B7A42}"
9 | EndProject
10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "asmodean", "Asmodean\Asmodean.vcxproj", "{5D227B71-C303-400C-8E99-DF63C79E3613}"
11 | EndProject
12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Native", "Native", "{D2B3D9D8-003A-4BC4-B53F-D942F09ED122}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Any CPU = Debug|Any CPU
17 | Debug|x64 = Debug|x64
18 | Debug|x86 = Debug|x86
19 | Release|Any CPU = Release|Any CPU
20 | Release|x64 = Release|x64
21 | Release|x86 = Release|x86
22 | EndGlobalSection
23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 | {B9E8EA56-874B-4CEB-A703-DCA3A307A4D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {B9E8EA56-874B-4CEB-A703-DCA3A307A4D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {B9E8EA56-874B-4CEB-A703-DCA3A307A4D3}.Debug|x64.ActiveCfg = Debug|Any CPU
27 | {B9E8EA56-874B-4CEB-A703-DCA3A307A4D3}.Debug|x64.Build.0 = Debug|Any CPU
28 | {B9E8EA56-874B-4CEB-A703-DCA3A307A4D3}.Debug|x86.ActiveCfg = Debug|Any CPU
29 | {B9E8EA56-874B-4CEB-A703-DCA3A307A4D3}.Debug|x86.Build.0 = Debug|Any CPU
30 | {B9E8EA56-874B-4CEB-A703-DCA3A307A4D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {B9E8EA56-874B-4CEB-A703-DCA3A307A4D3}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {B9E8EA56-874B-4CEB-A703-DCA3A307A4D3}.Release|x64.ActiveCfg = Release|Any CPU
33 | {B9E8EA56-874B-4CEB-A703-DCA3A307A4D3}.Release|x64.Build.0 = Release|Any CPU
34 | {B9E8EA56-874B-4CEB-A703-DCA3A307A4D3}.Release|x86.ActiveCfg = Release|Any CPU
35 | {B9E8EA56-874B-4CEB-A703-DCA3A307A4D3}.Release|x86.Build.0 = Release|Any CPU
36 | {1B2D824A-DD0D-4019-B234-54E5543B7A42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {1B2D824A-DD0D-4019-B234-54E5543B7A42}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {1B2D824A-DD0D-4019-B234-54E5543B7A42}.Debug|x64.ActiveCfg = Debug|Any CPU
39 | {1B2D824A-DD0D-4019-B234-54E5543B7A42}.Debug|x64.Build.0 = Debug|Any CPU
40 | {1B2D824A-DD0D-4019-B234-54E5543B7A42}.Debug|x86.ActiveCfg = Debug|Any CPU
41 | {1B2D824A-DD0D-4019-B234-54E5543B7A42}.Debug|x86.Build.0 = Debug|Any CPU
42 | {1B2D824A-DD0D-4019-B234-54E5543B7A42}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 | {1B2D824A-DD0D-4019-B234-54E5543B7A42}.Release|Any CPU.Build.0 = Release|Any CPU
44 | {1B2D824A-DD0D-4019-B234-54E5543B7A42}.Release|x64.ActiveCfg = Release|Any CPU
45 | {1B2D824A-DD0D-4019-B234-54E5543B7A42}.Release|x64.Build.0 = Release|Any CPU
46 | {1B2D824A-DD0D-4019-B234-54E5543B7A42}.Release|x86.ActiveCfg = Release|Any CPU
47 | {1B2D824A-DD0D-4019-B234-54E5543B7A42}.Release|x86.Build.0 = Release|Any CPU
48 | {5D227B71-C303-400C-8E99-DF63C79E3613}.Debug|Any CPU.ActiveCfg = Release|Win32
49 | {5D227B71-C303-400C-8E99-DF63C79E3613}.Debug|Any CPU.Build.0 = Release|Win32
50 | {5D227B71-C303-400C-8E99-DF63C79E3613}.Debug|x64.ActiveCfg = Debug|x64
51 | {5D227B71-C303-400C-8E99-DF63C79E3613}.Debug|x64.Build.0 = Debug|x64
52 | {5D227B71-C303-400C-8E99-DF63C79E3613}.Debug|x86.ActiveCfg = Debug|Win32
53 | {5D227B71-C303-400C-8E99-DF63C79E3613}.Debug|x86.Build.0 = Debug|Win32
54 | {5D227B71-C303-400C-8E99-DF63C79E3613}.Release|Any CPU.ActiveCfg = Release|Win32
55 | {5D227B71-C303-400C-8E99-DF63C79E3613}.Release|Any CPU.Build.0 = Release|Win32
56 | {5D227B71-C303-400C-8E99-DF63C79E3613}.Release|x64.ActiveCfg = Release|x64
57 | {5D227B71-C303-400C-8E99-DF63C79E3613}.Release|x64.Build.0 = Release|x64
58 | {5D227B71-C303-400C-8E99-DF63C79E3613}.Release|x86.ActiveCfg = Release|Win32
59 | {5D227B71-C303-400C-8E99-DF63C79E3613}.Release|x86.Build.0 = Release|Win32
60 | EndGlobalSection
61 | GlobalSection(SolutionProperties) = preSolution
62 | HideSolutionNode = FALSE
63 | EndGlobalSection
64 | GlobalSection(NestedProjects) = preSolution
65 | {5D227B71-C303-400C-8E99-DF63C79E3613} = {D2B3D9D8-003A-4BC4-B53F-D942F09ED122}
66 | EndGlobalSection
67 | GlobalSection(ExtensibilityGlobals) = postSolution
68 | SolutionGuid = {C48F6F6E-84B6-4BF8-AE32-6ECAD7113C0C}
69 | EndGlobalSection
70 | EndGlobal
71 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/AnimationHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Text.RegularExpressions;
7 | using System.Threading.Tasks;
8 |
9 | namespace GrisaiaExtractor {
10 | /// A static class for help with animation file names.
11 | public static class AnimationHelper {
12 |
13 | /// Matches an animation and its indexes.
14 | public static Regex AnimationRegex = new Regex(@"^(?'name'.*)(?:\+(?'indexA'\d\d\d)\+(?'indexB'\d\d\d))$");
15 |
16 | /// Gets the filename without extension or animation postfix.
17 | public static string GetBaseFileName(string path) {
18 | return GetBaseFileName(path, out _, out _);
19 | }
20 |
21 | /// Gets the filename without extension or animation postfix.
22 | public static string GetBaseFileName(string path, out bool isAnimation) {
23 | string baseName = GetBaseFileName(path, out int indexA, out int indexB);
24 | isAnimation = indexA != -1 || indexB != -1;
25 | return baseName;
26 | }
27 |
28 | /// Returns true if the file has an animation postfix.
29 | public static bool IsAnimation(string path) {
30 | return AnimationRegex.IsMatch(Path.GetFileNameWithoutExtension(path));
31 | }
32 |
33 | /// Returns true if the file has an animation postfix and outputs the indexes.
34 | public static bool IsAnimation(string path, out int indexA, out int indexB) {
35 | string fileNameNoExt = Path.GetFileNameWithoutExtension(path);
36 | Match match = AnimationRegex.Match(fileNameNoExt);
37 | if (match.Success) {
38 | indexA = int.Parse(match.Groups["indexA"].Value);
39 | indexB = int.Parse(match.Groups["indexB"].Value);
40 | return true;
41 | }
42 | indexA = indexB = -1;
43 | return false;
44 | }
45 |
46 | /// Gets the filename without extension or animation postfix.
47 | /// Outputs the animation indexes if they exist, otherwise, -1.
48 | public static string GetBaseFileName(string path, out int indexA, out int indexB) {
49 | string fileNameNoExt = Path.GetFileNameWithoutExtension(path);
50 | Match match = AnimationRegex.Match(fileNameNoExt);
51 | if (match.Success) {
52 | indexA = int.Parse(match.Groups["indexA"].Value);
53 | indexB = int.Parse(match.Groups["indexB"].Value);
54 | return match.Groups["name"].Value;
55 | }
56 | indexA = indexB = -1;
57 | return fileNameNoExt;
58 | }
59 |
60 | /// Gets all filenames associated with this file.
61 | public static string[] GetFileNames(string path, string ext = null) {
62 | List files = new List();
63 | string dir = Path.GetDirectoryName(path);
64 | string name = GetBaseFileName(path);
65 | if (ext == null)
66 | ext = Path.GetExtension(path);
67 |
68 | // Add the base file if one exists
69 | string file = Path.Combine(dir, name + ext);
70 | if (File.Exists(file))
71 | files.Add(file);
72 |
73 | // Look for files that end with +###+###
74 | // These are mostly used with animations
75 | // Check both +000+000 and +001+000 as first possible name
76 | for (int j = 0; ; j++) {
77 | file = GetFileNameQuick(dir, name, j, 0, ext);
78 | if (!File.Exists(file)) {
79 | if (j == 0)
80 | continue;
81 | else
82 | break;
83 | }
84 |
85 | files.Add(file);
86 |
87 | for (int k = 1; ; k++) {
88 | file = GetFileNameQuick(dir, name, j, k, ext);
89 | if (!File.Exists(file))
90 | break;
91 | files.Add(file);
92 | }
93 | }
94 | return files.ToArray();
95 | }
96 |
97 | /// Gets the filepath with the animation postfix and extension.
98 | /// Assumes the filename is just a name with no extension
99 | public static string GetFileNameQuick(string dir, string name, int indexA, int indexB, string ext = "") {
100 | return Path.Combine(dir,
101 | $"{name}" +
102 | $"+{indexA.ToString("000")}" +
103 | $"+{indexB.ToString("000")}" +
104 | $"{ext}");
105 | }
106 |
107 | /// Gets the filepath with the animation postfix and extension.
108 | public static string GetFileName(string dir, string file, int indexA, int indexB, string ext = "") {
109 | return Path.Combine(dir,
110 | $"{Path.GetFileNameWithoutExtension(file)}" +
111 | $"+{indexA.ToString("000")}" +
112 | $"+{indexB.ToString("000")}" +
113 | $"{ext}");
114 | }
115 |
116 | /// Gets the filepath with the animation postfix.
117 | public static string GetFileName(string filePath, int indexA, int indexB, string ext = "") {
118 | return
119 | $"{Path.ChangeExtension(filePath, null)}" +
120 | $"+{indexA.ToString("000")}" +
121 | $"+{indexB.ToString("000")}" +
122 | $"{ext}";
123 | }
124 |
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Asmodean/Exkifint.MersenneTwister.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.CompilerServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace GrisaiaExtractor.Asmodean {
9 | public static partial class Exkifint {
10 | private class MersenneTwister {
11 | #region Constants
12 |
13 | private const int N = 624;
14 | private const int M = 397;
15 | private const uint MATRIX_A = 0x9908b0df;
16 | private const uint UPPER_MASK = 0x80000000;
17 | private const uint LOWER_MASK = 0x7fffffff;
18 |
19 | private const uint TEMPERING_MASK_B = 0x9d2c5680;
20 | private const uint TEMPERING_MASK_C = 0xefc60000;
21 |
22 | #endregion
23 |
24 | #region Fields
25 |
26 | private uint dummy = 0;
27 | private uint mti = N + 1;
28 | private readonly uint[] mt = new uint[N];
29 |
30 | #endregion
31 |
32 | #region Constructors
33 |
34 | public MersenneTwister() { }
35 | public MersenneTwister(int seed) {
36 | Seed(seed);
37 | }
38 | public MersenneTwister(uint seed) {
39 | Seed(seed);
40 | }
41 |
42 | #endregion
43 |
44 | #region Seed
45 |
46 | public void Seed(int seed) => Seed(unchecked((uint) seed));
47 | public void Seed(uint seed) {
48 | for (int i = 0; i < N; i++) {
49 | mt[i] = seed & 0xffff0000;
50 | seed = 69069 * seed + 1;
51 | mt[i] |= (seed & 0xffff0000) >> 16;
52 | seed = 69069 * seed + 1;
53 | }
54 | mti = N;
55 | dummy = mti;
56 | }
57 |
58 | #endregion
59 |
60 | #region GenRand
61 |
62 | public uint GenRand() {
63 | uint y;
64 | uint[] mag01 = { 0x0, MATRIX_A };
65 | /* mag01[x] = x * MATRIX_A for x=0,1 */
66 |
67 | mti = dummy;
68 |
69 | if (mti >= N) { /* generate N words at one time */
70 | int kk;
71 |
72 | if (mti == N + 1) /* if sgenrand() has not been called, */
73 | Seed(4357); /* a default initial seed is used */
74 |
75 | for (kk = 0; kk < N - M; kk++) {
76 | y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
77 | mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1];
78 | }
79 | for (; kk < N - 1; kk++) {
80 | y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
81 | mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1];
82 | }
83 | y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
84 | mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1];
85 |
86 | mti = 0;
87 | }
88 |
89 | y = mt[mti++];
90 | y ^= TEMPERING_SHIFT_U(y);
91 | y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
92 | y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
93 | y ^= TEMPERING_SHIFT_L(y);
94 | dummy = mti;
95 |
96 | return y;
97 | }
98 |
99 | #endregion
100 |
101 | #region Static GenRand
102 |
103 | public static uint GenRand(int seed) {
104 | return new MersenneTwister(seed).GenRand();
105 | }
106 | public static uint GenRand(uint seed) {
107 | return new MersenneTwister(seed).GenRand();
108 | }
109 |
110 | #endregion
111 |
112 | #region Tempering Shift
113 |
114 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
115 | private static uint TEMPERING_SHIFT_U(uint y) => y >> 11;
116 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
117 | private static uint TEMPERING_SHIFT_S(uint y) => y << 7;
118 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
119 | private static uint TEMPERING_SHIFT_T(uint y) => y << 15;
120 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
121 | private static uint TEMPERING_SHIFT_L(uint y) => y >> 18;
122 |
123 | #endregion
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Asmodean/Exkifint.PInvoke.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace GrisaiaExtractor.Asmodean {
9 | public static partial class Exkifint {
10 |
11 | private const uint LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020;
12 |
13 | [DllImport("kernel32.dll")]
14 | private extern static IntPtr LoadLibraryEx(string lpLibFileName, IntPtr hFile, uint dwFlags);
15 |
16 | [DllImport("kernel32.dll")]
17 | [return: MarshalAs(UnmanagedType.I1)]
18 | private extern static bool FreeLibrary(IntPtr hLibModule);
19 |
20 | [DllImport("kernel32.dll")]
21 | private extern static IntPtr FindResource(IntPtr hModule, string lpName, string lpType);
22 |
23 | [DllImport("kernel32.dll", SetLastError = true)]
24 | private extern static IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
25 |
26 | [DllImport("kernel32.dll", SetLastError = true)]
27 | private extern static uint SizeofResource(IntPtr hModule, IntPtr hResInfo);
28 |
29 | [DllImport("kernel32.dll")]
30 | private extern static IntPtr LockResource(IntPtr hGlobal);
31 |
32 |
33 | [DllImport("asmodean.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
34 | [return: MarshalAs(UnmanagedType.LPStr)]
35 | private extern static void DecryptVCode2(
36 | byte[] keyBuffer,
37 | int keyLength,
38 | byte[] vcode2Buffer,
39 | int vcode2Length);
40 |
41 | [DllImport("asmodean.dll", CallingConvention = CallingConvention.Cdecl)]
42 | private extern static void DecryptEntry(
43 | ref KIFENTRYINFO entry,
44 | uint fileKey);
45 |
46 | [DllImport("asmodean.dll", CallingConvention = CallingConvention.Cdecl)]
47 | private extern static void DecryptData(
48 | byte[] buffer,
49 | int length,
50 | uint fileKey);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Asmodean/Exkifint.Structs.cs:
--------------------------------------------------------------------------------
1 | using GrisaiaExtractor.Extensions;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Runtime.InteropServices;
6 | using System.Runtime.Serialization.Formatters.Binary;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace GrisaiaExtractor.Asmodean {
11 | public static partial class Exkifint {
12 | [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 8, CharSet = CharSet.Ansi)]
13 | private struct KIFHDR {
14 | ///
15 | /// The raw character array signature of the file.
16 | ///
17 | [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 4)]
18 | public char[] SignatureRaw;
19 | ///
20 | /// The number of s in the KIFINT archive.
21 | ///
22 | public int EntryCount;
23 |
24 | ///
25 | /// Gets the signature of the file.
26 | ///
27 | public string Signature => SignatureRaw.ToNullTerminatedString();
28 | }
29 |
30 | [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 72, CharSet = CharSet.Ansi)]
31 | private struct KIFENTRY {
32 | ///
33 | /// We use this to preserve the developer naming fuckups such as the full-width 'g' in
34 | /// Meikyuu's "bg62t.hg3".
35 | ///
36 | private static readonly Encoding JapaneseEncoding = Encoding.GetEncoding(932);
37 |
38 | ///
39 | /// The raw character array filename of the entry.
40 | ///
41 | [FieldOffset(0)]
42 | [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 64)]
43 | public byte[] FileNameRaw;
44 | ///
45 | /// We don't need to pass the during P/Invoke, so we have this info
46 | /// structure.
47 | ///
48 | [FieldOffset(64)]
49 | public KIFENTRYINFO Info;
50 | ///
51 | /// The file offset to the entry's data.
52 | ///
53 | [FieldOffset(64)]
54 | public uint Offset;
55 | ///
56 | /// The file length to the entry's data.
57 | ///
58 | [FieldOffset(68)]
59 | public int Length;
60 |
61 | ///
62 | /// Gets the filename of the entry.
63 | ///
64 | public string FileName => FileNameRaw.ToNullTerminatedString(JapaneseEncoding);
65 | }
66 | ///
67 | /// We don't need to pass the during P/Invoke, so we have this
68 | /// info structure.
69 | ///
70 | [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 8)]
71 | private struct KIFENTRYINFO {
72 | ///
73 | /// The file offset to the entry's data.
74 | ///
75 | public uint Offset;
76 | ///
77 | /// The file length to the entry's data.
78 | ///
79 | public int Length;
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Asmodean/Exkifint.cs:
--------------------------------------------------------------------------------
1 | using GrisaiaExtractor.Extensions;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Runtime.InteropServices;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 |
11 | namespace GrisaiaExtractor.Asmodean {
12 | public static partial class Exkifint {
13 |
14 | private static uint GenTocSeed(string s) {
15 | const uint magic = 0x4C11DB7;
16 | uint seed = uint.MaxValue;
17 |
18 | for (int i = 0; i < s.Length; i++) {
19 | seed ^= ((uint)s[i]) << 24;
20 |
21 | for (int j = 0; j < 8; j++) {
22 | if ((seed & 0x80000000) != 0) {
23 | seed *= 2;
24 | seed ^= magic;
25 | }
26 | else {
27 | seed *= 2;
28 | }
29 | }
30 |
31 | seed = ~seed;
32 | }
33 |
34 | return seed;
35 | }
36 |
37 | private static void UnobfuscateFileName(byte[] s, uint seed) {
38 | const string FWD = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
39 | const string REV = "zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA";
40 |
41 | //MersenneTwister.Seed(seed);
42 | //uint key = MersenneTwister.GenRand();
43 | uint key = MersenneTwister.GenRand(seed);
44 | int shift = (byte) ((key >> 24) + (key >> 16) + (key >> 8) + key);
45 |
46 | for (int i = 0; i < s.Length; i++, shift++) {
47 | byte c = s[i];
48 |
49 | if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
50 | int index = 0;
51 | int index2 = shift;
52 |
53 | while (REV[index2 % 0x34] != c) {
54 | if (REV[(shift + index + 1) % 0x34] == c) {
55 | index += 1;
56 | break;
57 | }
58 |
59 | if (REV[(shift + index + 2) % 0x34] == c) {
60 | index += 2;
61 | break;
62 | }
63 |
64 | if (REV[(shift + index + 3) % 0x34] == c) {
65 | index += 3;
66 | break;
67 | }
68 |
69 | index += 4;
70 | index2 += 4;
71 |
72 | if (index > 0x34) {
73 | break;
74 | }
75 | }
76 |
77 | if (index < 0x34) {
78 | s[i] = (byte) FWD[index];
79 | }
80 | }
81 |
82 | //shift++;
83 | }
84 |
85 | return;
86 | }
87 |
88 | private static void CopyResource(IntPtr h,
89 | string name, string type, out byte[] buffer, out int length)
90 | {
91 | IntPtr r = FindResource(h, name, type);
92 | if (r == IntPtr.Zero)
93 | throw new ResourceException(name, type, "find");
94 |
95 | IntPtr g = LoadResource(h, r);
96 | if (g == IntPtr.Zero)
97 | throw new ResourceException(name, type, "load");
98 |
99 | length = (int) SizeofResource(h, r);
100 | buffer = new byte[(length + 7) & ~7];
101 |
102 | IntPtr lockPtr = LockResource(g);
103 | if (lockPtr == IntPtr.Zero)
104 | throw new ResourceException(name, type, "lock");
105 |
106 | Marshal.Copy(lockPtr, buffer, 0, length);
107 | }
108 |
109 | private static string FindVCode2(string exeFile) {
110 | IntPtr h = LoadLibraryEx(exeFile, IntPtr.Zero,
111 | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
112 | if (h == IntPtr.Zero)
113 | throw new LoadLibraryException(exeFile);
114 |
115 | CopyResource(h, "KEY", "KEY_CODE", out byte[] key, out int keyLength);
116 |
117 | for (int i = 0; i < key.Length; i++)
118 | key[i] ^= 0xCD;
119 |
120 | CopyResource(h, "DATA", "V_CODE2", out byte[] vcode2, out int vcode2Length);
121 |
122 | /*Blowfish bf = new Blowfish();
123 | fixed (byte* key_buff_ptr = keyBuffer)
124 | bf.Set_Key(key_buff_ptr, keyLength);
125 | bf.Decrypt(vcode2Buffer, (vcode2Length + 7) & ~7);
126 | string vcode2 = Encoding.ASCII.GetString(vcode2Buffer, 0, vcode2Length).NullTerminate();*/
127 |
128 | DecryptVCode2(key, keyLength, vcode2, vcode2Length);
129 |
130 | string result = Encoding.ASCII.GetString(vcode2).NullTerminate();
131 |
132 | FreeLibrary(h);
133 |
134 | return result;
135 | }
136 |
137 | public static void Run(string intFile, string exeFile, string outputDir,
138 | ExkifintCallback progress = null)
139 | {
140 | using (Stream stream = File.OpenRead(intFile))
141 | Run(stream, intFile, exeFile, outputDir, progress);
142 | }
143 |
144 | private static void Run(Stream stream, string intFile, string exeFile,
145 | string outputDir, ExkifintCallback progress = null)
146 | {
147 | Stopwatch watch = Stopwatch.StartNew();
148 | DateTime startTime = DateTime.UtcNow;
149 | string gameId = FindVCode2(exeFile);
150 |
151 |
152 | BinaryReader reader = new BinaryReader(stream);
153 | KIFHDR hdr = reader.ReadStruct();
154 |
155 | if (hdr.Signature != "KIF") // It's really a KIF INT file
156 | throw new InvalidFileException(Path.GetFileName(intFile), "INT");
157 |
158 | KIFENTRY[] entries = reader.ReadStructArray(hdr.EntryCount);
159 |
160 | uint tocSeed = GenTocSeed(gameId);
161 | uint fileKey = 0;
162 | bool decrypt = false;
163 |
164 | /*const string fileName = "bom_s.hg3";
165 | const uint offset = 1112718577;
166 | const int length = 1907629000;
167 | const uint fileKey2 = 1457527205;
168 | KIFENTRY kifEntry = new KIFENTRY {
169 | FileNameRaw = new char[64],
170 | Offset = offset,
171 | Length = length,
172 | };
173 | Array.Copy(fileName.ToCharArray(), kifEntry.FileNameRaw, fileName.Length);
174 | DecryptEntry(ref kifEntry, fileKey2);*/
175 |
176 | ExkifintArgs args = new ExkifintArgs();
177 | for (int i = 0; i < hdr.EntryCount; i++) {
178 | if (entries[i].FileName == "__key__.dat") {
179 | if (!decrypt) {
180 | //MersenneTwister.Seed(entries[i].Length);
181 | //fileKey = MersenneTwister.GenRand();
182 | fileKey = MersenneTwister.GenRand(entries[i].Length);
183 | decrypt = true;
184 | }
185 | }
186 | else {
187 | args.FileCount++;
188 | }
189 | }
190 |
191 | DateTime lastRefresh = DateTime.MinValue;
192 | Stopwatch writeTime = new Stopwatch();
193 | TimeSpan refreshTime = TimeSpan.FromMilliseconds(20);
194 | //Stopwatch processTime = new Stopwatch();
195 | for (uint i = 0; i < hdr.EntryCount; i++) {
196 | if (entries[i].FileName == "__key__.dat")
197 | continue;
198 |
199 | if (decrypt) {
200 | UnobfuscateFileName(entries[i].FileNameRaw, tocSeed + i);
201 | //UnobfuscateFileName(ref entries[i].FileName, tocSeed + i);
202 |
203 | entries[i].Offset += i;
204 |
205 | DecryptEntry(ref entries[i].Info, fileKey);
206 |
207 | /*Blowfish bf = new Blowfish();
208 | bf.Set_Key((byte*) &file_key, 4);
209 | byte[] entry_buff = entries[i].bytes;
210 | bf.Decrypt(entry_buff, 8);
211 | entries[i].bytes = entry_buff;*/
212 | }
213 |
214 | args.Ellapsed = DateTime.UtcNow - startTime;
215 | // Round to nearest hundredth
216 | args.Percent = Math.Round((double) args.FileIndex / args.FileCount * 10000) / 100;
217 | args.FileName = entries[i].FileName;
218 | TimeSpan sinceRefresh = DateTime.UtcNow - lastRefresh;
219 | if (sinceRefresh >= refreshTime) {
220 | lastRefresh = DateTime.UtcNow;
221 | writeTime.Start();
222 | progress?.Invoke(args);
223 | writeTime.Stop();
224 | }
225 |
226 | //processTime.Restart();
227 | stream.Position = entries[i].Offset;
228 | byte[] buffer = reader.ReadBytes(entries[i].Length);
229 |
230 | if (decrypt) {
231 | DecryptData(buffer, entries[i].Length, fileKey);
232 | /*Blowfish bf = new Blowfish();
233 | bf.Set_Key((byte*)&file_key, 4);
234 | bf.Decrypt(buff, (len / 8) * 8);*/
235 | }
236 |
237 | string path = Path.Combine(outputDir, entries[i].FileName);
238 | File.WriteAllBytes(path, buffer);
239 | args.FileIndex++;
240 | //processTime.Stop();
241 | //if (processTime.ElapsedMilliseconds >= 500)
242 | // Trace.WriteLine($"Large File: {buffer.Length / 1024:###,###,###,###}KB [{processTime.ElapsedMilliseconds}ms]");
243 | }
244 |
245 | args.Ellapsed = DateTime.UtcNow - startTime;
246 | args.Percent = 100.0;
247 | progress?.Invoke(args);
248 | Trace.WriteLine($"Console Write Time: {writeTime.Elapsed:mm\\:ss\\.fff}");
249 | }
250 | }
251 | }
252 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Asmodean/Hgx2png.PInvoke.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace GrisaiaExtractor.Asmodean {
9 | public static partial class Hgx2png {
10 |
11 | //[DllImport("zlib1.dll", EntryPoint = "uncompress", CallingConvention = CallingConvention.Cdecl)]
12 | //private extern static int Uncompress(byte[] dest, ref int destLen, byte[] source, int sourceLen);
13 |
14 | [DllImport("asmodean.dll", CallingConvention = CallingConvention.Cdecl)]
15 | private extern static void ProcessImage(
16 | byte[] bufferTmp,
17 | int length,
18 | int origLength,
19 | byte[] cmdBufferTmp,
20 | int cmdLength,
21 | int origCmdLength,
22 | //byte[] rgbaBuffer,
23 | out IntPtr pRgbaBuffer,
24 | out int rgbaLength,
25 | int width,
26 | int height,
27 | int depthBytes);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Asmodean/Hgx2png.Structs.cs:
--------------------------------------------------------------------------------
1 | using GrisaiaExtractor.Extensions;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Runtime.InteropServices;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace GrisaiaExtractor.Asmodean {
10 | public static partial class Hgx2png {
11 | [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 20, CharSet = CharSet.Ansi)]
12 | private struct HG3HDR {
13 | [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 4)]
14 | public char[] SignatureRaw; // "HG-3"
15 | public int Unknown1;
16 | public int Unknown2;
17 | public int Unknown3;
18 | public int EntryCount;
19 |
20 | public string Signature => SignatureRaw.ToNullTerminatedString();
21 | }
22 |
23 | [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 16, CharSet = CharSet.Ansi)]
24 | private struct HG3TAG {
25 | [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 8)]
26 | public char[] SignatureRaw;
27 | public int OffsetNext;
28 | public int Length;
29 |
30 | public string Signature => SignatureRaw.ToNullTerminatedString();
31 | }
32 |
33 | [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 40)]
34 | private struct HG3STDINFO {
35 | public int Width;
36 | public int Height;
37 | public int DepthBits;
38 | public int OffsetX;
39 | public int OffsetY;
40 | public int TotalWidth;
41 | public int TotalHeight;
42 | public int Unknown1;
43 | public int Unknown2;
44 | public int Unknown3;
45 | }
46 |
47 | [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 24)]
48 | private struct HG3IMG {
49 | public int Unknown;
50 | public int Height;
51 | public int DataLength;
52 | public int OriginalDataLength;
53 | public int CmdLength;
54 | public int OriginalCmdLength;
55 | };
56 |
57 | [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 8)]
58 | private struct HG3IMGAL {
59 | public int Length;
60 | public int OriginalLength;
61 | };
62 |
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Exceptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace GrisaiaExtractor {
10 | /// An exception thrown when trying to automatically locate the Grisaia
11 | /// executable.
12 | public class GrisaiaExeNotFoundException : Exception {
13 | public GrisaiaExeNotFoundException()
14 | : base("Could not find Grisaia executable file!") { }
15 | }
16 |
17 | /// An exception thrown when an enum is missing it's code attribute.
18 | public class CodeNotFoundException : Exception {
19 | public CodeNotFoundException(FieldInfo field)
20 | : base($"No code attribute found for {field.DeclaringType.Name}.{field.Name}!") { }
21 | }
22 |
23 | /// The result of an .hg3 extract operation.
24 | public enum ExtractHg3Result {
25 | Success,
26 | Hg3ConvertFailed,
27 | BmpConvertFailed,
28 | PngSaveFailed,
29 | BmpDeleteFailed,
30 | Unknown,
31 | }
32 |
33 | /// An exception thrown during an hg3 extraction failure.
34 | public class ExtractHg3Exception : Exception {
35 |
36 | /// The result of the .hg3 extract operation.
37 | public ExtractHg3Result State { get; }
38 | /// The file associated with the error.
39 | public string File { get; }
40 | /// The location in the unrle function where memory would have been leaked.
41 | public int MemoryLeakLocation { get; }
42 |
43 | /// Constructs the exception with a result and associated file.
44 | public ExtractHg3Exception(ExtractHg3Result result, string file)
45 | : base(WriteMessage(result, file)) {
46 | State = result;
47 | File = file;
48 | }
49 |
50 | /// Constructs the exception with a result, associated file, and inner
51 | /// exception.
52 | public ExtractHg3Exception(ExtractHg3Result result, string file,
53 | Exception innerException)
54 | : base(WriteMessage(result, file, innerException), innerException) {
55 | State = result;
56 | File = file;
57 | }
58 |
59 | /// Writes the exception message.
60 | private static string WriteMessage(ExtractHg3Result result, string file,
61 | Exception innerException = null, int memoryLeak = 0) {
62 | string name = Path.GetFileName(file);
63 | string error = innerException?.GetType().Name ?? "Unknown Error";
64 | switch (result) {
65 | case ExtractHg3Result.Hg3ConvertFailed:
66 | return $"{error} occurred while trying to convert '{name}' to a bmp!";
67 | case ExtractHg3Result.BmpConvertFailed:
68 | return $"{error} occurred while trying to convert '{name}' to a png!";
69 | case ExtractHg3Result.PngSaveFailed:
70 | return $"{error} occurred while trying to save '{name}'!";
71 | case ExtractHg3Result.BmpDeleteFailed:
72 | return $"{error} occurred while trying to delete leftover `{name}`!";
73 | case ExtractHg3Result.Unknown:
74 | return $"{error} occurred during an unknown point in the operation with '{name}'!";
75 | default:
76 | return "No error occurred.";
77 | }
78 | }
79 | }
80 |
81 | /// An exception thrown during a failure with a resource.
82 | public class ResourceException : Exception {
83 | /// The name of the resource. May be null.
84 | public string Name { get; }
85 | /// The type of the resource. May be null.
86 | public string Type { get; }
87 |
88 | public ResourceException(string name, string type, string action)
89 | : base($"Failed to {action} resource '{name}:{type}'!")
90 | {
91 | Name = name;
92 | Type = type;
93 | }
94 | }
95 |
96 | /// An exception thrown during a failure to load a library.
97 | public class LoadLibraryException : Exception {
98 | /// The name of the library file.
99 | public string Library { get; }
100 |
101 | public LoadLibraryException(string library)
102 | : base($"Failed to load '{Path.GetFileName(library)}'!")
103 | {
104 | Library = Path.GetFileName(library);
105 | }
106 | }
107 |
108 | /// An exception thrown when the file is not of the valid type.
109 | public class InvalidFileException : Exception {
110 | /// The name of the invalid file.
111 | public string FileName { get; }
112 |
113 | public InvalidFileException(string file, string validType)
114 | : base($"'{Path.GetFileName(file)}' is not a valid {validType} file!")
115 | {
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Extensions/BinaryExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace GrisaiaExtractor.Extensions {
10 | public static class BinaryExtensions {
11 | public static TStruct ReadStruct(this BinaryReader reader)
12 | where TStruct : struct {
13 | byte[] buffer = reader.ReadBytes(Marshal.SizeOf());
14 |
15 | GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
16 |
17 | TStruct result = Marshal.PtrToStructure(
18 | handle.AddrOfPinnedObject());
19 | handle.Free();
20 | return result;
21 | }
22 |
23 | public static TStruct[] ReadStructArray(this BinaryReader reader, int length)
24 | where TStruct : struct {
25 | TStruct[] result = new TStruct[length];
26 | int size = Marshal.SizeOf();
27 | byte[] buffer = reader.ReadBytes(size * length);
28 |
29 | GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
30 | IntPtr ptr = handle.AddrOfPinnedObject();
31 |
32 | for (int i = 0; i < length; i++) {
33 | IntPtr ins = new IntPtr(ptr.ToInt32() + i * size);
34 | result[i] = Marshal.PtrToStructure(ins);
35 | }
36 |
37 | handle.Free();
38 | return result;
39 | }
40 |
41 | public static void WriteStruct(this BinaryWriter writer, TStruct value)
42 | where TStruct : struct {
43 | byte[] buffer = new byte[Marshal.SizeOf()];
44 | GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
45 |
46 | Marshal.StructureToPtr(value, handle.AddrOfPinnedObject(), true);
47 | writer.Write(buffer);
48 | handle.Free();
49 | }
50 |
51 | public static string ReadString(this BinaryReader reader, int length) {
52 | return new string(reader.ReadChars(length));
53 | }
54 |
55 | public static bool IsEndOfStream(this Stream stream) {
56 | return stream.Position >= stream.Length;
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Extensions/StringExtensions.Surround.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace GrisaiaExtractor.Extensions {
8 | public static partial class StringExtensions {
9 |
10 | /// Returns true if the string starts and ends with the
11 | /// parts.
12 | /// The left and right parts of the surrounding.
13 | /// The two parts must not
14 | /// overlap each other.
15 | /// Returns true if the string starts and ends with the
16 | /// parts.
17 | public static bool IsSurrounded(this string str, char openClose,
18 | bool noOverlap = true)
19 | {
20 | return str.IsSurrounded(openClose, openClose, noOverlap);
21 | }
22 |
23 | /// Returns true if the string starts with and
24 | /// ends with .
25 | /// The left part of the surrounding.
26 | /// The right part of the surrounding.
27 | /// The and
28 | /// parts must not overlap each other.
29 | /// Returns true if the string starts with and
30 | /// ends with .
31 | public static bool IsSurrounded(this string str, char open, char close,
32 | bool noOverlap = true)
33 | {
34 | return ((!noOverlap && str.Length >= 1) || str.Length >= 2) &&
35 | str[0] == open && str[str.Length - 1] == close;
36 | }
37 |
38 | /// Returns true if the string starts and ends with the
39 | /// parts.
40 | /// The left and right parts of the surrounding.
41 | /// The two parts must not
42 | /// overlap each other.
43 | /// Returns true if the string starts and ends with the
44 | /// parts.
45 | public static bool IsSurrounded(this string str, string openClose,
46 | bool noOverlap = true)
47 | {
48 | return str.IsSurrounded(openClose, openClose, noOverlap);
49 | }
50 |
51 | /// Returns true if the string starts with and
52 | /// ends with .
53 | /// The left part of the surrounding.
54 | /// The right part of the surrounding.
55 | /// The and
56 | /// parts must not overlap each other.
57 | /// Returns true if the string starts with and
58 | /// ends with .
59 | /// or
60 | /// is null.
61 | public static bool IsSurrounded(this string str, string open, string close,
62 | bool noOverlap = true)
63 | {
64 | return (!noOverlap || str.Length >= open.Length + close.Length) &&
65 | str.StartsWith(open) && str.EndsWith(close);
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Extensions/StringExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace GrisaiaExtractor.Extensions {
8 | public static partial class StringExtensions {
9 |
10 | /// Returns true if the strings are equal, allows for ignore case.
11 | public static bool Equals2(this string a, string b, bool ignoreCase) {
12 | return a.Equals(b, ignoreCase ?
13 | StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
14 | }
15 |
16 | /*public static string Surround(this string str, string open, string close) {
17 |
18 | }*/
19 |
20 | /// Removes surrounding quotes from a string.
21 | public static string RemoveQuotes(this string str) {
22 | if (str.StartsWith("\"") && str.EndsWith("\"")) {
23 | if (str.Length >= 2)
24 | return str.Substring(1, str.Length - 2);
25 | return "";
26 | }
27 | return str;
28 | }
29 |
30 | public static string ReplaceAt(this string str, int index, string value) {
31 | return str.Substring(0, index) + value + str.Substring(index + value.Length);
32 | }
33 |
34 | public static string ReplaceAt(this string str, int index, char c) {
35 | return str.Substring(0, index) + c + str.Substring(index + 1);
36 | }
37 |
38 | public static string NullTerminate(this string str) {
39 | int index = str.IndexOf('\0');
40 | return (index != -1 ? str.Substring(0, index) : str);
41 | }
42 |
43 | public static int IndexOfNullTerminator(this string str) {
44 | int index = str.IndexOf('\0');
45 | return (index != -1 ? index : str.Length);
46 | }
47 |
48 | public static int IndexOfNullTerminator(this char[] chars) {
49 | for (int i = 0; i < chars.Length; i++) {
50 | if (chars[i] == '\0')
51 | return i;
52 | }
53 | return chars.Length;
54 | }
55 |
56 | public static int IndexOfNullTerminator(this byte[] chars) {
57 | for (int i = 0; i < chars.Length; i++) {
58 | if (chars[i] == '\0')
59 | return i;
60 | }
61 | return chars.Length;
62 | }
63 |
64 | public static string ToNullTerminatedString(this byte[] chars) {
65 | return Encoding.ASCII.GetString(chars, 0, chars.IndexOfNullTerminator());
66 | }
67 | public static string ToNullTerminatedString(this byte[] chars, Encoding encoding) {
68 | return encoding.GetString(chars, 0, chars.IndexOfNullTerminator());
69 | }
70 |
71 | public static string ToNullTerminatedString(this char[] chars) {
72 | return new string(chars, 0, chars.IndexOfNullTerminator());
73 | }
74 |
75 | public static string GetNullTerminated(this Encoding encoding, byte[] bytes) {
76 | return encoding.GetString(bytes).NullTerminate();
77 | }
78 |
79 | /// Designed for use with ASCII encoding to easily get a single char
80 | /// from a single byte.
81 | public static char GetChar(this Encoding encoding, byte singleByte) {
82 | return encoding.GetChars(new byte[] { singleByte })[0];
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/GrisaiaExtractor.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {B9E8EA56-874B-4CEB-A703-DCA3A307A4D3}
8 | Library
9 | Properties
10 | GrisaiaExtractor
11 | GrisaiaExtractor
12 | v4.6.1
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 | true
24 | x86
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 | true
34 | x86
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | zlib1.dll
79 | PreserveNewest
80 |
81 |
82 |
83 |
84 | {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}
85 | asmodean
86 | false
87 | Content
88 | PreserveNewest
89 | True
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Identifying/Backgrounds.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Text.RegularExpressions;
8 | using System.Threading.Tasks;
9 |
10 | namespace GrisaiaExtractor.Identifying {
11 | [Flags]
12 | public enum BackgroundFlags {
13 |
14 | [Name("Default"), Code("")]
15 | Default = 0,
16 |
17 | // Special
18 | [Name("Alternate"), Code("t")]
19 | [Description("Some alternates are no different from default")]
20 | Alternate = (1 << 0),
21 |
22 | // Coloration
23 | [Name("Dark"), Code("d")]
24 | Dark = (1 << 1),
25 | [Name("Evening"), Code("e")]
26 | Evening = (1 << 2),
27 | [Name("Night"), Code("n")]
28 | [Description("Dark but with lights on")]
29 | Night = (1 << 3),
30 | [Name("Sepia"), Code("s")]
31 | Sepia = (1 << 4),
32 |
33 | // Weather
34 | [Name("Cloudy"), Code("c")]
35 | Cloudy = (1 << 5),
36 | [Name("Rain"), Code("r")]
37 | Rain = (1 << 6),
38 | [Name("Heavy Rain"), Code("r2")]
39 | HeavyRain = (1 << 7),
40 |
41 | // Meta
42 | [Name("Large"), Code("L")]
43 | Large = (1 << 8),
44 | }
45 |
46 | public enum BackgroundScale {
47 | [Name("Full"), Code("")]
48 | Full = 0,
49 |
50 | [Name("Large"), Code("l")]
51 | Large,
52 | [Name("Medium"), Code("m")]
53 | Medium,
54 | }
55 |
56 | [Flags]
57 | public enum BackgroundOffset {
58 | [Name("No Offset"), Code("")]
59 | NoOffset = 0,
60 |
61 | [Name("Center"), Code("c")]
62 | Center = (1 << 0),
63 |
64 | [Name("Left"), Code("l")]
65 | Left = (1 << 1),
66 |
67 | [Name("Right"), Code("r")]
68 | Right = (1 << 2),
69 |
70 | [Name("Up"), Code("u")]
71 | Up = (1 << 3),
72 |
73 | [Name("Down"), Code("d")]
74 | Down = (1 << 4),
75 | }
76 |
77 | public class BackgroundI : ImageIdentification {
78 |
79 | public static readonly Regex FormatRegex =
80 | new Regex(@"^(bgi_|bgmitei)(?'name'.*)");
81 |
82 | public string Name { get; private set; }
83 |
84 | public static void Register() {
85 | ImageIdentifier.RegisterIdentifier(
86 | "BackgroundI", FormatRegex, false);
87 | }
88 |
89 | public BackgroundI() { }
90 |
91 | protected override void Setup(Match match) {
92 | Name = match.Groups["name"].Value;
93 | }
94 |
95 | public override string OutputDirectory => "Backgrounds";
96 | }
97 |
98 | public class MiscBackground : ImageIdentification {
99 |
100 | public static readonly string[] Prefixes = {
101 | "bg_etc",
102 | "bgdave",
103 | "bg", // See: Grisaia no Meikyuu 'bg62t.png'
104 | "b‚‡", // See: Legacy before Japanese encoding 'b‚‡62t.png'
105 | };
106 |
107 | public static readonly Regex FormatRegex = PrefixesToRegex(Prefixes);
108 |
109 | public static void Register() {
110 | ImageIdentifier.RegisterIdentifier(
111 | "Misc Backgrounds", FormatRegex, false);
112 | }
113 |
114 | public override string OutputDirectory => "Backgrounds";
115 |
116 | }
117 |
118 | public abstract class BackgroundBase : ImageIdentification {
119 |
120 | /// The index ID of the background.
121 | public int Index { get; private set; }
122 | /// The flags describing the background.
123 | public BackgroundFlags Flags { get; private set; }
124 | /// The unidentified background flags.
125 | public string UnknownFlags { get; private set; }
126 |
127 | public BackgroundBase() { }
128 |
129 | /// Sets up the background base identification information.
130 | protected override void Setup(Match match) {
131 | Index = int.Parse(match.Groups["index"].Value);
132 |
133 | Flags = AttributeHelper.ParseCode(
134 | match.Groups["flags"].Value, out string unknownFlags);
135 | UnknownFlags = unknownFlags;
136 | }
137 | }
138 |
139 | public class Background : BackgroundBase {
140 | public static readonly Regex FormatRegex =
141 | new Regex(@"^bg[ert]?(?'index'\d\d)(?'flags'[a-zA-Z0-9]*)(?:_(?'scale'[a-zA-Z0-9])(?'offset'[a-zA-Z0-9])?)?(?'offsetIndex'\d\d)?(?'leftover'.*)?$");
142 |
143 | public static void Register() {
144 | ImageIdentifier.RegisterIdentifier(
145 | "Background", FormatRegex, false);
146 | }
147 |
148 | public BackgroundScale Scale { get; private set; }
149 | public string UnknownScale { get; private set; }
150 | public BackgroundOffset Offset { get; private set; }
151 | public string UnknownOffset { get; private set; }
152 | public List SpecialAnimations { get; }
153 |
154 | public Background() { }
155 |
156 | /// Sets up the background identification information.
157 | protected override void Setup(Match match) {
158 | Scale = AttributeHelper.ParseCode(
159 | match.Groups["scale"].Value, out string unknownScale);
160 | UnknownScale = unknownScale;
161 |
162 | Offset = AttributeHelper.ParseCode(
163 | match.Groups["offset"].Value, out string unknownOffset);
164 | UnknownOffset = unknownOffset;
165 | }
166 |
167 | public override string OutputDirectory => "Backgrounds";
168 | public override IEnumerable Tags {
169 | get {
170 | List tags = new List();
171 | tags.Add(Index.ToString());
172 | tags.AddRange(AttributeHelper.GetNames(Flags));
173 | tags.AddRange(AttributeHelper.GetNames(Scale));
174 | tags.AddRange(AttributeHelper.GetNames(Offset));
175 | return tags;
176 | }
177 | }
178 | }
179 |
180 | public class BackgroundSpecialAnimation : BackgroundBase {
181 | public static readonly Regex FormatRegex =
182 | new Regex(@"^(?'parent'bg(e|r)?(?'index'\d\d)(?'flags'[a-zA-Z0-9]*))_(?'name'[a-zA-Z0-9]+)$");
183 |
184 | public static void Register() {
185 | ImageIdentifier.RegisterIdentifier(
186 | "Background Special Animation", FormatRegex, true,
187 | PostAdd);
188 | }
189 |
190 | public string AnimationName { get; private set; }
191 | public string Parent { get; private set; }
192 |
193 | public BackgroundSpecialAnimation() { }
194 |
195 | /// Sets up the background identification information.
196 | protected override void Setup(Match match) {
197 | AnimationName = match.Groups["name"].Value;
198 | Parent = match.Groups["parent"].Value;
199 | }
200 |
201 | public static void PostAdd(ImageIdentifier identifier, ImageIdentification selfBase) {
202 | BackgroundSpecialAnimation self = (BackgroundSpecialAnimation) selfBase;
203 | if (identifier.TryGetImage(self.AnimationName, out var image)) {
204 | if (image is Background bg) {
205 | bg.SpecialAnimations.Add(self);
206 | }
207 | }
208 | }
209 | public override string OutputDirectory => "Backgrounds";
210 | public override IEnumerable Tags {
211 | get {
212 | List tags = new List();
213 | tags.Add(Index.ToString());
214 | tags.AddRange(AttributeHelper.GetNames(Flags));
215 | tags.Add(AnimationName);
216 | return tags;
217 | }
218 | }
219 | }
220 | }
221 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Identifying/Character.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Text.RegularExpressions;
7 | using System.Threading.Tasks;
8 |
9 | namespace GrisaiaExtractor.Identifying {
10 |
11 | public enum CharacterType {
12 | [Name("CG"), Code("")]
13 | [Group("CG")]
14 | CG = 0,
15 |
16 | [Name("Chibi"), Code("sd", "_sd", "__sd", IgnoreCase = true)]
17 | [Group("Chibi")]
18 | Chibi,
19 |
20 | [Name("Sprite"), Code("T")]
21 | [Group("Sprites")]
22 | Sprite,
23 | }
24 |
25 | /*public enum CGScale {
26 | [Name("Normal"), Code("")]
27 | Normal = 0,
28 |
29 | [Name("Thumb")]
30 | }*/
31 |
32 |
33 |
34 | public class Character : ImageIdentification {
35 |
36 | public static readonly Dictionary Characters =
37 | new Dictionary()
38 | {
39 | { "hir", "Amane Classmates/Hiroka Tamaki" },
40 | { "ibu", "Amane Classmates/Haruna Ibuki" },
41 | { "kan", "Amane Classmates/Saaya Kaneda" },
42 | { "koi", "Amane Classmates/Ritsu Koide" },
43 | { "kom", "Amane Classmates/Megumi Komori" },
44 | { "och", "Amane Classmates/Yoshihiko Ochi" },
45 | { "sak", "Amane Classmates/Chiaki Sakashita" },
46 | { "skm", "Amane Classmates/Minori Sakuma" },
47 | { "skr", "Amane Classmates/Mifuyu Sakurai" },
48 | { "tas", "Amane Classmates/Keiji Sakashita" },
49 | { "sas", "Sachi Komine/Battle" },
50 | { "mib", "Michiru Matsushima/Black Hair" },
51 | { "ama", "Amane Suou" },
52 | { "mak", "Makina Irisu" },
53 | { "mic", "Michiru Matsushima" },
54 | { "sac", "Sachi Komine" },
55 | { "yum", "Yumiko Sakaki" },
56 | { "kar", "Kazuki Kazami" },
57 | { "kap", "Kazuki Kazami" },
58 | { "kaz", "Kazuki Kazami" },
59 | { "chi", "Chizuru Tachibana" },
60 | { "jb", "JB" },
61 | { "jbs", "JB" },
62 | { "asa", "Asako Kusakabe" },
63 | { "yuj", "Yuuji Kazami" },
64 | { "kia", "Chiara Farrell" },
65 | { "sam", "Sachi's Mother" },
66 | { "saf", "Sachi's Father" },
67 | { "yuf", "Michiaki Sakaki (Yumiko's Father)" },
68 | { "mif", "Michiru's Friend" },
69 | { "kiy", "Kiyoka Irisu (Makina's Mother)" },
70 | { "amm", "Amane Suou (Middle School)" },
71 | { "amp", "Amane Suou (Middle School)" },
72 | { "nya", "Nyanmel" },
73 | { "tan", "Thanatochu" },
74 | { "kam", "Kami-sama" },
75 | { "yjf", "Ryouji Kazami (Yuuji's Father)" },
76 | { "yjm", "Satoko Kazami (Yuuji's Mother)" },
77 | { "dan", "Daniel Bone" },
78 | { "edi", "Edward Walker" },
79 | { "gar", "Agnes Garrett" },
80 | { "jei", "Justin Mikemeyer" },
81 | { "joh", "John (Yuuji's dog)" },
82 | { "osr", "Heath Oslo" },
83 | { "osl", "Heath Oslo" },
84 | { "mar", "Marin" },
85 | { "mir", "Milliela Stanfield" },
86 | { "rob", "Robert Wallson" },
87 | { "dave", "Professor Dave" },
88 | { "dav", "Professor Dave" },
89 | //{ "ev", "Everyone" },
90 | { "oth", "Other" },
91 | //{ "op", "Other" },
92 |
93 | // Zankou
94 | { "iza", "Isabella Fitzgerald" },
95 | { "mro", "Marion Garland" },
96 | { "nob", "Ramon Noboa" },
97 | };
98 |
99 | public static readonly Dictionary SpriteOnlyCharacters =
100 | new Dictionary()
101 | {
102 | { "meg", "Goddess" }, // TODO: What is her name?
103 | { "cha", "Chaos" },
104 | { "gho", "Ghost" },
105 | { "str", "Stranger" },
106 | { "nan", "Nanano Suou" },
107 | { "ren", "Renge Yamabuki" },
108 | { "mag", "Other" },
109 | };
110 |
111 | public static readonly Regex FormatRegex =
112 | new Regex(
113 | $"^((?'type'T|_?_?sd)?_?(?'name'{string.Join("|", Characters.Keys.ToArray())})|" +
114 | $"^(?'type'T)_?(?'name'{string.Join("|", SpriteOnlyCharacters.Keys.ToArray())}))",
115 | RegexOptions.IgnoreCase);
116 |
117 | public static void Register() {
118 | ImageIdentifier.RegisterIdentifier(
119 | "Character", FormatRegex, false);
120 | }
121 |
122 | public string Code { get; private set; }
123 | public CharacterType Type { get; private set; }
124 | public string Name { get; private set; }
125 | public string Category { get; private set; }
126 | public string SubCategory { get; private set; }
127 |
128 | static Character() {
129 | // SpriteOnlyCharacters is only needed for regex initialization.
130 | // So let's dump all SpriteOnlyCharacters into Characters.
131 | foreach (var pair in SpriteOnlyCharacters) {
132 | Characters.Add(pair.Key, pair.Value);
133 | }
134 | }
135 |
136 | public Character() { }
137 |
138 | protected override void Setup(Match match) {
139 | Code = match.Groups["name"].Value.ToLower();
140 | Name = Characters[Code];
141 | Type = AttributeHelper.ParseCode(match.Groups["type"].Value, out _);
142 | }
143 |
144 | public override string OutputDirectory {
145 | get {
146 | string path = "Characters";
147 | if (!string.IsNullOrWhiteSpace(Category))
148 | path = Path.Combine(path, Category);
149 | path = Path.Combine(path, Name);
150 | if (!string.IsNullOrWhiteSpace(SubCategory))
151 | path = Path.Combine(path, SubCategory);
152 | return Path.Combine(path, AttributeHelper.GetGroup(Type));
153 | }
154 | }
155 |
156 | public override IEnumerable Tags {
157 | get {
158 | List tags = new List();
159 | tags.Add(Type.ToString());
160 | tags.Add(Name);
161 | tags.Add(Category);
162 | tags.Add(SubCategory);
163 | return tags;
164 | }
165 | }
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Identifying/Effect.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.RegularExpressions;
6 | using System.Threading.Tasks;
7 |
8 | namespace GrisaiaExtractor.Identifying {
9 | public class Effect : ImageIdentification {
10 | public static readonly string[] Prefixes = {
11 | "anm_",
12 | "bom_",
13 | "glass_anim",
14 | "manpu_",
15 | "mask_",
16 | "parts_",
17 | "slash",
18 | "yuge",
19 | };
20 |
21 | public static readonly Regex FormatRegex = PrefixesToRegex(Prefixes);
22 |
23 | public static void Register() {
24 | ImageIdentifier.RegisterIdentifier(
25 | "Effect", FormatRegex, false);
26 | }
27 |
28 | public Effect() { }
29 |
30 | public override string OutputDirectory => "Effects";
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Identifying/ImageIdentification.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Text.RegularExpressions;
7 | using System.Threading.Tasks;
8 |
9 | namespace GrisaiaExtractor.Identifying {
10 | /// The base class for an image identification.
11 | public abstract class ImageIdentification {
12 |
13 | // General:
14 | /// The base filename with no extension.
15 | public string FileName { get; private set; }
16 |
17 | // Animation:
18 | /// True if a filename exists without the animation postfix.
19 | public bool HasBase { get; private set; }
20 | /// Gets the first A frame in the animation. -1 if not an animation.
21 | public int FirstFrameA { get; private set; } = -1;
22 | /// Gets the first B frame in the animation. -1 if not an animation.
23 | public int FirstFrameB { get; private set; } = -1;
24 | /// Gets the last A frame in the animation. -1 if not an animation.
25 | public int LastFrameA { get; private set; } = -1;
26 | /// Gets the last B frame in the animation. -1 if not an animation.
27 | public int LastFrameB { get; private set; } = -1;
28 |
29 |
30 | //-----------------------------------------------------------------------------
31 | // Constructors
32 | //-----------------------------------------------------------------------------
33 |
34 | /// Constructs the base image identification.
35 | public ImageIdentification() { }
36 |
37 | /// Initializes the image identification from the filepath.
38 | public void Initialize(string path, Match match, bool findAnimaion) {
39 | FileName = AnimationHelper.GetBaseFileName(path);
40 |
41 | if (findAnimaion) {
42 | string[] fileNames = AnimationHelper.GetFileNames(path);
43 | InitializeFileNames(fileNames);
44 | }
45 | Setup(match);
46 | }
47 |
48 | /// Initializes the image identification from the filepath.
49 | public void Initialize(string[] paths, Match match) {
50 | FileName = AnimationHelper.GetBaseFileName(paths[0]);
51 |
52 | string[] fileNames = paths.Select(p =>
53 | Path.GetFileNameWithoutExtension(p)).ToArray();
54 | InitializeFileNames(fileNames);
55 | Setup(match);
56 | }
57 |
58 | /// Sets up the basic identification information.
59 | private void InitializeFileNames(string[] fileNames) {
60 | // Gather information about the animation:
61 | // Check the first two files for animations
62 | int indexA, indexB;
63 | for (int i = 0; i < 2 && i + 1 < fileNames.Length; i++) {
64 | if (AnimationHelper.IsAnimation(fileNames[i], out indexA, out indexB)) {
65 | FirstFrameA = indexA;
66 | FirstFrameB = indexB;
67 | // Get the last animation frames
68 | AnimationHelper.IsAnimation(fileNames[fileNames.Length - 1], out indexA, out indexB);
69 | LastFrameA = indexA;
70 | LastFrameB = indexB;
71 | break;
72 | }
73 | else {
74 | // This should only ever be reached when i == 0
75 | HasBase = true;
76 | }
77 | }
78 | }
79 |
80 | /// Sets up the extended image identification.
81 | protected virtual void Setup(Match match) { }
82 |
83 |
84 | //-----------------------------------------------------------------------------
85 | // General
86 | //-----------------------------------------------------------------------------
87 |
88 | /// Creates a string representation of the identification as a
89 | /// filename and tags.
90 | public override string ToString() {
91 | string name = FileName;
92 | if (IsAnimated)
93 | return name += $" (+{TotalFrameCount})";
94 | name += $" {string.Join(",", Tags.ToArray())}";
95 | return name;
96 | }
97 |
98 | /// A quick method to create regex from a list of prefixes.
99 | protected static Regex PrefixesToRegex(string[] prefixes)
100 | => new Regex($"^({string.Join("|", prefixes)})");
101 |
102 |
103 | //-----------------------------------------------------------------------------
104 | // File Paths
105 | //-----------------------------------------------------------------------------
106 |
107 | /// Gets the base .png filepath.
108 | public string GetPng(string dir) {
109 | return Path.Combine(dir, OutputDirectory, FileName + ".png");
110 | }
111 |
112 | /// Gets the animation .png filepath.
113 | public string GetPng(string dir, int indexA, int indexB) {
114 | return AnimationHelper.GetFileNameQuick(Path.Combine(dir, OutputDirectory), FileName, indexA, indexB, ".png");
115 | }
116 |
117 | /// Gets all .png filepaths for the image.
118 | public IEnumerable GetPngs(string dir) {
119 | if (HasBase)
120 | yield return GetPng(dir);
121 | for (int a = FirstFrameA; a <= LastFrameA; a++) {
122 | for (int b = FirstFrameB; b <= LastFrameB; b++) {
123 | yield return GetPng(dir, a, b);
124 | }
125 | }
126 | }
127 |
128 | /// Gets the .bmp filepath.
129 | public string GetBmp(string dir) {
130 | return Path.Combine(dir, FileName + ".bmp");
131 | }
132 |
133 | /// Gets the animation .bmp filepath.
134 | public string GetBmp(string dir, int indexA, int indexB) {
135 | return AnimationHelper.GetFileNameQuick(dir, FileName, indexA, indexB, ".bmp");
136 | }
137 |
138 | /// Gets all .bmp filepaths for the image.
139 | public IEnumerable GetBmps(string dir) {
140 | if (HasBase)
141 | yield return GetBmp(dir);
142 | for (int a = FirstFrameA; a <= LastFrameA; a++) {
143 | for (int b = FirstFrameB; b <= LastFrameB; b++) {
144 | yield return GetBmp(dir, a, b);
145 | }
146 | }
147 | }
148 |
149 | /// Gets the .hg3 filepath.
150 | public string GetHg3(string dir) {
151 | return Path.Combine(dir, FileName + ".hg3");
152 | }
153 |
154 |
155 | //-----------------------------------------------------------------------------
156 | // Properties
157 | //-----------------------------------------------------------------------------
158 |
159 | /// Returns true if the image has animation frames.
160 | public bool IsAnimated {
161 | get { return FirstFrameA != -1; }
162 | }
163 |
164 | /// Gets the number of A frames in the animation.
165 | public int FrameCountA {
166 | get { return (FirstFrameA == -1 ? 0 : LastFrameA - FirstFrameA + 1); }
167 | }
168 |
169 | /// Gets the number of B frames in the animation.
170 | public int FrameCountB {
171 | get { return (FirstFrameB == -1 ? 0 : LastFrameB - FirstFrameB + 1); }
172 | }
173 |
174 | /// Gets the total number of frames in the animation.
175 | public int TotalFrameCount {
176 | get { return FrameCountA * FrameCountB; }
177 | }
178 |
179 | /// Gets the output directory for the image.
180 | public abstract string OutputDirectory { get; }
181 |
182 | /// Gets the searchable tags for the image.
183 | public virtual IEnumerable Tags {
184 | get { return Enumerable.Empty(); }
185 | }
186 |
187 | /// Gets if the image should be expanded to its full size when
188 | /// extracting.
189 | public virtual bool ExpandImage => true;
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Identifying/ImageIdentifier.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Text.RegularExpressions;
7 | using System.Threading.Tasks;
8 |
9 | namespace GrisaiaExtractor.Identifying {
10 |
11 | /// A handler for matching and creating an identification.
12 | public class ImageIdentifierType {
13 | // Information:
14 | /// The type created from this identifier.
15 | public Type Type { get; }
16 | /// The name of the type created from this identifier.
17 | public string Name { get; }
18 |
19 | // Matching:
20 | /// The regex used to match with this type.
21 | public Regex Regex { get; }
22 | /// True if this type requires an animation.
23 | public bool RequiresAnimation { get; }
24 |
25 | // Functions:
26 | /// Called after the identification has been created.
27 | public Action PostAdd { get; }
28 |
29 | /// Constructs the identifier type.
30 | public ImageIdentifierType(Type type, string name, Regex regex,
31 | bool requiresAnimation,
32 | Action postAdd = null)
33 | {
34 | Type = type;
35 | Name = name;
36 | Regex = regex;
37 | RequiresAnimation = requiresAnimation;
38 | PostAdd = postAdd;
39 | }
40 |
41 | /// Creates an empty image identification from the type.
42 | public ImageIdentification Create() {
43 | return (ImageIdentification) Activator.CreateInstance(Type);
44 | }
45 | }
46 |
47 | /// Identifies .
48 | public class ImageIdentifier {
49 |
50 | private static List identifiers =
51 | new List();
52 |
53 | static ImageIdentifier() {
54 | Background.Register();
55 | MiscBackground.Register();
56 | BackgroundI.Register();
57 | //BackgroundSpecialAnimation.Register();
58 | Effect.Register();
59 | Logo.Register();
60 | StoryCGChibi.Register();
61 | Character.Register();
62 | MiscChibi.Register();
63 | UserInterface.Register();
64 | TmbIcon.Register();
65 | Transition.Register();
66 | Item.Register();
67 | }
68 |
69 | public static void RegisterIdentifier(
70 | string name, Regex regex, bool requiresAnimation,
71 | Action postAdd = null)
72 | where IType : ImageIdentification
73 | {
74 | identifiers.Add(new ImageIdentifierType(
75 | typeof(IType), name, regex, requiresAnimation, postAdd));
76 | }
77 |
78 |
79 | private Dictionary images;
80 |
81 | public ImageIdentifier() {
82 | images = new Dictionary();
83 | }
84 |
85 | public void AddImage(ImageIdentification image) {
86 | images.Add(image.FileName, image);
87 | }
88 |
89 | public bool TryGetImage(string name, out ImageIdentification result) {
90 | return images.TryGetValue(name, out result);
91 | }
92 |
93 | public ImageIdentifierType GetIdentifier(string path, out Match match) {
94 | string name = AnimationHelper.GetBaseFileName(path, out bool isAnimation);
95 | foreach (ImageIdentifierType identifier in identifiers) {
96 | if (identifier.RequiresAnimation && !isAnimation)
97 | continue;
98 | match = identifier.Regex.Match(name);
99 | if (match.Success)
100 | return identifier;
101 | }
102 | match = null;
103 | return null;
104 | }
105 |
106 | public ImageIdentification PreIdentifyImage(string path) {
107 | ImageIdentifierType identifier = GetIdentifier(path, out Match match);
108 | ImageIdentification image = identifier?.Create() ?? new Unidentified();
109 | image.Initialize(path, match, false);
110 | //AddImage(image);
111 | //identifier?.PostAdd?.Invoke(this, image);
112 | return image;
113 | }
114 |
115 | public ImageIdentification IdentifyImage(string[] paths) {
116 | ImageIdentifierType identifier = GetIdentifier(paths[0], out Match match);
117 | ImageIdentification image = identifier?.Create() ?? new Unidentified();
118 | image.Initialize(paths, match);
119 | AddImage(image);
120 | identifier?.PostAdd?.Invoke(this, image);
121 | return image;
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Identifying/Item.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.RegularExpressions;
6 | using System.Threading.Tasks;
7 |
8 | namespace GrisaiaExtractor.Identifying {
9 | public class Item : ImageIdentification {
10 |
11 | public static readonly Regex FormatRegex = new Regex(@"^item");
12 |
13 | public static void Register() {
14 | ImageIdentifier.RegisterIdentifier- ("Item", FormatRegex, false);
15 | }
16 |
17 | public override string OutputDirectory => "Items";
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Identifying/Logo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.RegularExpressions;
6 | using System.Threading.Tasks;
7 |
8 | namespace GrisaiaExtractor.Identifying {
9 | public class Logo : ImageIdentification {
10 |
11 | public static readonly string[] Prefixes = {
12 | "10thlogo",
13 | "fwlogo",
14 | "install",
15 | "logo",
16 | "sddava_logo",
17 | "sekai_logo",
18 | "sys_title",
19 | "title",
20 | };
21 |
22 | public static readonly Regex FormatRegex = PrefixesToRegex(Prefixes);
23 |
24 |
25 | public static void Register() {
26 | ImageIdentifier.RegisterIdentifier("Logo", FormatRegex, false);
27 | }
28 |
29 | public Logo() {
30 |
31 | }
32 |
33 | public override string OutputDirectory => "Logos";
34 | public override bool ExpandImage => false;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Identifying/MiscChibi.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Text.RegularExpressions;
7 | using System.Threading.Tasks;
8 |
9 | namespace GrisaiaExtractor.Identifying {
10 |
11 | public class MiscChibi : ImageIdentification {
12 |
13 | public static readonly Regex FormatRegex =
14 | new Regex(@"^_?_?sd\d\d\d", RegexOptions.IgnoreCase);
15 |
16 |
17 | public static void Register() {
18 | ImageIdentifier.RegisterIdentifier(
19 | "Misc Chibi", FormatRegex, false);
20 | }
21 |
22 | public override string OutputDirectory => Path.Combine("Story", "Chibi");
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Identifying/StoryCGChibi.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Text.RegularExpressions;
7 | using System.Threading.Tasks;
8 |
9 | namespace GrisaiaExtractor.Identifying {
10 | public class StoryCGChibi : ImageIdentification {
11 |
12 | public static readonly Dictionary Categories =
13 | new Dictionary()
14 | {
15 | { "op", "Opening" },
16 | { "pro", "Prologue" },
17 | { "bla", "Main Story" },
18 | { "aft", "After Story" },
19 | { "mag", "Story" }, // Idol Mahou Shoujo
20 | { "ev", "Story" }, // Yuukan
21 | { "evt", "Story" }, // Zankou
22 | };
23 |
24 | /*public static readonly string[] RegexNames = {
25 | "pro(?!title)",
26 | };
27 |
28 | public const string NameRegex
29 |
30 | private static string[] GetNames() {
31 | string[] names = new string[Categories.Count];
32 | int i = 0;
33 | foreach (string name in Categories.Keys) {
34 | names[i] = name + @"";
35 | foreach (string nameRegex in RegexNames) {
36 | if (new Regex(nameRegex).IsMatch(name)) {
37 | names[i] = nameRegex;
38 | break;
39 | }
40 | }
41 | i++;
42 | }
43 | return names;
44 | }*/
45 |
46 |
47 | public static readonly Regex FormatRegex = new Regex(
48 | $"^(?'chibi'_?_?sd)?(?'category'{string.Join("|", Categories.Keys.ToArray())})(?:[^a-zA-Z]|$)", RegexOptions.IgnoreCase);
49 |
50 | public static void Register() {
51 | ImageIdentifier.RegisterIdentifier(
52 | "CG/Chibi", FormatRegex, false);
53 | }
54 |
55 |
56 | public StoryCGChibi() {
57 |
58 | }
59 |
60 | protected override void Setup(Match match) {
61 | if (string.IsNullOrEmpty(match.Groups["chibi"].Value))
62 | Type = "CG";
63 | else
64 | Type = "Chibi";
65 | Code = match.Groups["category"].Value.ToLower();
66 | Category = Categories[Code];
67 | }
68 |
69 | public string Type { get; private set; }
70 |
71 | public string Code { get; private set; }
72 | public string Category { get; private set; }
73 |
74 |
75 |
76 | public override string OutputDirectory => Path.Combine(Category, Type);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Identifying/TmbIcon.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.RegularExpressions;
6 | using System.Threading.Tasks;
7 |
8 | namespace GrisaiaExtractor.Identifying {
9 | public class TmbIcon : ImageIdentification {
10 |
11 | public static readonly Regex FormatRegex = new Regex(@"^tmbicon");
12 |
13 | public static void Register() {
14 | ImageIdentifier.RegisterIdentifier("Icon", FormatRegex, false);
15 | }
16 |
17 | public TmbIcon() { }
18 |
19 | protected override void Setup(Match match) {
20 |
21 | }
22 |
23 | public override string OutputDirectory => "Icons";
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Identifying/Transition.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.RegularExpressions;
6 | using System.Threading.Tasks;
7 |
8 | namespace GrisaiaExtractor.Identifying {
9 | public class Transition : ImageIdentification {
10 |
11 | public static readonly Regex FormatRegex =
12 | new Regex(@"^wipe(?'index'\d\d)(?'subtype'[a-z])?");
13 |
14 | public int Index { get; private set; }
15 | public string Subtype { get; private set; }
16 |
17 | public static void Register() {
18 | ImageIdentifier.RegisterIdentifier("Transition", FormatRegex, false);
19 | }
20 |
21 | public Transition() { }
22 |
23 | protected override void Setup(Match match) {
24 | Index = int.Parse(match.Groups["index"].Value);
25 | Subtype = match.Groups["subtype"].Value;
26 | }
27 |
28 | public override string OutputDirectory => "Transitions";
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Identifying/Unidentified.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace GrisaiaExtractor.Identifying {
8 | public class Unidentified : ImageIdentification {
9 |
10 | public Unidentified() {
11 |
12 | }
13 |
14 | public override string OutputDirectory => "Unidentified";
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Identifying/UserInterface.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.RegularExpressions;
6 | using System.Threading.Tasks;
7 |
8 | namespace GrisaiaExtractor.Identifying {
9 | public class UserInterface : ImageIdentification {
10 | private static readonly string[] Prefixes = {
11 | "_conf_txt",
12 | "activate",
13 | "award",
14 | "caution",
15 | "bgm",
16 | "cap_mic_change",
17 | "cg_",
18 | "cgmode",
19 | "click",
20 | "cm001",
21 | "conf",
22 | "cursor",
23 | "dave_select",
24 | "delt_plane",
25 | "delta_plane",
26 | "dl_",
27 | "eyecatch",
28 | "guripe",
29 | "hamon",
30 | "half_plane",
31 | "hist",
32 | "jumpmes",
33 | "moviemode",
34 | "novel_click",
35 | "nowloading",
36 | "progress",
37 | "s_cnf_",
38 | "scenemode",
39 | "scenesel",
40 | "scnhlp",
41 | "scnsel",
42 | "secret",
43 | "seek",
44 | "sel",
45 | "scenarioselect",
46 | "shortcut",
47 | "sl_",
48 | "slide_",
49 | "ss_",
50 | @"str\d_plane",
51 | "sys_(?!title)", // sys_title -> Logo
52 | "userfont",
53 | "wpthm",
54 | };
55 |
56 | public static readonly Regex FormatRegex = PrefixesToRegex(Prefixes);
57 |
58 | public static void Register() {
59 | ImageIdentifier.RegisterIdentifier(
60 | "User Interface", FormatRegex, false);
61 | }
62 |
63 | public UserInterface() { }
64 |
65 | public override string OutputDirectory => "User Interface";
66 | public override bool ExpandImage => false;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/PathHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace GrisaiaExtractor {
10 | /// A helper with extra methods for paths, files, and directories.
11 | public static class PathHelper {
12 |
13 | //-----------------------------------------------------------------------------
14 | // Constants
15 | //-----------------------------------------------------------------------------
16 |
17 | /// The stored executable path for the entry assembly.
18 | public static readonly string ExePath =
19 | Assembly.GetEntryAssembly().Location;
20 |
21 | /// The directory of the entry executable.
22 | public static readonly string ExeDirectory =
23 | Path.GetDirectoryName(ExePath);
24 |
25 | /// Gets the file name of the entry executable.
26 | public static readonly string ExeFile =
27 | Path.GetFileName(ExePath);
28 |
29 | /// Gets the file name of the entry executable without its extension.
30 | public static readonly string ExeName =
31 | Path.GetFileNameWithoutExtension(ExePath);
32 |
33 | /// Provides a platform-specific character used to separate directory
34 | /// levels in a path string that reflects a hierarchical file system
35 | /// organization.
36 | public static readonly char[] DirectorySeparators = new char[] {
37 | Path.DirectorySeparatorChar,
38 | Path.AltDirectorySeparatorChar,
39 | };
40 |
41 | //-----------------------------------------------------------------------------
42 | // Methods
43 | //-----------------------------------------------------------------------------
44 |
45 | /// Returns true if the fileName has valid characters for search
46 | /// patterns.
47 | public static bool IsValidNamePattern(string name) {
48 | name = name.Replace("*", "").Replace("?", "");
49 | return IsValidName(name);
50 | }
51 |
52 | /// Returns true if the filePath has valid characters for search
53 | /// patterns.
54 | public static bool IsValidPathPattern(string path) {
55 | path = path.Replace("*", "").Replace("?", "");
56 | return IsValidPath(path);
57 | //return path.IndexOfAny(Path.GetInvalidPathChars()) == -1;
58 | }
59 |
60 | /// Returns true if the fileName has valid characters.
61 | public static bool IsValidName(string name) {
62 | return name.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
63 | }
64 |
65 | /// Returns true if the filePath has valid characters.
66 | public static bool IsValidPath(string path) {
67 | try {
68 | Path.GetFullPath(path);
69 | return true;
70 | }
71 | catch {
72 | return false;
73 | }
74 | //return path.IndexOfAny(Path.GetInvalidPathChars()) == -1;
75 | }
76 |
77 | /// Returns true if the filePath has valid characters and does not
78 | /// lead to a directory.
79 | public static bool IsValidFile(string path) {
80 | return IsValidPath(path) &&
81 | !Directory.Exists(path);
82 | }
83 |
84 | /// Returns true if the filePath has valid characters and does not
85 | /// lead to a file.
86 | public static bool IsValidDirectory(string path) {
87 | return IsValidPath(path) &&
88 | !File.Exists(path);
89 | }
90 |
91 | /// Returns true if the filePath has valid characters and is not
92 | /// rooted.
93 | public static bool IsValidRelativePath(string path) {
94 | if (Path.IsPathRooted(path))
95 | return false;
96 | return IsValidPath(path);
97 | }
98 |
99 | /// Returns a path that can be compared with another normalized path.
100 | public static string NormalizePath(string path) {
101 | return Path.GetFullPath(path)
102 | .TrimEnd(DirectorySeparators)
103 | .ToUpperInvariant();
104 | }
105 |
106 | /// Returns true if the two paths lead to the same location.
107 | public static bool IsPathTheSame(string path1, string path2) {
108 | return string.Compare(
109 | NormalizePath(path1), NormalizePath(path2), true) == 0;
110 | }
111 |
112 | /// Combines the specified paths with the executable directory.
113 | public static string CombineExecutable(string path1) {
114 | return Path.Combine(ExeDirectory, path1);
115 | }
116 |
117 | /// Combines the specified paths with the executable directory.
118 | public static string CombineExecutable(string path1, string path2) {
119 | return Path.Combine(ExeDirectory, path1, path2);
120 | }
121 |
122 | /// Combines the specified paths with the executable directory.
123 | public static string CombineExecutable(string path1, string path2,
124 | string path3) {
125 | return Path.Combine(ExeDirectory, path1, path2, path3);
126 | }
127 |
128 | /// Combines the specified paths with the executable directory.
129 | public static string CombineExecutable(params string[] paths) {
130 | return Path.Combine(ExeDirectory, Path.Combine(paths));
131 | }
132 |
133 | /// Gets the proper capitalization of a path so it looks nice.
134 | public static string GetProperDirectoryCapitalization(string dir) {
135 | string path = GetProperDirectoryCapitalization(new DirectoryInfo(dir));
136 | if (path.Length >= 2 && char.IsLetter(path[0]) &&
137 | path[1] == ':' && path[2] == '\\')
138 | {
139 | path = char.ToUpper(path[0]) + path.Substring(1);
140 | }
141 | return path;
142 | }
143 |
144 | /// Gets the proper capitalization of a path so it looks nice.
145 | private static string GetProperDirectoryCapitalization(DirectoryInfo dirInfo) {
146 | DirectoryInfo parentDirInfo = dirInfo.Parent;
147 | if (null == parentDirInfo)
148 | return dirInfo.Name;
149 | return Path.Combine(GetProperDirectoryCapitalization(parentDirInfo),
150 | parentDirInfo.GetDirectories(dirInfo.Name)[0].Name);
151 | }
152 |
153 | /// Returns a collection of all files and subfiles in the directory.
154 | public static List GetAllFiles(string directory) {
155 | List files = new List();
156 | AddAllFiles(files, directory);
157 | return files;
158 | }
159 |
160 | /// Returns a collection of all files and subfiles in the directory.
161 | public static IEnumerable EnumerateAllFiles(string directory, string pattern) {
162 | foreach (string file in Directory.EnumerateFiles(directory, pattern)) {
163 | yield return file;
164 | }
165 | foreach (string dir in Directory.EnumerateDirectories(directory)) {
166 | foreach (string file in EnumerateAllFiles(dir, pattern))
167 | yield return file;
168 | }
169 | }
170 |
171 | public static bool IsDirectoryEmpty(string directory) {
172 | return !Directory.EnumerateFileSystemEntries(directory).Any();
173 | }
174 |
175 | /// Returns a collection of all files and subfiles in the directory.
176 | public static void DeleteAllEmptyDirectories(string directory) {
177 | foreach (string dir in Directory.GetDirectories(directory)) {
178 | if (IsDirectoryEmpty(dir)) {
179 | Directory.Delete(dir);
180 | }
181 | else {
182 | DeleteAllEmptyDirectories(dir);
183 | if (IsDirectoryEmpty(dir))
184 | Directory.Delete(dir);
185 | }
186 | }
187 | }
188 |
189 |
190 | //-----------------------------------------------------------------------------
191 | // Internal Methods
192 | //-----------------------------------------------------------------------------
193 |
194 | /// Adds all of the files and subfiles in the directory to the list.
195 | private static void AddAllFiles(List files, string directory) {
196 | foreach (string file in Directory.GetFiles(directory)) {
197 | files.Add(file);
198 | }
199 | foreach (string dir in Directory.GetDirectories(directory)) {
200 | AddAllFiles(files, dir);
201 | }
202 | }
203 | }
204 | }
205 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/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("GrisaiaExtrator")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("GrisaiaExtrator")]
13 | [assembly: AssemblyCopyright("Copyright © Robert Jordan 2018")]
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("b9e8ea56-874b-4ceb-a703-dca3a307a4d3")]
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.2.2")]
36 | [assembly: AssemblyFileVersion("1.0.2.2")]
37 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Unused/Exkifint.Blowfish.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.CompilerServices;
5 | using System.Runtime.InteropServices;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace GrisaiaExtractor.Asmodean {
10 | public static partial class Exkifint {
11 | public unsafe partial class Blowfish {
12 |
13 | private const int MAXKEYBYTES = 56;
14 | private const int NPASS = 16;
15 |
16 | private uint[] PArray;
17 | private uint[,] SBoxes;
18 |
19 | public Blowfish() {
20 | PArray = new uint[18];
21 | SBoxes = new uint[4,256];
22 | }
23 |
24 | /*private uint S(aword x, int i) {
25 | return SBoxes[i, x.bytes[i]];
26 | }*/
27 |
28 |
29 | //[MethodImpl(MethodImplOptions.AggressiveInlining)]
30 | private uint bf_F(aword x) {
31 | return ((SBoxes[0, x.byte0] + SBoxes[1, x.byte1]) ^ SBoxes[2, x.byte2]) + SBoxes[3, x.byte3];
32 | }
33 |
34 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
35 | private void ROUND(ref aword a, aword x, int n) {
36 | //a.dword ^= bf_F(x) ^ PArray[n];
37 | a.dword ^= (((SBoxes[0, x.byte0] + SBoxes[1, x.byte1]) ^ SBoxes[2, x.byte2]) + SBoxes[3, x.byte3]) ^ PArray[n];
38 | }
39 |
40 | //[MethodImpl(MethodImplOptions.AggressiveInlining)]
41 | private uint ROUND(aword x, int n) {
42 | //a.dword ^= bf_F(x) ^ PArray[n];
43 | Count++;
44 | return (((SBoxes[0, x.byte0] + SBoxes[1, x.byte1]) ^ SBoxes[2, x.byte2]) + SBoxes[3, x.byte3]) ^ PArray[n];
45 | }
46 |
47 | public static int Count = 0;
48 | private unsafe void Blowfish_encipher(uint* xl, uint* xr) {
49 | aword Xl = new aword();
50 | aword Xr = new aword();
51 |
52 | Xl.dword = *xl;
53 | Xr.dword = *xr;
54 |
55 | Xl.dword ^= PArray[0];
56 | /*ROUND(ref Xr, Xl, 1);
57 | ROUND(ref Xl, Xr, 2);
58 | ROUND(ref Xr, Xl, 3);
59 | ROUND(ref Xl, Xr, 4);
60 | ROUND(ref Xr, Xl, 5);
61 | ROUND(ref Xl, Xr, 6);
62 | ROUND(ref Xr, Xl, 7);
63 | ROUND(ref Xl, Xr, 8);
64 | ROUND(ref Xr, Xl, 9);
65 | ROUND(ref Xl, Xr, 10);
66 | ROUND(ref Xr, Xl, 11);
67 | ROUND(ref Xl, Xr, 12);
68 | ROUND(ref Xr, Xl, 13);
69 | ROUND(ref Xl, Xr, 14);
70 | ROUND(ref Xr, Xl, 15);
71 | ROUND(ref Xl, Xr, 16);*/
72 | Xr.dword ^= ROUND(Xl, 1);
73 | Xl.dword ^= ROUND(Xr, 2);
74 | Xr.dword ^= ROUND(Xl, 3);
75 | Xl.dword ^= ROUND(Xr, 4);
76 | Xr.dword ^= ROUND(Xl, 5);
77 | Xl.dword ^= ROUND(Xr, 6);
78 | Xr.dword ^= ROUND(Xl, 7);
79 | Xl.dword ^= ROUND(Xr, 8);
80 | Xr.dword ^= ROUND(Xl, 9);
81 | Xl.dword ^= ROUND(Xr, 10);
82 | Xr.dword ^= ROUND(Xl, 11);
83 | Xl.dword ^= ROUND(Xr, 12);
84 | Xr.dword ^= ROUND(Xl, 13);
85 | Xl.dword ^= ROUND(Xr, 14);
86 | Xr.dword ^= ROUND(Xl, 15);
87 | Xl.dword ^= ROUND(Xr, 16);
88 | Xr.dword ^= PArray[17];
89 |
90 | *xr = Xl.dword;
91 | *xl = Xr.dword;
92 | }
93 |
94 | private unsafe void Blowfish_decipher(uint* xl, uint* xr) {
95 | aword Xl = new aword();
96 | aword Xr = new aword();
97 |
98 | Xl.dword = *xl;
99 | Xr.dword = *xr;
100 |
101 | Xl.dword ^= PArray[17];
102 | /*ROUND(ref Xr, Xl, 16);
103 | ROUND(ref Xl, Xr, 15);
104 | ROUND(ref Xr, Xl, 14);
105 | ROUND(ref Xl, Xr, 13);
106 | ROUND(ref Xr, Xl, 12);
107 | ROUND(ref Xl, Xr, 11);
108 | ROUND(ref Xr, Xl, 10);
109 | ROUND(ref Xl, Xr, 9);
110 | ROUND(ref Xr, Xl, 8);
111 | ROUND(ref Xl, Xr, 7);
112 | ROUND(ref Xr, Xl, 6);
113 | ROUND(ref Xl, Xr, 5);
114 | ROUND(ref Xr, Xl, 4);
115 | ROUND(ref Xl, Xr, 3);
116 | ROUND(ref Xr, Xl, 2);
117 | ROUND(ref Xl, Xr, 1);*/
118 | Xr.dword ^= ROUND(Xl, 16);
119 | Xl.dword ^= ROUND(Xr, 15);
120 | Xr.dword ^= ROUND(Xl, 14);
121 | Xl.dword ^= ROUND(Xr, 13);
122 | Xr.dword ^= ROUND(Xl, 12);
123 | Xl.dword ^= ROUND(Xr, 11);
124 | Xr.dword ^= ROUND(Xl, 10);
125 | Xl.dword ^= ROUND(Xr, 9);
126 | Xr.dword ^= ROUND(Xl, 8);
127 | Xl.dword ^= ROUND(Xr, 7);
128 | Xr.dword ^= ROUND(Xl, 6);
129 | Xl.dword ^= ROUND(Xr, 5);
130 | Xr.dword ^= ROUND(Xl, 4);
131 | Xl.dword ^= ROUND(Xr, 3);
132 | Xr.dword ^= ROUND(Xl, 2);
133 | Xl.dword ^= ROUND(Xr, 1);
134 | Xr.dword ^= PArray[0];
135 |
136 | *xl = Xr.dword;
137 | *xr = Xl.dword;
138 | }
139 |
140 | // constructs the enctryption sieve
141 | public void Initialize(byte* key, int keybytes) {
142 | int i, j;
143 | uint data, datal, datar;
144 | aword temp = new aword();
145 |
146 | // first fill arrays from data tables
147 | for (i = 0; i < 18; i++)
148 | PArray[i] = bf_P[i];
149 |
150 | for (i = 0; i < 4; i++) {
151 | for (j = 0; j < 256; j++)
152 | SBoxes[i,j] = bf_S[i,j];
153 | }
154 |
155 |
156 | j = 0;
157 | for (i = 0; i < NPASS + 2; ++i) {
158 | temp.dword = 0;
159 | temp.byte0 = key[j];
160 | temp.byte1 = key[(j + 1) % keybytes];
161 | temp.byte2 = key[(j + 2) % keybytes];
162 | temp.byte3 = key[(j + 3) % keybytes];
163 | data = temp.dword;
164 | PArray[i] ^= data;
165 | j = (j + 4) % keybytes;
166 | }
167 |
168 | datal = 0;
169 | datar = 0;
170 |
171 | for (i = 0; i < NPASS + 2; i += 2) {
172 | Blowfish_encipher(&datal, &datar);
173 | PArray[i] = datal;
174 | PArray[i + 1] = datar;
175 | }
176 |
177 | for (i = 0; i < 4; ++i) {
178 | for (j = 0; j < 256; j += 2) {
179 | Blowfish_encipher(&datal, &datar);
180 | SBoxes[i,j] = datal;
181 | SBoxes[i,j + 1] = datar;
182 | }
183 | }
184 | }
185 |
186 | // get output length, which must be even MOD 8
187 | private int GetOutputLength(int lInputLong) {
188 | int lVal;
189 |
190 | lVal = lInputLong % 8; // find out if uneven number of bytes atthe end
191 | if (lVal != 0)
192 | return lInputLong + 8 - lVal;
193 | else
194 | return lInputLong;
195 | }
196 |
197 | // Decode pIntput into pOutput. Input length in lSize. Inputbuffer and
198 | // output buffer can be the same, but be sure buffer length is even MOD8.
199 | public unsafe void Decode(byte[] pInputArray, byte[] pOutputArray, int lSize) {
200 | uint lCount;
201 | byte* pi, po;
202 | int i;
203 | bool SameDest = pInputArray == pOutputArray;
204 |
205 | fixed (byte* pInputFixed = pInputArray)
206 | fixed (byte* pOutputFixed = pOutputArray) {
207 | byte* pInput = pInputFixed;
208 | byte* pOutput = pOutputFixed;
209 |
210 | for (lCount = 0; lCount < lSize; lCount += 8) {
211 | if (SameDest) // if encoded data is being written into inputbuffer
212 | {
213 | Blowfish_decipher((uint*) pInput,
214 | (uint*) (pInput + 4));
215 | pInput += 8;
216 | }
217 | else // output buffer not equal to inputbuffer
218 | { // so copy input to output before decoding
219 | pi = pInput;
220 | po = pOutput;
221 | for (i = 0; i < 8; i++)
222 | *po++ = *pi++;
223 | Blowfish_decipher((uint*) pOutput,
224 | (uint*) (pOutput + 4));
225 | pInput += 8;
226 | pOutput += 8;
227 | }
228 | }
229 | }
230 | }
231 |
232 |
233 | public void Set_Key(byte* key, int keybytes) {
234 | Initialize(key, keybytes);
235 | }
236 |
237 | public void Decrypt(byte[] pInput, int lSize) {
238 | if (lSize != GetOutputLength(lSize))
239 | throw new Exception("Input len != Output len");
240 |
241 | byte[] pOutput = new byte[lSize];
242 | Decode(pInput, pOutput, lSize);
243 |
244 | Array.Copy(pOutput, pInput, lSize);
245 | }
246 |
247 | [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 4)]
248 | private struct aword {
249 | [FieldOffset(0)]
250 | public uint dword;
251 | [FieldOffset(0)]
252 | public byte byte3;
253 | [FieldOffset(1)]
254 | public byte byte2;
255 | [FieldOffset(2)]
256 | public byte byte1;
257 | [FieldOffset(3)]
258 | public byte byte0;
259 |
260 | /*public byte byte3 {
261 | get { return (byte) (dword & 0xFF); }
262 | set { dword = (dword & 0xFFFFFF00) ^ value; }
263 | }
264 | public byte byte2 {
265 | get { return (byte) ((dword >> 8) & 0xFF); }
266 | set { dword = (dword & 0xFFFF00FF) ^ (uint) (value << 8); }
267 | }
268 | public byte byte1 {
269 | get { return (byte) ((dword >> 16) & 0xFF); }
270 | set { dword = (dword & 0xFF00FFFF) ^ (uint) (value << 16); }
271 | }
272 | public byte byte0 {
273 | get { return (byte) ((dword >> 24) & 0xFF); }
274 | set { dword = (dword & 0x00FFFFFF) ^ (uint) (value << 24); }
275 | }*/
276 | }
277 | }
278 | }
279 | }
280 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/Unused/Hgx2png.BitBuffer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace GrisaiaExtractor.Asmodean {
8 | public static partial class Hgx2png {
9 | private class BitBuffer {
10 |
11 | private byte[] buffer;
12 | private int index;
13 |
14 | public BitBuffer(byte[] buffer) {
15 | this.buffer = buffer;
16 | this.index = 0;
17 | }
18 |
19 | public bool GetBit() {
20 | return ((buffer[index / 8] >> (index++ % 8)) & 1) == 1;
21 | }
22 |
23 | // Didn't expect to see this in the wild...
24 | public uint GetEliasGammaValue() {
25 | uint value = 0;
26 | int digits = 0;
27 |
28 | while (!GetBit())
29 | digits++;
30 |
31 | value = 1U << digits;
32 |
33 | while (digits-- != 0) {
34 | if (GetBit())
35 | value |= 1U << digits;
36 | }
37 |
38 | return value;
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/GrisaiaExtractor/zlib1.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trigger-segfault/GrisaiaExtractor/fdd6e8339fd4e69a0c6fc92acb7aa57000b6b81c/GrisaiaExtractor/zlib1.dll
--------------------------------------------------------------------------------
/GrisaiaExtractorConsole/App.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trigger-segfault/GrisaiaExtractor/fdd6e8339fd4e69a0c6fc92acb7aa57000b6b81c/GrisaiaExtractorConsole/App.ico
--------------------------------------------------------------------------------
/GrisaiaExtractorConsole/AsciiImage.cs:
--------------------------------------------------------------------------------
1 | using GrisaiaExtractor.Extensions;
2 | using System;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace GrisaiaExtractorConsole {
8 | public class AsciiImage {
9 | public struct Pixel {
10 | public static readonly Encoding ConsoleEncoding =
11 | Encoding.GetEncoding("Windows-1252");
12 |
13 | public char Character;
14 | public ConsoleColor Foreground;
15 |
16 | public Pixel(char character, ConsoleColor foreground) {
17 | Character = character;
18 | Foreground = foreground;
19 | }
20 |
21 | public Pixel(byte character, byte foreground) {
22 | Character = ConsoleEncoding.GetChar(character);
23 | Foreground = (ConsoleColor) foreground;
24 | }
25 | }
26 |
27 | public Pixel[,] Pixels { get; private set; }
28 |
29 | public int Width => Pixels.GetLength(0);
30 | public int Height => Pixels.GetLength(1);
31 |
32 | public static AsciiImage FromStream(Stream stream) {
33 | AsciiImage image = new AsciiImage();
34 | BinaryReader reader = new BinaryReader(stream);
35 |
36 | int width = reader.ReadInt32();
37 | int height = reader.ReadInt32();
38 | image.Pixels = new Pixel[width, height];
39 | for (int y = 0; y < height; y++) {
40 | for (int x = 0; x < width; x++) {
41 | image.Pixels[x, y] = new Pixel(
42 | reader.ReadByte(), reader.ReadByte());
43 | }
44 | }
45 |
46 | return image;
47 | }
48 |
49 | public void Draw() {
50 | ConsoleColor oldForeground = Console.ForegroundColor;
51 |
52 | // Make sure we start on a brand-spanking-new line
53 | if (Console.CursorLeft > 0)
54 | Console.WriteLine();
55 |
56 | // Optimized by writing to the console as few times as possible
57 | int bufferWidth = Console.BufferWidth;
58 | string currentLine = "";
59 | for (int y = 0; y < Height; y++) {
60 | for (int x = 0; x < Width && x < bufferWidth; x++) {
61 | if (Pixels[x, y].Foreground != Console.ForegroundColor) {
62 | // We've reached a few color, gotta write the current line
63 | // (Check to make sure this isn't the first pixel
64 | if (currentLine.Length > 0) {
65 | Console.Write(currentLine);
66 | currentLine = "";
67 | }
68 | // Set the new foreground color for the next line
69 | Console.ForegroundColor = Pixels[x, y].Foreground;
70 | }
71 | currentLine += Pixels[x, y].Character;
72 | }
73 |
74 | // Keep drawing the current string onto the next line
75 | // (If we don't automatically go to the next line due to wrapping)
76 | if ((Console.CursorLeft + currentLine.Length) % bufferWidth != 0)
77 | currentLine += Environment.NewLine;
78 | }
79 | // Write the remaining line
80 | if (currentLine.Length > 0)
81 | Console.Write(currentLine);
82 |
83 | Console.ForegroundColor = oldForeground;
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/GrisaiaExtractorConsole/GrisaiaExtractorConsole.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {1B2D824A-DD0D-4019-B234-54E5543B7A42}
8 | Exe
9 | GrisaiaExtractorConsole
10 | GrisaiaExtract
11 | v4.6.1
12 | 512
13 | true
14 |
15 |
16 | x86
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | TRACE;DEBUG
22 | prompt
23 | 4
24 |
25 |
26 | x86
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 | App.ico
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | {b9e8ea56-874b-4ceb-a703-dca3a307a4d3}
66 | GrisaiaExtractor
67 |
68 |
69 | {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}
70 | asmodean
71 | false
72 | Content
73 | PreserveNewest
74 | True
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/GrisaiaExtractorConsole/Ini/IniEnums.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace GrisaiaExtractorConsole.Ini {
8 | /// The available property assignment styles for ini documents.
9 | public enum IniAssignmentStyle {
10 | /// Uses "=" for ini property assignment.
11 | Equals,
12 | /// Uses ":" for ini property assignment.
13 | Colon,
14 | /// Uses " = " for ini property assignment.
15 | EqualsSpaced,
16 | /// Uses " : " for ini property assignment.
17 | ColonSpaced,
18 | }
19 |
20 | /// The available comment styles for ini documents.
21 | public enum IniCommentStyle {
22 | /// Uses ";" as the ini comment indicator.
23 | Semicolon,
24 | /// Uses "#" as the ini comment indicator.
25 | Pound,
26 | /// Uses "!" as the ini comment indicator.
27 | Exclamation,
28 | /// Uses "; " as the ini comment indicator.
29 | SemicolonSpaced,
30 | /// Uses "# " as the ini comment indicator.
31 | PoundSpaced,
32 | /// Uses "! " as the ini comment indicator.
33 | ExclamationSpaced,
34 | }
35 |
36 | /// The formats an enum can be stored in.
37 | public enum EnumFormat {
38 | /// The enum is stored in string form.
39 | String,
40 | /// The enum is stored in integer form.
41 | Int,
42 | }
43 |
44 | /// Extensions for the ini enums.
45 | public static class IniEnumExtensions {
46 | /// Gets the string representation of the ini assignment style.
47 | public static string GetString(this IniAssignmentStyle assignmentStyle) {
48 | switch (assignmentStyle) {
49 | case IniAssignmentStyle.Equals: return "=";
50 | case IniAssignmentStyle.Colon: return ":";
51 | case IniAssignmentStyle.EqualsSpaced: return " = ";
52 | case IniAssignmentStyle.ColonSpaced: return " : ";
53 | }
54 | return "";
55 | }
56 |
57 | /// Gets the string representation of the ini comment style.
58 | public static string GetString(this IniCommentStyle commentStyle) {
59 | switch (commentStyle) {
60 | case IniCommentStyle.Semicolon: return ";";
61 | case IniCommentStyle.Pound: return "#";
62 | case IniCommentStyle.Exclamation: return "!";
63 | case IniCommentStyle.SemicolonSpaced: return "; ";
64 | case IniCommentStyle.PoundSpaced: return "# ";
65 | case IniCommentStyle.ExclamationSpaced: return "! ";
66 | }
67 | return "";
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/GrisaiaExtractorConsole/Ini/IniProperty.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace GrisaiaExtractorConsole.Ini {
8 | public class IniProperty {
9 |
10 | //-----------------------------------------------------------------------------
11 | // Members
12 | //-----------------------------------------------------------------------------
13 |
14 | /// The name of the property.
15 | private string name;
16 | /// The comments for the property.
17 | private string comments;
18 | /// The value of the property.
19 | private string value;
20 |
21 | // Save Settings
22 | /// True if the property uses quotes to format its value.
23 | private bool useQuotes;
24 |
25 |
26 | //-----------------------------------------------------------------------------
27 | // Constructor
28 | //-----------------------------------------------------------------------------
29 |
30 | /// Constructs the ini property with the specified name, value, and
31 | /// settings.
32 | public IniProperty(string name, string value = "", string comments = "",
33 | bool useQuotes = false)
34 | {
35 | this.name = name;
36 | this.comments = comments;
37 | this.value = value;
38 | this.useQuotes = useQuotes;
39 | }
40 |
41 |
42 | //-----------------------------------------------------------------------------
43 | // Get Accessors
44 | //-----------------------------------------------------------------------------
45 |
46 | /// Gets the value of the property as an enum.
47 | public TEnum GetEnum(EnumFormat format = EnumFormat.String)
48 | where TEnum : struct, IConvertible
49 | {
50 | if (format == EnumFormat.String) {
51 | TEnum result;
52 | Enum.TryParse(value, out result);
53 | return result;
54 | }
55 | else {
56 | return (TEnum) Enum.ToObject(typeof(TEnum), GetInt());
57 | }
58 | }
59 |
60 | /// Gets the string value of the property.
61 | public string GetString() {
62 | return value;
63 | }
64 |
65 | /// Gets the integer value of the property.
66 | public int GetInt() {
67 | int result;
68 | int.TryParse(value, out result);
69 | return result;
70 | }
71 |
72 | /// Gets the float value of the property.
73 | public float GetFloat() {
74 | float result;
75 | float.TryParse(value, out result);
76 | return result;
77 | }
78 |
79 | /// Get the boolean value of the property.
80 | public bool GetBool() {
81 | if (string.Compare(value, "true", true) == 0 ||
82 | string.Compare(value, "1") == 0)
83 | {
84 | return true;
85 | }
86 | return false;
87 | }
88 |
89 |
90 | //-----------------------------------------------------------------------------
91 | // Try Get Accessors
92 | //-----------------------------------------------------------------------------
93 |
94 | /// Trys to get the value of the property as an enum.
95 | public bool TryGetEnum(out TEnum result,
96 | EnumFormat format = EnumFormat.String)
97 | where TEnum : struct, IConvertible
98 | {
99 | try {
100 | if (format == EnumFormat.String)
101 | result = (TEnum) Enum.Parse(typeof(TEnum), value);
102 | else
103 | result = (TEnum) Enum.ToObject(typeof(TEnum), GetInt());
104 | return true;
105 | }
106 | catch {
107 | result = Activator.CreateInstance();
108 | return false;
109 | }
110 | }
111 |
112 | /// Trys to get the integer value of the property.
113 | public bool TryGetInt(out int result) {
114 | return int.TryParse(value, out result);
115 | }
116 |
117 | /// Trys to get the float value of the property.
118 | public bool TryGetFloat(out float result) {
119 | return float.TryParse(value, out result);
120 | }
121 |
122 | /// Trys to get the boolean value of the property.
123 | public bool TryGetBool(out bool result) {
124 | if (string.Compare(value, "true", true) == 0 ||
125 | string.Compare(value, "1") == 0)
126 | {
127 | result = true;
128 | return true;
129 | }
130 | if (string.Compare(value, "false", true) == 0 ||
131 | string.Compare(value, "0") == 0)
132 | {
133 | result = false;
134 | return true;
135 | }
136 | result = false;
137 | return false;
138 | }
139 |
140 |
141 | //-----------------------------------------------------------------------------
142 | // Mutators
143 | //-----------------------------------------------------------------------------
144 |
145 | /// Set the value of the property as an enum.
146 | public void SetEnum(TEnum value, EnumFormat format = EnumFormat.String)
147 | where TEnum : struct, IConvertible
148 | {
149 | if (format == EnumFormat.String)
150 | this.value = value.ToString();
151 | else
152 | this.value = ((int)(object) value).ToString();
153 | }
154 |
155 | /// Sets the string value of the property.
156 | public void SetString(string value) {
157 | this.value = value;
158 | }
159 |
160 | /// Sets the integer value of the property.
161 | public void SetInt(int value) {
162 | this.value = value.ToString();
163 | }
164 |
165 | /// Sets the float value of the property.
166 | public void SetFloat(float value) {
167 | this.value = value.ToString();
168 | }
169 |
170 | /// Sets the boolean value of the property.
171 | public void SetBool(bool value) {
172 | this.value = value.ToString();
173 | }
174 |
175 | /// Sets the object value of the property.
176 | public void SetObject(object value) {
177 | this.value = value.ToString();
178 | }
179 |
180 |
181 | //-----------------------------------------------------------------------------
182 | // Properties
183 | //-----------------------------------------------------------------------------
184 |
185 | /// Gets the name of the property.
186 | public string Name {
187 | get { return name; }
188 | }
189 |
190 | /// Gets or sets the comments for the property.
191 | public string Comments {
192 | get { return comments; }
193 | set { comments = value; }
194 | }
195 |
196 | /// Gets or sets the value of the property.
197 | public string Value {
198 | get { return value; }
199 | set { this.value = value; }
200 | }
201 |
202 | /// Gets or sets if the property uses quotes to format its value.
203 | public bool UseQuotes {
204 | get { return useQuotes; }
205 | set { useQuotes = value; }
206 | }
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/GrisaiaExtractorConsole/Ini/IniSection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace GrisaiaExtractorConsole.Ini {
9 | public class IniSection : IEnumerable {
10 |
11 | //-----------------------------------------------------------------------------
12 | // Members
13 | //-----------------------------------------------------------------------------
14 |
15 | /// The name of the section.
16 | private string name;
17 | /// The description of the section.
18 | private string comments;
19 | /// The collection of properties in the section.
20 | private Dictionary properties;
21 |
22 |
23 | //-----------------------------------------------------------------------------
24 | // Constructor
25 | //-----------------------------------------------------------------------------
26 |
27 | /// Constructs the ini section with the specified name and optional
28 | /// comments.
29 | public IniSection(string name, string comments = "") {
30 | this.name = name;
31 | this.comments = comments;
32 | this.properties = new Dictionary();
33 | }
34 |
35 |
36 | //-----------------------------------------------------------------------------
37 | // IEnumerable
38 | //-----------------------------------------------------------------------------
39 |
40 | /// Gets the enumerator for the properties in the section.
41 | public IEnumerator GetEnumerator() {
42 | return properties.Values.GetEnumerator();
43 | }
44 |
45 | /// Gets the enumerator for the properties in the section.
46 | IEnumerator IEnumerable.GetEnumerator() {
47 | return properties.Values.GetEnumerator();
48 | }
49 |
50 |
51 | //-----------------------------------------------------------------------------
52 | // Accessors
53 | //-----------------------------------------------------------------------------
54 |
55 | /// Gets the property in the section with the specified name.
56 | public IniProperty Get(string propertyName, bool returnDefault = true) {
57 | IniProperty property;
58 | properties.TryGetValue(propertyName, out property);
59 | if (property == null && returnDefault)
60 | return new IniProperty(propertyName, "");
61 | return property;
62 | }
63 |
64 | /// Returns true if this section contains the specified property.
65 | public bool Contains(IniProperty property) {
66 | return properties.ContainsKey(property.Name);
67 | }
68 |
69 | /// Returns true if this section contains a property with the
70 | /// specified name.
71 | public bool Contains(string propertyName) {
72 | return properties.ContainsKey(propertyName);
73 | }
74 |
75 | /// Returns true if the section has any properties.
76 | public bool Any() {
77 | return properties.Any();
78 | }
79 |
80 |
81 | //-----------------------------------------------------------------------------
82 | // Mutators
83 | //-----------------------------------------------------------------------------
84 |
85 | /// Adds the property to the section.
86 | public IniProperty Add(IniProperty property) {
87 | properties[property.Name] = property;
88 | return property;
89 | }
90 |
91 | /// Adds a new property to the section.
92 | public IniProperty Add(string propertyName, string value = "",
93 | string comments = "", bool useQuotes = false)
94 | {
95 | return Add(new IniProperty(propertyName, value, comments, useQuotes));
96 | }
97 |
98 | /// Removes the property from the section.
99 | public void Remove(IniProperty property) {
100 | properties.Remove(property.Name);
101 | }
102 |
103 | /// Removes the property with the specified name from the section.
104 | public void Remove(string propertyName) {
105 | properties.Remove(propertyName);
106 | }
107 |
108 | /// Removes all of the properties from the section.
109 | public void Clear() {
110 | properties.Clear();
111 | }
112 |
113 |
114 | //-----------------------------------------------------------------------------
115 | // Get Property Accessors
116 | //-----------------------------------------------------------------------------
117 |
118 | /// Gets the value of the property as an enum.
119 | public TEnum GetEnum(string propertyName,
120 | EnumFormat format = EnumFormat.String)
121 | where TEnum : struct, IConvertible
122 | {
123 | return Get(propertyName).GetEnum(format);
124 | }
125 |
126 | /// Gets the string value of the property.
127 | public string GetString(string propertyName) {
128 | return Get(propertyName).GetString();
129 | }
130 |
131 | /// Gets the integer value of the property.
132 | public int GetInt(string propertyName) {
133 | return Get(propertyName).GetInt();
134 | }
135 |
136 | /// Gets the float value of the property.
137 | public float GetFloat(string propertyName) {
138 | return Get(propertyName).GetFloat();
139 | }
140 |
141 | /// Get the boolean value of the property.
142 | public bool GetBool(string propertyName) {
143 | return Get(propertyName).GetBool();
144 | }
145 |
146 |
147 | //-----------------------------------------------------------------------------
148 | // Try Get Property Accessors
149 | //-----------------------------------------------------------------------------
150 |
151 | /// Trys to get the value of the property as an enum.
152 | public bool TryGetEnum(string propertyName, out TEnum result,
153 | EnumFormat format = EnumFormat.String)
154 | where TEnum : struct, IConvertible
155 | {
156 | return Get(propertyName).TryGetEnum(out result);
157 | }
158 |
159 | /// Trys to get the integer value of the property.
160 | public bool TryGetInt(string propertyName, out int result) {
161 | return Get(propertyName).TryGetInt(out result);
162 | }
163 |
164 | /// Trys to get the float value of the property.
165 | public bool TryGetFloat(string propertyName, out float result) {
166 | return Get(propertyName).TryGetFloat(out result);
167 | }
168 |
169 | /// Trys to get the boolean value of the property.
170 | public bool TryGetBool(string propertyName, out bool result) {
171 | return Get(propertyName).TryGetBool(out result);
172 | }
173 |
174 |
175 | //-----------------------------------------------------------------------------
176 | // Set Property Mutators
177 | //-----------------------------------------------------------------------------
178 |
179 | /// Set the value of the property as an enum.
180 | public void SetEnum(string propertyName, TEnum value,
181 | EnumFormat format = EnumFormat.String)
182 | where TEnum : struct, IConvertible
183 | {
184 | Get(propertyName).SetEnum(value, format);
185 | }
186 |
187 | /// Sets the string value of the property.
188 | public void SetString(string propertyName, string value) {
189 | Get(propertyName).SetString(value);
190 | }
191 |
192 | /// Sets the integer value of the property.
193 | public void SetInt(string propertyName, int value) {
194 | Get(propertyName).SetInt(value);
195 | }
196 |
197 | /// Sets the float value of the property.
198 | public void SetFloat(string propertyName, float value) {
199 | Get(propertyName).SetFloat(value);
200 | }
201 |
202 | /// Sets the boolean value of the property.
203 | public void SetBool(string propertyName, bool value) {
204 | Get(propertyName).SetBool(value);
205 | }
206 |
207 | /// Sets the object value of the property.
208 | public void SetObject(string propertyName, object value) {
209 | Get(propertyName).SetObject(value);
210 | }
211 |
212 |
213 | //-----------------------------------------------------------------------------
214 | // Properties
215 | //-----------------------------------------------------------------------------
216 |
217 | /// Gets the name of the section.
218 | public string Name {
219 | get { return name; }
220 | }
221 |
222 | /// Gets or sets the description of the section.
223 | public string Comments {
224 | get { return comments; }
225 | set { comments = value; }
226 | }
227 |
228 | /// Gets the number of properties in the section.
229 | public int Count {
230 | get { return properties.Count; }
231 | }
232 | }
233 | }
234 |
--------------------------------------------------------------------------------
/GrisaiaExtractorConsole/Ini/TypeHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Reflection;
6 |
7 | namespace GrisaiaExtractorConsole.Ini {
8 | /// An exception thrown when a type could not be found.
9 | public class MissingTypeException : Exception {
10 | /// Constructs the missing type exception for the specified type.
11 | public MissingTypeException(string typeName)
12 | : base("Type '" + typeName + "' could not be found!") { }
13 | }
14 |
15 | /// An exception thrown when a type does not inherit from the
16 | /// required type.
17 | public class NoInheritanceException : Exception {
18 | /// Constructs the does not inherit exception for the specified types.
19 | public NoInheritanceException(Type baseType, Type type)
20 | : base("Type '" + type.Name + "' does not inherit '" +
21 | baseType.Name + "'!") { }
22 | }
23 |
24 | /// A static class for helpers with object types
25 | public static class TypeHelper {
26 |
27 | //-----------------------------------------------------------------------------
28 | // Get Inheritance
29 | //-----------------------------------------------------------------------------
30 |
31 | /// Returns a list of types that Type inherits from.
32 | public static Type[] GetInheritance(Type type, bool baseTypesFirst) {
33 | return GetInheritance(typeof(object), type, baseTypesFirst);
34 | }
35 |
36 | /// Returns a list of types that Type inherits from until BaseType.
37 | public static Type[] GetInheritance(Type type, bool baseTypesFirst) {
38 | return GetInheritance(typeof(BaseType), type, baseTypesFirst);
39 | }
40 |
41 | /// Returns a list of types that Type inherits from until BaseType.
42 | /// Type does not inherit base type.
43 | public static Type[] GetInheritance(Type baseType, Type type,
44 | bool baseTypesFirst)
45 | {
46 | if (baseType == null || type == null)
47 | return new Type[0];
48 | if (!baseType.IsAssignableFrom(type))
49 | throw new ArgumentException("Type does not inherit from BaseType!");
50 | List types = new List();
51 | while (type != null) {
52 | if (baseTypesFirst)
53 | types.Insert(0, type);
54 | else
55 | types.Add(type);
56 | if (type.Equals(baseType))
57 | break;
58 | type = type.BaseType;
59 | }
60 | return types.ToArray();
61 | }
62 |
63 | /// Gets the type's most-extended interface that inherits from the
64 | /// base interface. Returns null if no interface was found.
65 | public static Type GetExtendedInterface(Type type, Type baseInterface) {
66 | Type nextInterface = baseInterface;
67 | bool found = false;
68 | foreach (Type interfaceType in type.GetInterfaces()) {
69 | if (nextInterface.IsAssignableFrom(interfaceType)) {
70 | nextInterface = interfaceType;
71 | found = true;
72 | }
73 | }
74 | return (found ? nextInterface : null);
75 | }
76 |
77 | /// Gets the type's most-extended interface that inherits from the
78 | /// base interface. Returns null if no interface was found.
79 | public static Type GetExtendedInterface(Type type) {
80 | return GetExtendedInterface(type, typeof(BaseInterface));
81 | }
82 |
83 |
84 | //-----------------------------------------------------------------------------
85 | // Type Has Base
86 | //-----------------------------------------------------------------------------
87 |
88 | /// Returns true if the specified type implements the specified base.
89 | public static bool TypeHasBase(Type type) {
90 | return TypeHasBase(typeof(BaseType), type);
91 | }
92 |
93 | /// Returns true if the specified type implements the specified base.
94 | public static bool TypeHasBase(Type baseType, Type type) {
95 | if (baseType == null || type == null)
96 | return false;
97 | return baseType.IsAssignableFrom(type);
98 | }
99 |
100 |
101 | //-----------------------------------------------------------------------------
102 | // Find Type With Base
103 | //-----------------------------------------------------------------------------
104 |
105 | /// Returns the type with the specified name.
106 | /// The type could not be found.
107 | /// The type does not inherit base type.
108 | public static Type FindTypeWithBase(string typeName,
109 | bool ignoreCase, params Assembly[] assemblies)
110 | {
111 | return FindTypeWithBase(typeof(BaseType), typeName, ignoreCase,
112 | assemblies);
113 | }
114 |
115 | /// Returns the type with the specified name.
116 | /// Returns null if the type was not found or does not inheritf base type.
117 | public static Type FindTypeWithBaseSafe(string typeName,
118 | bool ignoreCase, params Assembly[] assemblies)
119 | {
120 | return FindTypeWithBaseSafe(typeof(BaseType), typeName, ignoreCase,
121 | assemblies);
122 | }
123 |
124 | /// Returns the type with the specified name.
125 | /// The type could not be found.
126 | /// The type does not inherit base type.
127 | public static Type FindTypeWithBase(Type baseType, string typeName,
128 | bool ignoreCase, params Assembly[] assemblies)
129 | {
130 | Type type = FindType(typeName, ignoreCase, assemblies);
131 | if (!baseType.IsAssignableFrom(type))
132 | throw new NoInheritanceException(baseType, type);
133 | return type;
134 | }
135 |
136 | /// Returns the type with the specified name.
137 | /// Returns null if the type was not found or does not inheritf base type.
138 | public static Type FindTypeWithBaseSafe(Type baseType, string typeName,
139 | bool ignoreCase, params Assembly[] assemblies)
140 | {
141 | Type type = FindTypeSafe(typeName, ignoreCase, assemblies);
142 | if (type != null && !baseType.IsAssignableFrom(type))
143 | throw new NoInheritanceException(baseType, type);
144 | return type;
145 | }
146 |
147 |
148 | //-----------------------------------------------------------------------------
149 | // Find Type
150 | //-----------------------------------------------------------------------------
151 |
152 | /// Returns the type with the specified name. Throws an exception
153 | /// if the type could not be found.
154 | /// The type could not be found.
155 | public static Type FindType(string typeName, bool ignoreCase,
156 | params Assembly[] assemblies)
157 | {
158 | Type type = FindTypeSafe(typeName, ignoreCase, assemblies);
159 | if (type == null)
160 | throw new MissingTypeException(typeName);
161 | return type;
162 | }
163 |
164 | /// Returns the type with the specified name. Returns null if the
165 | /// type could not be found.
166 | public static Type FindTypeSafe(string typeName, bool ignoreCase,
167 | params Assembly[] assemblies) {
168 | StringComparison comparision = StringComparison.Ordinal;
169 | if (ignoreCase)
170 | comparision = StringComparison.OrdinalIgnoreCase;
171 |
172 | // Check the listed assemblies
173 | Type type = null;
174 | foreach (Assembly assembly in assemblies) {
175 | type = assembly.GetTypes()
176 | .FirstOrDefault(t => t.Name.Equals(typeName, comparision));
177 | if (type != null)
178 | return type;
179 | }
180 |
181 | return null;
182 | }
183 |
184 |
185 | //-----------------------------------------------------------------------------
186 | // Get Default Value
187 | //-----------------------------------------------------------------------------
188 |
189 | /// Gets the default value of the type.
190 | /// Runtime equivalent of default(type).
191 | public static T GetDefaultValue() {
192 | return (T) GetDefaultValue(typeof(T));
193 | }
194 |
195 | /// Gets the default value of the type.
196 | /// Runtime equivalent of default(type).
197 | public static object GetDefaultValue(Type type) {
198 | if (type.IsValueType)
199 | return Activator.CreateInstance(type);
200 | return null;
201 | }
202 |
203 |
204 | //-----------------------------------------------------------------------------
205 | // Converting
206 | //-----------------------------------------------------------------------------
207 |
208 | /// Converts the value to the specified type using the type's
209 | /// type converter.
210 | public static object ConvertFrom(Type type, object value) {
211 | var converter = TypeDescriptor.GetConverter(type);
212 | return converter.ConvertFrom(value);
213 | }
214 |
215 | /// Converts the value to the specified type using the value's
216 | /// type converter.
217 | public static object ConvertTo(Type type, object value) {
218 | var converter = TypeDescriptor.GetConverter(value.GetType());
219 | return converter.ConvertTo(value, type);
220 | }
221 | }
222 | }
223 |
--------------------------------------------------------------------------------
/GrisaiaExtractorConsole/Program.Classes.cs:
--------------------------------------------------------------------------------
1 | using GrisaiaExtractor;
2 | using GrisaiaExtractor.Extensions;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace GrisaiaExtractorConsole {
11 | static partial class Program {
12 | public struct IntArgs {
13 | public string InputDir { get; set; }
14 | public string OutputDir { get; set; }
15 | public string OutputDirAfter { get; set; }
16 | public string IntFile { get; set; }
17 | public Game Game { get; set; }
18 |
19 | public bool IsImage {
20 | get {
21 | return Path.GetFileNameWithoutExtension(IntFile).ToLower()
22 | .StartsWith("image");
23 | }
24 | }
25 | }
26 |
27 | public struct Hg3Args {
28 | public string InputDir { get; set; }
29 | public string InputDirAfter { get; set; }
30 | public string OutputDir { get; set; }
31 | public string OutputDirAfter { get; set; }
32 | public string Pattern { get; set; }
33 | public Hg3Sorting Sorting { get; set; }
34 | public bool StopOnError { get; set; }
35 | public string ContinueFile { get; set; }
36 | public Game Game { get; set; }
37 | }
38 |
39 | public struct PngArgs {
40 | public string ResortDir { get; set; }
41 | public string ResortDirAfter { get; set; }
42 | public Game Game { get; set; }
43 | }
44 |
45 | private class LogInfo : IDisposable {
46 | public DateTime StartTime { get; } = DateTime.UtcNow;
47 | public int GamesComplete { get; set; }
48 | public HashSet GamesWithErrors { get; } = new HashSet();
49 | public HashSet GamesFailed { get; } = new HashSet();
50 |
51 | public int OperationsComplete { get; set; }
52 |
53 |
54 | public TimeSpan Ellapsed => DateTime.UtcNow - StartTime;
55 |
56 | public StreamWriter LogWriter { get; }
57 | public int LastOperationLogged { get; set; }
58 |
59 | public void WriteLine(string line) => LogWriter.WriteLine(line);
60 | public void WriteLine() => LogWriter.WriteLine();
61 | public void Write(string text) => LogWriter.Write(text);
62 |
63 | public LogInfo() {
64 | string path = PathHelper.CombineExecutable($"{PathHelper.ExeName}.log");
65 | var stream = new FileStream(path, FileMode.Append);
66 | LogWriter = new StreamWriter(stream) {
67 | AutoFlush = true,
68 | };
69 | }
70 |
71 | public void Dispose() {
72 | LogWriter.Close();
73 | }
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/GrisaiaExtractorConsole/Program.Input.cs:
--------------------------------------------------------------------------------
1 | using GrisaiaExtractor;
2 | using GrisaiaExtractor.Extensions;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace GrisaiaExtractorConsole {
11 | static partial class Program {
12 | private static Game ReadGame(bool allowNone = false) {
13 | do {
14 | List games = Locator.LocateGames(out bool newPaths, true);
15 | if (newPaths) {
16 | settings.Save();
17 | }
18 | int index = 1;
19 | foreach (Game game in games) {
20 | Console.Write($"{index}) ");
21 | game.WriteLine(settings.General.UseJapaneseNames);
22 | /*Console.Write($"{index}) {game.Game.JPName}");
23 | if (game.Path == null)
24 | Console.Write(": [NOT FOUND]");
25 | Console.WriteLine();*/
26 | index++;
27 | }
28 | Console.WriteLine($"{index}) {Game.All.Name()}");
29 | if (allowNone)
30 | Console.WriteLine("0) None");
31 | Console.Write("Choice: ");
32 | if (!int.TryParse(ReadLine(), out index) || index < 0)
33 | WriteError("Input is not a valid index!");
34 | else if ((!allowNone && index == 0) || index - 1 > games.Count)
35 | WriteError("Input index is out of bounds!");
36 | else if (index == 0)
37 | return null;
38 | else if (index - 1 == games.Count) {
39 | Console.WriteLine();
40 | Console.WriteLine("All located games will be ripped and each " +
41 | "game will use a directory with its name.");
42 | Console.WriteLine();
43 | return Game.All;
44 | }
45 | else
46 | return games[index - 1];
47 | } while (true);
48 | }
49 |
50 | private static IntArgs RequestExtractIntArgs(Game game) {
51 | IntArgs args = new IntArgs() {
52 | Game = game,
53 | };
54 | if (game != null)
55 | Console.WriteLine($"Extract {game.Name()} Int Archive:");
56 | else
57 | Console.WriteLine($"Extract Int Archive:");
58 |
59 | bool parseSuccess;
60 |
61 | if (game != Game.All) {
62 | do {
63 | Console.Write("Input Directory: ");
64 | if (game.Path != null)
65 | WriteWatermark("");
66 | args.InputDir = ReadDirectory(game.Path, out parseSuccess);
67 | } while (!parseSuccess);
68 | }
69 |
70 | string defOutputDir = Path.Combine(game.Name(), settings.Directories.IntDirectory);
71 | do {
72 | if (game == Game.All) {
73 | defOutputDir = ".";
74 | Console.Write("Output Directory (Before game name): ");
75 | WriteWatermark("");
76 | }
77 | else {
78 | Console.Write("Output Directory: ");
79 | WriteWatermark(defOutputDir);
80 | }
81 | args.OutputDir = ReadDirectory(defOutputDir, out parseSuccess);
82 | } while (!parseSuccess);
83 |
84 | if (game == Game.All) {
85 | defOutputDir = settings.Directories.IntDirectory;
86 | do {
87 | Console.Write("Output Directory (After game name): ");
88 | WriteWatermark(defOutputDir);
89 | args.OutputDirAfter = ReadRelativePath(defOutputDir, out parseSuccess);
90 | } while (!parseSuccess);
91 | }
92 |
93 | do {
94 | Console.Write("Int File: ");
95 | WriteWatermark("image*.int");
96 | args.IntFile = ReadPattern("image*.int", out parseSuccess);
97 | } while (!parseSuccess);
98 | if (!args.IntFile.EndsWith(".int", StringComparison.OrdinalIgnoreCase) &&
99 | !args.IntFile.EndsWith(".int*", StringComparison.OrdinalIgnoreCase)) {
100 | args.IntFile += ".int";
101 | }
102 |
103 | return args;
104 | }
105 |
106 |
107 | private static Hg3Args RequestConvertHg3Args(Game game, IntArgs? intArgs = null) {
108 | Hg3Args args = new Hg3Args() {
109 | Game = game,
110 | };
111 | if (game != null)
112 | Console.WriteLine($"Convert {game.Name()} Hg3s to Pngs:");
113 | else
114 | Console.WriteLine($"Convert Hg3s to Pngs:");
115 |
116 | bool parseSuccess;
117 |
118 | string defInputDir = settings.Directories.IntDirectory;
119 | string defOutputDir = settings.Directories.Hg3Directory;
120 | if (game == Game.All) {
121 | defInputDir = ".";
122 | }
123 | else if (game != null) {
124 | defInputDir = Path.Combine(game.Name(), defInputDir);
125 | defOutputDir = Path.Combine(game.Name(), defOutputDir);
126 | }
127 | if (!intArgs.HasValue) {
128 | do {
129 | if (game == Game.All) {
130 | defInputDir = ".";
131 | Console.Write("Input Directory (Before game name): ");
132 | WriteWatermark("");
133 | }
134 | else {
135 | Console.Write("Input Directory: ");
136 | WriteWatermark(defInputDir);
137 | }
138 | args.InputDir = ReadDirectory(defInputDir, out parseSuccess);
139 | } while (!parseSuccess);
140 |
141 | if (game == Game.All) {
142 | defInputDir = settings.Directories.IntDirectory;
143 | do {
144 | Console.Write("Input Directory (After game name): ");
145 | WriteWatermark(defInputDir);
146 | args.InputDirAfter = ReadRelativePath(defInputDir, out parseSuccess);
147 | } while (!parseSuccess);
148 | }
149 | }
150 | else {
151 | args.InputDir = intArgs.Value.OutputDir;
152 | args.InputDirAfter = intArgs.Value.OutputDirAfter;
153 | }
154 |
155 | /*do {
156 | Console.Write("Output Directory: ");
157 | WriteWatermark(defOutputDir);
158 | args.OutputDir = ReadDirectory(defOutputDir, out parseSuccess);
159 | } while (!parseSuccess);*/
160 |
161 | do {
162 | if (game == Game.All) {
163 | defOutputDir = ".";
164 | Console.Write("Output Directory (Before game name): ");
165 | WriteWatermark("");
166 | }
167 | else {
168 | Console.Write("Output Directory: ");
169 | WriteWatermark(defOutputDir);
170 | }
171 | args.OutputDir = ReadDirectory(defOutputDir, out parseSuccess);
172 | } while (!parseSuccess);
173 |
174 | if (game == Game.All) {
175 | defOutputDir = settings.Directories.Hg3Directory;
176 | do {
177 | Console.Write("Output Directory (After game name): ");
178 | WriteWatermark(defOutputDir);
179 | args.OutputDirAfter = ReadRelativePath(defOutputDir, out parseSuccess);
180 | } while (!parseSuccess);
181 | }
182 |
183 | do {
184 | Console.Write("Search Pattern: ");
185 | WriteWatermark("(none)");
186 | args.Pattern = ReadPattern("", out parseSuccess);
187 | } while (!parseSuccess);
188 |
189 | do {
190 | Console.Write("Sorting (sorted/unsorted/both): ");
191 | WriteWatermark("sorted");
192 | args.Sorting = ReadSorting(Hg3Sorting.Sorted, out parseSuccess);
193 | } while (!parseSuccess);
194 |
195 | do {
196 | Console.Write("Stop on Error (y/n): ");
197 | WriteWatermark("no");
198 | args.StopOnError = ReadYesNo(false, out parseSuccess);
199 | } while (!parseSuccess);
200 |
201 |
202 | return args;
203 | }
204 |
205 |
206 | private static PngArgs RequestResortPngArgs(Game game) {
207 | PngArgs args = new PngArgs() {
208 | Game = game,
209 | };
210 | if (game != null)
211 | Console.WriteLine($"Resort {game.Name()} Pngs:");
212 | else
213 | Console.WriteLine($"Resort Pngs:");
214 | WriteWarning("This will attempt to resort EVERY png found in the specified directory. " +
215 | "Make extra sure that you do not input the wrong directory.");
216 | Console.WriteLine();
217 |
218 | bool parseSuccess;
219 |
220 | string defOutputDir = settings.Directories.Hg3Directory;
221 | if (game == Game.All) {
222 | }
223 | else if (game != null) {
224 | defOutputDir = Path.Combine(game.Name(), defOutputDir);
225 | }
226 | do {
227 | if (game == Game.All) {
228 | defOutputDir = ".";
229 | Console.Write("Resort Directory (Before game name): ");
230 | WriteWatermark("");
231 | }
232 | else {
233 | Console.Write("Resort Directory: ");
234 | WriteWatermark(defOutputDir);
235 | }
236 | args.ResortDir = ReadDirectory(defOutputDir, out parseSuccess);
237 | } while (!parseSuccess);
238 |
239 | if (game == Game.All) {
240 | defOutputDir = settings.Directories.Hg3Directory;
241 | do {
242 | Console.Write("Resort Directory (After game name): ");
243 | WriteWatermark(defOutputDir);
244 | args.ResortDirAfter = ReadRelativePath(defOutputDir, out parseSuccess);
245 | } while (!parseSuccess);
246 | }
247 |
248 | return args;
249 | }
250 |
251 | private static string ReadLine() {
252 | Console.ForegroundColor = ConsoleColor.White;
253 | string line = Console.ReadLine();
254 | ResetForegroundColor();
255 | return line;
256 | }
257 |
258 | private static Hg3Sorting ReadSorting(Hg3Sorting? defaultValue, out bool parseSuccess) {
259 | string input = ReadLine().Trim();
260 | parseSuccess = true;
261 | if (string.IsNullOrWhiteSpace(input)) {
262 | if (defaultValue.HasValue)
263 | return defaultValue.Value;
264 | WriteError("Input cannot be empty!");
265 | }
266 | else {
267 | if (input.Equals2("sorted", true) ||
268 | input.Equals2("sort", true) ||
269 | input.Equals2("s", true))
270 | return Hg3Sorting.Sorted;
271 | else if (input.Equals2("unsorted", true) ||
272 | input.Equals2("unsort", true) ||
273 | input.Equals2("u", true))
274 | return Hg3Sorting.Unsorted;
275 | else if (input.Equals2("both", true) ||
276 | input.Equals2("b", true))
277 | return Hg3Sorting.Both;
278 | WriteError("Input is not in 'sorted/unsorted/both' format!");
279 | }
280 | parseSuccess = false;
281 | return Hg3Sorting.None;
282 | }
283 |
284 | private static string ReadPattern(string defaultValue, out bool parseSuccess) {
285 | string input = ReadLine().Trim().RemoveQuotes();
286 | parseSuccess = true;
287 | if (string.IsNullOrWhiteSpace(input)) {
288 | if (defaultValue != null)
289 | return defaultValue;
290 | WriteError("Input cannot be empty!");
291 | }
292 | else {
293 | if (PathHelper.IsValidNamePattern(input))
294 | return input;
295 | WriteError("Input is not a valid path!");
296 | }
297 | parseSuccess = false;
298 | return "";
299 | }
300 |
301 | private static string ReadRelativePath(string defaultValue, out bool parseSuccess) {
302 | string input = ReadLine().Trim().RemoveQuotes().Trim();
303 | parseSuccess = true;
304 | if (string.IsNullOrWhiteSpace(input)) {
305 | if (defaultValue != null)
306 | return defaultValue;
307 | WriteError("Input cannot be empty!");
308 | }
309 | else {
310 | if (PathHelper.IsValidPathPattern(input))
311 | return input;
312 | WriteError("Input is not a valid path!");
313 | }
314 | parseSuccess = false;
315 | return "";
316 | }
317 |
318 | private static string ReadDirectory(string defaultValue, out bool parseSuccess) {
319 | string input = ReadLine().Trim().RemoveQuotes().Trim();
320 | parseSuccess = true;
321 | if (string.IsNullOrWhiteSpace(input)) {
322 | if (defaultValue != null)
323 | return defaultValue;
324 | WriteError("Input cannot be empty!");
325 | }
326 | else {
327 | if (PathHelper.IsValidDirectory(input))
328 | return input;
329 | WriteError("Input is not a valid path!");
330 | }
331 | parseSuccess = false;
332 | return "";
333 | }
334 |
335 | private static bool ReadYesNo(bool? defaultValue, out bool parseSuccess) {
336 | string input = ReadLine().Trim();
337 | parseSuccess = true;
338 | if (string.IsNullOrWhiteSpace(input)) {
339 | if (defaultValue.HasValue)
340 | return defaultValue.Value;
341 | WriteError("Input cannot be empty!");
342 | }
343 | else {
344 | if (input.Equals2("yes", true) || input.Equals2("y", true))
345 | return true;
346 | else if (input.Equals2("no", true) || input.Equals2("n", true))
347 | return false;
348 | WriteError("Input is not in yes/no format!");
349 | }
350 | parseSuccess = false;
351 | return false;
352 | }
353 | }
354 | }
355 |
--------------------------------------------------------------------------------
/GrisaiaExtractorConsole/Program.Output.cs:
--------------------------------------------------------------------------------
1 | using GrisaiaExtractor;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Reflection;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 |
11 | namespace GrisaiaExtractorConsole {
12 | static partial class Program {
13 |
14 | private static void WriteLog(LogInfo log, bool complete) {
15 | if (complete)
16 | Console.WriteLine("Ripping Finished!");
17 | if (log.GamesComplete > 0)
18 | Console.WriteLine($"Games Completed: {log.GamesComplete}");
19 | if (log.GamesWithErrors.Any()) {
20 | Console.WriteLine($"Games Failed: {log.GamesFailed.Count}");
21 | if (complete)
22 | WriteGames(log.GamesFailed);
23 | }
24 | if (log.GamesWithErrors.Any()) {
25 | Console.WriteLine($"Games with Errors: {log.GamesWithErrors.Count}");
26 | if (complete)
27 | WriteGames(log.GamesWithErrors);
28 | }
29 | if (log.OperationsComplete > 0) {
30 | string operations = "operation";
31 | if (log.OperationsComplete > 1)
32 | operations += 's';
33 | if (complete && log.OperationsComplete > 1)
34 | Console.Write($"All {log.OperationsComplete} ");
35 | else if (!complete && log.OperationsComplete == 1)
36 | Console.Write($"Previous ");
37 | else if (!complete && log.OperationsComplete > 1)
38 | Console.Write($"{log.OperationsComplete} previous ");
39 | Console.WriteLine($"{operations} took: {log.Ellapsed.ToString(@"hh\:mm\:ss")}");
40 | }
41 | }
42 |
43 | private static void LogOperation(IntArgs args, LogInfo log) {
44 |
45 | }
46 |
47 | private static void LogDateTime(LogInfo log) {
48 | log.Write($"[{DateTime.Now}] ");
49 | }
50 |
51 | private static void LogMessage(LogInfo log, string message, Game game = null) {
52 | log.Write($"[{DateTime.Now}] ");
53 | log.WriteLine(message);
54 | if (game != null && game != Game.All)
55 | log.WriteLine($"Game: {game.Name()}");
56 | }
57 |
58 | private static string Name(this Game game) =>
59 | game.Name(settings.General.UseJapaneseNames);
60 |
61 |
62 | private static void WriteWatermark(string watermark) {
63 | int left = Console.CursorLeft;
64 | int top = Console.CursorTop;
65 | Console.ForegroundColor = ConsoleColor.DarkGray;
66 | Console.Write(watermark);
67 | Console.CursorLeft = left;
68 | Console.CursorTop = top;
69 | ResetForegroundColor();
70 | }
71 |
72 | private static void WriteError(string message) {
73 | if (Console.CursorLeft != 0)
74 | Console.WriteLine();
75 | Console.ForegroundColor = ConsoleColor.Red;
76 | Console.WriteLine($"Error: {message}");
77 | ResetForegroundColor();
78 | }
79 |
80 | private static void WriteWarning(string message) {
81 | if (Console.CursorLeft != 0)
82 | Console.WriteLine();
83 | Console.ForegroundColor = ConsoleColor.Yellow;
84 | Console.WriteLine($"Warning: {message}");
85 | ResetForegroundColor();
86 | }
87 |
88 | private static void WriteError(Exception ex) {
89 | if (Console.CursorLeft != 0)
90 | Console.WriteLine();
91 | Console.ForegroundColor = ConsoleColor.Red;
92 | string message = ex.Message;
93 | if (Debugger.IsAttached)
94 | message = ex.ToString();
95 | Console.WriteLine($"Error: {message}");
96 | ResetForegroundColor();
97 | }
98 |
99 | private static void DrawLogo() {
100 | Assembly assembly = typeof(AsciiImage).Assembly;
101 | using (Stream stream = assembly.GetManifestResourceStream(
102 | $"GrisaiaExtractorConsole.grisaia.ascii"))
103 | {
104 | AsciiImage logo = AsciiImage.FromStream(stream);
105 | if (Console.CursorLeft != 0)
106 | Console.WriteLine();
107 | logo.Draw();
108 | }
109 | }
110 |
111 | private static void WriteIntProgress(int line, TimeSpan ellapsed) {
112 | Console.CursorLeft = 0;
113 | Console.CursorTop = line;
114 | Console.Write($"[{ellapsed.ToString(@"hh\:mm\:ss")}]");
115 | }
116 |
117 | private static void WriteProgress(int line, ref int lastLineLength, Hgx2pngArgs args) {
118 | Console.CursorLeft = 0;
119 | Console.CursorTop = line;
120 | string newLine =
121 | $"[{args.Percent.ToString("00.00")}%]" +
122 | $"[{Math.Min(args.FileCount, args.FileIndex + 1)}/{args.FileCount}]" +
123 | $"[{args.Ellapsed.ToString(@"hh\:mm\:ss")}]" +
124 | $" {args.FileName}";
125 | if (newLine.Length > Console.BufferWidth)
126 | newLine = newLine.Substring(0, Console.BufferWidth);
127 | if (lastLineLength > newLine.Length)
128 | newLine += new string(' ', lastLineLength - newLine.Length);
129 | lastLineLength = newLine.Length;
130 | Console.Write(newLine);
131 |
132 | // Display the number of errors if there are any
133 | if (args.TotalErrors > 0) {
134 | Console.CursorLeft = 0;
135 | Console.CursorTop = line + 1;
136 | Console.ForegroundColor = ConsoleColor.Red;
137 | Console.Write($"Errors: {args.TotalErrors}");
138 | ResetForegroundColor();
139 | }
140 | }
141 |
142 | private static void WriteProgress(int line, ref int lastLineLength, ExkifintArgs args) {
143 | Console.CursorLeft = 0;
144 | Console.CursorTop = line;
145 | string newLine =
146 | $"[{args.Percent.ToString("00.00")}%]" +
147 | $"[{Math.Min(args.FileCount, args.FileIndex + 1)}/{args.FileCount}]" +
148 | $"[{args.Ellapsed.ToString(@"hh\:mm\:ss")}]" +
149 | $" {args.FileName}";
150 | if (newLine.Length > Console.BufferWidth)
151 | newLine = newLine.Substring(0, Console.BufferWidth);
152 | if (lastLineLength > newLine.Length)
153 | newLine += new string(' ', lastLineLength - newLine.Length);
154 | lastLineLength = newLine.Length;
155 | Console.Write(newLine);
156 | }
157 |
158 | private static void Beep() {
159 | if (settings.General.BeepAfterOperation)
160 | Console.Beep();
161 | }
162 |
163 | private static void Beep(int frequency, int duration) {
164 | if (settings.General.BeepAfterOperation)
165 | Console.Beep(frequency, duration);
166 | }
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/GrisaiaExtractorConsole/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Resources;
2 | using System.Reflection;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("Grisaia Extract")]
10 | [assembly: AssemblyDescription("A ripping & categorizing tool for Grisaia resources. (Ripping code by asmodean)")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("Trigger's Tools & Games")]
13 | [assembly: AssemblyProduct("GrisaiaExtract")]
14 | [assembly: AssemblyCopyright("Copyright © Robert Jordan 2018")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 |
18 | // Setting ComVisible to false makes the types in this assembly not visible
19 | // to COM components. If you need to access a type in this assembly from
20 | // COM, set the ComVisible attribute to true on that type.
21 | [assembly: ComVisible(false)]
22 |
23 | // The following GUID is for the ID of the typelib if this project is exposed to COM
24 | [assembly: Guid("1b2d824a-dd0d-4019-b234-54e5543b7a42")]
25 |
26 | // Version information for an assembly consists of the following four values:
27 | //
28 | // Major Version
29 | // Minor Version
30 | // Build Number
31 | // Revision
32 | //
33 | // You can specify all the values or you can default the Build and Revision Numbers
34 | // by using the '*' as shown below:
35 | // [assembly: AssemblyVersion("1.0.*")]
36 | [assembly: AssemblyVersion("1.0.2.2")]
37 | [assembly: AssemblyFileVersion("1.0.2.2")]
38 | [assembly: NeutralResourcesLanguage("en")]
39 |
40 |
--------------------------------------------------------------------------------
/GrisaiaExtractorConsole/UserSettings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Reflection;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using GrisaiaExtractor;
10 | using GrisaiaExtractorConsole.Ini;
11 |
12 | namespace GrisaiaExtractorConsole {
13 | /// The user settings for Zelda Oracle Engine gameplay.
14 | public class UserSettings : IniReflectionSettings {
15 |
16 | //-----------------------------------------------------------------------------
17 | // Override Methods
18 | //-----------------------------------------------------------------------------
19 |
20 | /// Called after loading finishes only if the load was unsuccessful.
21 | protected override void PostLoadFailed(Exception ex) {
22 | // TODO: Log error here
23 | }
24 |
25 | /// Called after saving finishes only if the save was unsuccessful.
26 | protected override void PostSaveFailed(Exception ex) {
27 | Console.ForegroundColor = ConsoleColor.Red;
28 | Console.WriteLine("Faied to save ini settings!");
29 | Console.ForegroundColor = ConsoleColor.Gray;
30 | // TODO: Log error here
31 | }
32 |
33 |
34 | //-----------------------------------------------------------------------------
35 | // Override Properties
36 | //-----------------------------------------------------------------------------
37 |
38 | /// The path to the settings file.
39 | protected override string SettingsPath {
40 | get { return PathHelper.CombineExecutable($"{PathHelper.ExeName}.ini"); }
41 | }
42 |
43 | /// The comments to display at the top of the ini file.
44 | protected override string HeaderComments {
45 | get {
46 | return
47 | @" `s- " + '\n' +
48 | @" `y- " + '\n' +
49 | @" ``.--.-:::h/---.``` " + '\n' +
50 | @" .:/+++oo+///+osyssy+/:::::-. " + '\n' +
51 | @" `/o/:///++-do+++o+///+ooooo+++/:-` " + '\n' +
52 | @" -s-`ohyyyy.`hssoooossoossosysso++/:` " + '\n' +
53 | @" `s. :hs+//sh-hyhsoohhoshhyhyyhhyy++/:` " + '\n' +
54 | @" :s` +y+/sssyyyydy+ /// /ddddddhhhyso/- " + '\n' +
55 | @" -s` /y++yso. /sdds .ddhdddddddddhyys+:` " + '\n' +
56 | @" ++`.ys++sh. sdhds /ddddddddddddddhso/` " + '\n' +
57 | @" .os/-/oo+:o.sddo: -+sdddddddddddhhyo/` " + '\n' +
58 | @" `/+osssyyhhyhhdddddddddddddddddhhyyo/` " + '\n' +
59 | @" :/+++ooosyyyhh+:../++/-./dddddhhys+- " + '\n' +
60 | @" ./++ooossyyyyhds .dddhd:-dddddhhys/` " + '\n' +
61 | @" -++oosyyyhyhhds .dd+-dh+dyoooohosss+ " + '\n' +
62 | @" -+oosyyyyhyhds``+:`-dhdddy/`/d+/ys: " + '\n' +
63 | @" .+ssyyhhhhhds`.ddo:md+hdddy.-od- " + '\n' +
64 | @" `:oyyhhhhhds.-ddddms.hmdd+o+-oy:` " + '\n' +
65 | @" ./sydddo/--ooo+/--dh+:/yy/-/oh." + '\n' +
66 | @" `.-/+ooooooooo+//ooo++ooo+:`" + '\n' +
67 | @" " + '\n' +
68 | @" GRISAIA EXTRACT SETTINGS " + '\n' +
69 | @"===================================================================" + '\n' +
70 | @"These are all the settings for Grisaia Extract that cannot be" + '\n' +
71 | @"changed within the program." + '\n' +
72 | @"" + '\n' +
73 | @"ALL RIPPING CODE FOR GRISAIA WAS WRITTEN BY ASMODEAN." + '\n' +
74 | @"Link: http://asmodean.reverse.net/pages/exkifint.html";
75 | }
76 | }
77 |
78 |
79 | //-----------------------------------------------------------------------------
80 | // Ini Sections
81 | //-----------------------------------------------------------------------------
82 |
83 | /// The general settings.
84 | public class GeneralSection {
85 | /// True if JP game names are used instead of US names.
86 | [DefaultValue(true)]
87 | public bool UseJapaneseNames { get; set; }
88 |
89 | /// Beeps after each int or hg3 operation.
90 | [DefaultValue(true)]
91 | public bool BeepAfterOperation { get; set; }
92 |
93 | /// Beeps after all operations are complete.
94 | [DefaultValue(true)]
95 | public bool BeepOnCompletion { get; set; }
96 | }
97 |
98 | /// The custom default directories.
99 | public class DirectoriesSection {
100 | /// The default current directory.
101 | [DefaultValue("")]
102 | [UseQuotes]
103 | public string CurrentDirectory { get; set; }
104 |
105 | /// The default directory ending for .int file output.
106 | [DefaultValue("Raw")]
107 | [UseQuotes]
108 | public string IntDirectory { get; set; }
109 |
110 | /// The default directory ending for .hg3 file output.
111 | [DefaultValue("Output")]
112 | [UseQuotes]
113 | public string Hg3Directory { get; set; }
114 | }
115 |
116 | // Games ----------------------------------------------------------------------
117 |
118 | /// The manual game locations.
119 | public class GameLocationsSection {
120 | /// The Fruit of Grisaia.
121 | [DefaultValue("")]
122 | [UseQuotes]
123 | [Comments("The Fruit of Grisaia")]
124 | public string Kajitsu {
125 | get => Locator.GetPath();
126 | set => Locator.SetPath(value);
127 | }
128 |
129 | /// The Labyrinth of Grisaia.
130 | [DefaultValue("")]
131 | [UseQuotes]
132 | [Comments("The Labyrinth of Grisaia")]
133 | public string Meikyuu {
134 | get => Locator.GetPath();
135 | set => Locator.SetPath(value);
136 | }
137 |
138 | /// The Eden of Grisaia.
139 | [DefaultValue("")]
140 | [UseQuotes]
141 | [Comments("The Eden of Grisaia")]
142 | public string Rakuen {
143 | get => Locator.GetPath();
144 | set => Locator.SetPath(value);
145 | }
146 |
147 | /// The Leisure of Grisaia.
148 | [DefaultValue("")]
149 | [UseQuotes]
150 | [Comments("\nThe Leisure of Grisaia")]
151 | public string Yuukan {
152 | get => Locator.GetPath();
153 | set => Locator.SetPath(value);
154 | }
155 |
156 | /// The Afterglow of Grisaia.
157 | [DefaultValue("")]
158 | [UseQuotes]
159 | [Comments("The Afterglow of Grisaia")]
160 | public string Zankou {
161 | get => Locator.GetPath();
162 | set => Locator.SetPath(value);
163 | }
164 |
165 | /// The Melody of Grisaia.
166 | [DefaultValue("")]
167 | [UseQuotes]
168 | [Comments("The Melody of Grisaia")]
169 | public string Senritsu {
170 | get => Locator.GetPath();
171 | set => Locator.SetPath(value);
172 | }
173 |
174 | /// Idol Magical Girl Chiru Chiru Michiru (Full).
175 | [DefaultValue("")]
176 | [UseQuotes]
177 | [Comments("\nIdol Magical Girl Chiru Chiru Michiru (Full)")]
178 | public string IdolMahouFull {
179 | get => Locator.GetPath();
180 | set => Locator.SetPath(value);
181 | }
182 |
183 | /// Idol Magical Girl Chiru Chiru Michiru (Part 1).
184 | [DefaultValue("")]
185 | [UseQuotes]
186 | [Comments("Idol Magical Girl Chiru Chiru Michiru (Part 1)")]
187 | public string IdolMahouPart1 {
188 | get => Locator.GetPath();
189 | set => Locator.SetPath(value);
190 | }
191 |
192 | /// Idol Magical Girl Chiru Chiru Michiru (Part 2).
193 | [DefaultValue("")]
194 | [UseQuotes]
195 | [Comments("Idol Magical Girl Chiru Chiru Michiru (Part 2)")]
196 | public string IdolMahouPart2 {
197 | get => Locator.GetPath();
198 | set => Locator.SetPath(value);
199 | }
200 |
201 | /// Gets all paths listed by the game locations.
202 | [Browsable(false)]
203 | public IEnumerable> Paths {
204 | get {
205 | foreach (PropertyInfo prop in typeof(GameLocationsSection)
206 | .GetProperties())
207 | {
208 | if (prop.IsBrowsable()) {
209 | yield return new KeyValuePair(
210 | prop.Name, prop.GetValue(this) as string);
211 | }
212 | }
213 | }
214 | }
215 | }
216 |
217 |
218 | //-----------------------------------------------------------------------------
219 | // Ini Properties
220 | //-----------------------------------------------------------------------------
221 |
222 | /// The general settings.
223 | [Section]
224 | public GeneralSection General { get; } = new GeneralSection();
225 |
226 | /// The custom default directories.
227 | [Section]
228 | public DirectoriesSection Directories { get; } = new DirectoriesSection();
229 |
230 | /// The manual game locations.
231 | [Section]
232 | [Comments(@"Override or manual locations for games that could not be found")]
233 | public GameLocationsSection GameLocations { get; } = new GameLocationsSection();
234 |
235 | }
236 | }
237 |
--------------------------------------------------------------------------------
/GrisaiaExtractorConsole/grisaia.ascii:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trigger-segfault/GrisaiaExtractor/fdd6e8339fd4e69a0c6fc92acb7aa57000b6b81c/GrisaiaExtractorConsole/grisaia.ascii
--------------------------------------------------------------------------------
/License.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Robert Jordan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # Grisaia Extract 
2 |
3 | [](https://github.com/trigger-death/GrisaiaExtractor/releases/latest)
4 | [](https://github.com/trigger-death/GrisaiaExtractor/releases/latest)
5 | [](https://github.com/trigger-death/GrisaiaExtractor/releases)
6 | [](https://github.com/trigger-death/GrisaiaExtractor/commit/2ae789f18d7387024f2b92b85cc6a21709796ed7)
7 | [](https://discord.gg/vB7jUbY)
8 |
9 | A ripping tool (Primarily for images) for the Grisaia games. *(Phantom Trigger not supported)*
10 |
11 | This is basically a polished, easy-to-use wrapper for existing programs that extract Grisaia files. (Although much of the original code has been ported to C#)
12 |
13 | **All ripping code written by asmodean:** http://asmodean.reverse.net/pages/exkifint.html
14 |
15 | **Additional thanks to ripping documentation on reddit:** https://www.reddit.com/r/grisaia/wiki/ripping
16 |
17 | I originally planned to turn this into a full-fledged Windows application that would include sprite combining but after realising I wouldn't reach that point, I wrote up a final console version for use instead.
18 |
19 | 
20 |
21 | ### [Image Album](https://imgur.com/a/7xouR3f)
22 |
23 | ## About
24 |
25 | * **Created By:** Robert Jordan
26 | * **Ripping By:** asmodean
27 | * **Language:** C#/C++
28 |
29 | ## Features
30 |
31 | * Designed to be a bit more user friendly than existing tools. Users no longer need to run a program through the command line or write batch files to convert .hg3's.
32 | * Outputs .hg3's directly to .png's with proper transparency. Now an entire int file can be output in one go with disk space to spare.
33 | * Optional ability to sort all images to a categorized directory based on its name.
34 | * Attempts to locate all existing Grisaia games.
35 | * Fixes a bug with `hgx2bmp.exe` where a small selection of .hg3 didn't get all of their images extracted.
36 | * An .ini settings file called `GrisaiaExtract.ini` can be modified after the program is run to modify certain defaults and settings.
37 |
38 | ## Cons
39 |
40 | * Currently no command line support.
41 | * May not play well when not run through a Windows Console.
42 |
43 | **Example of Sorted Images:** *Note, Windows draws folder thumbnails poorly, they do not actually have alpha issues.*
44 |
45 | 
46 |
--------------------------------------------------------------------------------
/zlib/bin/zlib1.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trigger-segfault/GrisaiaExtractor/fdd6e8339fd4e69a0c6fc92acb7aa57000b6b81c/zlib/bin/zlib1.dll
--------------------------------------------------------------------------------
/zlib/include/zconf.h:
--------------------------------------------------------------------------------
1 | /* zconf.h -- configuration of the zlib compression library
2 | * Copyright (C) 1995-2005 Jean-loup Gailly.
3 | * For conditions of distribution and use, see copyright notice in zlib.h
4 | */
5 |
6 | /* @(#) $Id$ */
7 |
8 | #ifndef ZCONF_H
9 | #define ZCONF_H
10 |
11 | /*
12 | * If you *really* need a unique prefix for all types and library functions,
13 | * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
14 | */
15 | #ifdef Z_PREFIX
16 | # define deflateInit_ z_deflateInit_
17 | # define deflate z_deflate
18 | # define deflateEnd z_deflateEnd
19 | # define inflateInit_ z_inflateInit_
20 | # define inflate z_inflate
21 | # define inflateEnd z_inflateEnd
22 | # define deflateInit2_ z_deflateInit2_
23 | # define deflateSetDictionary z_deflateSetDictionary
24 | # define deflateCopy z_deflateCopy
25 | # define deflateReset z_deflateReset
26 | # define deflateParams z_deflateParams
27 | # define deflateBound z_deflateBound
28 | # define deflatePrime z_deflatePrime
29 | # define inflateInit2_ z_inflateInit2_
30 | # define inflateSetDictionary z_inflateSetDictionary
31 | # define inflateSync z_inflateSync
32 | # define inflateSyncPoint z_inflateSyncPoint
33 | # define inflateCopy z_inflateCopy
34 | # define inflateReset z_inflateReset
35 | # define inflateBack z_inflateBack
36 | # define inflateBackEnd z_inflateBackEnd
37 | # define compress z_compress
38 | # define compress2 z_compress2
39 | # define compressBound z_compressBound
40 | # define uncompress z_uncompress
41 | # define adler32 z_adler32
42 | # define crc32 z_crc32
43 | # define get_crc_table z_get_crc_table
44 | # define zError z_zError
45 |
46 | # define alloc_func z_alloc_func
47 | # define free_func z_free_func
48 | # define in_func z_in_func
49 | # define out_func z_out_func
50 | # define Byte z_Byte
51 | # define uInt z_uInt
52 | # define uLong z_uLong
53 | # define Bytef z_Bytef
54 | # define charf z_charf
55 | # define intf z_intf
56 | # define uIntf z_uIntf
57 | # define uLongf z_uLongf
58 | # define voidpf z_voidpf
59 | # define voidp z_voidp
60 | #endif
61 |
62 | #if defined(__MSDOS__) && !defined(MSDOS)
63 | # define MSDOS
64 | #endif
65 | #if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
66 | # define OS2
67 | #endif
68 | #if defined(_WINDOWS) && !defined(WINDOWS)
69 | # define WINDOWS
70 | #endif
71 | #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
72 | # ifndef WIN32
73 | # define WIN32
74 | # endif
75 | #endif
76 | #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
77 | # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
78 | # ifndef SYS16BIT
79 | # define SYS16BIT
80 | # endif
81 | # endif
82 | #endif
83 |
84 | /*
85 | * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
86 | * than 64k bytes at a time (needed on systems with 16-bit int).
87 | */
88 | #ifdef SYS16BIT
89 | # define MAXSEG_64K
90 | #endif
91 | #ifdef MSDOS
92 | # define UNALIGNED_OK
93 | #endif
94 |
95 | #ifdef __STDC_VERSION__
96 | # ifndef STDC
97 | # define STDC
98 | # endif
99 | # if __STDC_VERSION__ >= 199901L
100 | # ifndef STDC99
101 | # define STDC99
102 | # endif
103 | # endif
104 | #endif
105 | #if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
106 | # define STDC
107 | #endif
108 | #if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
109 | # define STDC
110 | #endif
111 | #if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
112 | # define STDC
113 | #endif
114 | #if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
115 | # define STDC
116 | #endif
117 |
118 | #if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
119 | # define STDC
120 | #endif
121 |
122 | #ifndef STDC
123 | # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
124 | # define const /* note: need a more gentle solution here */
125 | # endif
126 | #endif
127 |
128 | /* Some Mac compilers merge all .h files incorrectly: */
129 | #if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
130 | # define NO_DUMMY_DECL
131 | #endif
132 |
133 | /* Maximum value for memLevel in deflateInit2 */
134 | #ifndef MAX_MEM_LEVEL
135 | # ifdef MAXSEG_64K
136 | # define MAX_MEM_LEVEL 8
137 | # else
138 | # define MAX_MEM_LEVEL 9
139 | # endif
140 | #endif
141 |
142 | /* Maximum value for windowBits in deflateInit2 and inflateInit2.
143 | * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
144 | * created by gzip. (Files created by minigzip can still be extracted by
145 | * gzip.)
146 | */
147 | #ifndef MAX_WBITS
148 | # define MAX_WBITS 15 /* 32K LZ77 window */
149 | #endif
150 |
151 | /* The memory requirements for deflate are (in bytes):
152 | (1 << (windowBits+2)) + (1 << (memLevel+9))
153 | that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
154 | plus a few kilobytes for small objects. For example, if you want to reduce
155 | the default memory requirements from 256K to 128K, compile with
156 | make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
157 | Of course this will generally degrade compression (there's no free lunch).
158 |
159 | The memory requirements for inflate are (in bytes) 1 << windowBits
160 | that is, 32K for windowBits=15 (default value) plus a few kilobytes
161 | for small objects.
162 | */
163 |
164 | /* Type declarations */
165 |
166 | #ifndef OF /* function prototypes */
167 | # ifdef STDC
168 | # define OF(args) args
169 | # else
170 | # define OF(args) ()
171 | # endif
172 | #endif
173 |
174 | /* The following definitions for FAR are needed only for MSDOS mixed
175 | * model programming (small or medium model with some far allocations).
176 | * This was tested only with MSC; for other MSDOS compilers you may have
177 | * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
178 | * just define FAR to be empty.
179 | */
180 | #ifdef SYS16BIT
181 | # if defined(M_I86SM) || defined(M_I86MM)
182 | /* MSC small or medium model */
183 | # define SMALL_MEDIUM
184 | # ifdef _MSC_VER
185 | # define FAR _far
186 | # else
187 | # define FAR far
188 | # endif
189 | # endif
190 | # if (defined(__SMALL__) || defined(__MEDIUM__))
191 | /* Turbo C small or medium model */
192 | # define SMALL_MEDIUM
193 | # ifdef __BORLANDC__
194 | # define FAR _far
195 | # else
196 | # define FAR far
197 | # endif
198 | # endif
199 | #endif
200 |
201 | #if defined(WINDOWS) || defined(WIN32)
202 | /* If building or using zlib as a DLL, define ZLIB_DLL.
203 | * This is not mandatory, but it offers a little performance increase.
204 | */
205 | # ifdef ZLIB_DLL
206 | # if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
207 | # ifdef ZLIB_INTERNAL
208 | # define ZEXTERN extern __declspec(dllexport)
209 | # else
210 | # define ZEXTERN extern __declspec(dllimport)
211 | # endif
212 | # endif
213 | # endif /* ZLIB_DLL */
214 | /* If building or using zlib with the WINAPI/WINAPIV calling convention,
215 | * define ZLIB_WINAPI.
216 | * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
217 | */
218 | # ifdef ZLIB_WINAPI
219 | # ifdef FAR
220 | # undef FAR
221 | # endif
222 | # include
223 | /* No need for _export, use ZLIB.DEF instead. */
224 | /* For complete Windows compatibility, use WINAPI, not __stdcall. */
225 | # define ZEXPORT WINAPI
226 | # ifdef WIN32
227 | # define ZEXPORTVA WINAPIV
228 | # else
229 | # define ZEXPORTVA FAR CDECL
230 | # endif
231 | # endif
232 | #endif
233 |
234 | #if defined (__BEOS__)
235 | # ifdef ZLIB_DLL
236 | # ifdef ZLIB_INTERNAL
237 | # define ZEXPORT __declspec(dllexport)
238 | # define ZEXPORTVA __declspec(dllexport)
239 | # else
240 | # define ZEXPORT __declspec(dllimport)
241 | # define ZEXPORTVA __declspec(dllimport)
242 | # endif
243 | # endif
244 | #endif
245 |
246 | #ifndef ZEXTERN
247 | # define ZEXTERN extern
248 | #endif
249 | #ifndef ZEXPORT
250 | # define ZEXPORT
251 | #endif
252 | #ifndef ZEXPORTVA
253 | # define ZEXPORTVA
254 | #endif
255 |
256 | #ifndef FAR
257 | # define FAR
258 | #endif
259 |
260 | #if !defined(__MACTYPES__)
261 | typedef unsigned char Byte; /* 8 bits */
262 | #endif
263 | typedef unsigned int uInt; /* 16 bits or more */
264 | typedef unsigned long uLong; /* 32 bits or more */
265 |
266 | #ifdef SMALL_MEDIUM
267 | /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
268 | # define Bytef Byte FAR
269 | #else
270 | typedef Byte FAR Bytef;
271 | #endif
272 | typedef char FAR charf;
273 | typedef int FAR intf;
274 | typedef uInt FAR uIntf;
275 | typedef uLong FAR uLongf;
276 |
277 | #ifdef STDC
278 | typedef void const *voidpc;
279 | typedef void FAR *voidpf;
280 | typedef void *voidp;
281 | #else
282 | typedef Byte const *voidpc;
283 | typedef Byte FAR *voidpf;
284 | typedef Byte *voidp;
285 | #endif
286 |
287 | #if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
288 | # include /* for off_t */
289 | # include /* for SEEK_* and off_t */
290 | # ifdef VMS
291 | # include /* for off_t */
292 | # endif
293 | # define z_off_t off_t
294 | #endif
295 | #ifndef SEEK_SET
296 | # define SEEK_SET 0 /* Seek from beginning of file. */
297 | # define SEEK_CUR 1 /* Seek from current position. */
298 | # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
299 | #endif
300 | #ifndef z_off_t
301 | # define z_off_t long
302 | #endif
303 |
304 | #if defined(__OS400__)
305 | # define NO_vsnprintf
306 | #endif
307 |
308 | #if defined(__MVS__)
309 | # define NO_vsnprintf
310 | # ifdef FAR
311 | # undef FAR
312 | # endif
313 | #endif
314 |
315 | /* MVS linker does not support external names larger than 8 bytes */
316 | #if defined(__MVS__)
317 | # pragma map(deflateInit_,"DEIN")
318 | # pragma map(deflateInit2_,"DEIN2")
319 | # pragma map(deflateEnd,"DEEND")
320 | # pragma map(deflateBound,"DEBND")
321 | # pragma map(inflateInit_,"ININ")
322 | # pragma map(inflateInit2_,"ININ2")
323 | # pragma map(inflateEnd,"INEND")
324 | # pragma map(inflateSync,"INSY")
325 | # pragma map(inflateSetDictionary,"INSEDI")
326 | # pragma map(compressBound,"CMBND")
327 | # pragma map(inflate_table,"INTABL")
328 | # pragma map(inflate_fast,"INFA")
329 | # pragma map(inflate_copyright,"INCOPY")
330 | #endif
331 |
332 | #endif /* ZCONF_H */
333 |
--------------------------------------------------------------------------------
/zlib/lib/libz.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trigger-segfault/GrisaiaExtractor/fdd6e8339fd4e69a0c6fc92acb7aa57000b6b81c/zlib/lib/libz.a
--------------------------------------------------------------------------------
/zlib/lib/libz.dll.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trigger-segfault/GrisaiaExtractor/fdd6e8339fd4e69a0c6fc92acb7aa57000b6b81c/zlib/lib/libz.dll.a
--------------------------------------------------------------------------------
/zlib/lib/zlib-bcc.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trigger-segfault/GrisaiaExtractor/fdd6e8339fd4e69a0c6fc92acb7aa57000b6b81c/zlib/lib/zlib-bcc.lib
--------------------------------------------------------------------------------
/zlib/lib/zlib.def:
--------------------------------------------------------------------------------
1 | ; h:\mingw\3.3.1\bin\dlltool.exe --export-all-symbols --output-def=zlib.def adler32.pic.o compress.pic.o crc32.pic.o gzio.pic.o uncompr.pic.o deflate.pic.o trees.pic.o zutil.pic.o inflate.pic.o infback.pic.o inftrees.pic.o inffast.pic.o zlib-dllversion.o zlib-dll-res.o
2 | EXPORTS
3 | DllGetVersion @ 1 ;
4 | _dist_code @ 2 DATA ;
5 | _length_code @ 3 DATA ;
6 | _tr_align @ 4 ;
7 | _tr_flush_block @ 5 ;
8 | _tr_init @ 6 ;
9 | _tr_stored_block @ 7 ;
10 | _tr_tally @ 8 ;
11 | adler32 @ 9 ;
12 | adler32_combine @ 10 ;
13 | compress @ 11 ;
14 | compress2 @ 12 ;
15 | compressBound @ 13 ;
16 | crc32 @ 14 ;
17 | crc32_combine @ 15 ;
18 | deflate @ 16 ;
19 | deflateBound @ 17 ;
20 | deflateCopy @ 18 ;
21 | deflateEnd @ 19 ;
22 | deflateInit2_ @ 20 ;
23 | deflateInit_ @ 21 ;
24 | deflateParams @ 22 ;
25 | deflatePrime @ 23 ;
26 | deflateReset @ 24 ;
27 | deflateSetDictionary @ 25 ;
28 | deflateSetHeader @ 26 ;
29 | deflateTune @ 27 ;
30 | deflate_copyright @ 28 DATA ;
31 | get_crc_table @ 29 ;
32 | gzclearerr @ 30 ;
33 | gzclose @ 31 ;
34 | gzdirect @ 32 ;
35 | gzdopen @ 33 ;
36 | gzeof @ 34 ;
37 | gzerror @ 35 ;
38 | gzflush @ 36 ;
39 | gzgetc @ 37 ;
40 | gzgets @ 38 ;
41 | gzopen @ 39 ;
42 | gzprintf @ 40 ;
43 | gzputc @ 41 ;
44 | gzputs @ 42 ;
45 | gzread @ 43 ;
46 | gzrewind @ 44 ;
47 | gzseek @ 45 ;
48 | gzsetparams @ 46 ;
49 | gztell @ 47 ;
50 | gzungetc @ 48 ;
51 | gzwrite @ 49 ;
52 | inflate @ 50 ;
53 | inflateBack @ 51 ;
54 | inflateBackEnd @ 52 ;
55 | inflateBackInit_ @ 53 ;
56 | inflateCopy @ 54 ;
57 | inflateEnd @ 55 ;
58 | inflateGetHeader @ 56 ;
59 | inflateInit2_ @ 57 ;
60 | inflateInit_ @ 58 ;
61 | inflatePrime @ 59 ;
62 | inflateReset @ 60 ;
63 | inflateSetDictionary @ 61 ;
64 | inflateSync @ 62 ;
65 | inflateSyncPoint @ 63 ;
66 | inflate_copyright @ 64 DATA ;
67 | inflate_fast @ 65 ;
68 | inflate_table @ 66 ;
69 | uncompress @ 67 ;
70 | zError @ 68 ;
71 | z_errmsg @ 69 DATA ;
72 | zcalloc @ 70 ;
73 | zcfree @ 71 ;
74 | zlibCompileFlags @ 72 ;
75 | zlibVersion @ 73 ;
76 |
--------------------------------------------------------------------------------
/zlib/lib/zlib.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/trigger-segfault/GrisaiaExtractor/fdd6e8339fd4e69a0c6fc92acb7aa57000b6b81c/zlib/lib/zlib.lib
--------------------------------------------------------------------------------
/zlib/manifest/zlib-1.2.3-lib.mft:
--------------------------------------------------------------------------------
1 | include/zconf.h
2 | include/zlib.h
3 | lib/libz.a
4 | lib/libz.dll.a
5 | lib/zlib-bcc.lib
6 | lib/zlib.def
7 | lib/zlib.lib
8 | manifest/zlib-1.2.3-lib.mft
9 | manifest/zlib-1.2.3-lib.ver
10 |
--------------------------------------------------------------------------------
/zlib/manifest/zlib-1.2.3-lib.ver:
--------------------------------------------------------------------------------
1 | Zlib-1.2.3: Developer files
2 | Zlib: general purpose data compression / decompression library
--------------------------------------------------------------------------------