Compare commits

...

92 Commits

Author SHA1 Message Date
Crsky
c44ab6ae03 fix: Add zh-Hant strings 2026-03-17 20:19:47 +08:00
Crsky
83f4abd211 Merge pull request #179 from love80312/master
Add Traditional Chinese language files
2026-03-17 20:15:27 +08:00
Crsky
0fd41b39f4 Merge pull request #180 from crskycode/feat/support-tlg-ref
feat: Support TLGref
2026-03-17 20:07:13 +08:00
Crsky
75b1799b54 feat: Support TLGref 2026-03-17 20:03:54 +08:00
笙歌
2f424474f5 Merge pull request #1 from love80312/add-zh-hant
Add zh hant
2026-03-17 19:28:34 +08:00
笙歌
43948a6e07 arcStrings.zh-Hant.resx 2026-03-17 19:27:57 +08:00
笙歌
4b003410c5 garStrings.zh-Hant.resx 2026-03-17 19:27:24 +08:00
笙歌
3fe5dadf72 guiStrings.zh-Hant.resx 2026-03-17 19:26:48 +08:00
Crsky
f58958c892 Update packages 2026-03-17 18:31:47 +08:00
Crsky
030d3adbbc Use old SixLabors.ImageSharp 2026-03-17 18:12:05 +08:00
Crsky
f61d08f1d9 Merge pull request #178 from crskycode/fix/xp3-webp-detection
fix: Fix XP3 RIFF detection
2026-03-17 17:32:33 +08:00
Crsky
47c8219417 Merge pull request #174 from crskycode/feat/suppor-tlg-mux-qoi
feat: Support TLG mux qoi
2026-03-17 17:32:00 +08:00
Crsky
bbd7476b6f style: format 2026-03-17 17:29:53 +08:00
Crsky
be1485a429 perf: Use stream decode in DecodeQOI 2026-03-17 17:12:41 +08:00
Crsky
94b6bc22f0 fix: Fix XP3 RIFF detection 2026-03-17 16:35:26 +08:00
Crsky
387d6110ce fix: Add argument check 2026-03-17 11:05:12 +08:00
Crsky
60b0f0bf40 feat: Add TLG mux qoi archive 2026-03-17 10:44:30 +08:00
Crsky
bb2c831206 feat: Support multi-layer qoi 2026-03-17 09:41:29 +08:00
Crsky
efbabb0ab3 Merge pull request #177 from akiWagashi/master
Add supprot for SimpleCrypt32 of Entis
2026-03-15 14:46:33 +08:00
akiWagashi
89a617854d Update code style 2026-03-15 12:09:31 +08:00
akiWagashi
3ba4ef5e4e Add supprot for SimpleCrypt32 of Entis 2026-03-15 01:09:55 +08:00
Crsky
cd548330a9 feat: Support TLGqoi file 2026-03-14 02:26:39 +08:00
Crsky
c4d3c71513 feat: Support TLG mux qoi 2026-03-13 23:58:37 +08:00
Crsky
612eb2d0ad (Entis): Support ERISACrypt 2026-03-10 14:43:26 +08:00
Crsky
ed4ff6de9a Update BCnEncoder.Net package 2026-03-06 10:57:23 +08:00
Crsky
1e6fc9c810 Remove local nuget package source 2026-03-06 10:56:57 +08:00
Crsky
89aebd6ff0 Merge pull request #167 from akiWagashi/master
Add support for new Circus Voice.dat format
2026-03-01 15:08:28 +08:00
akiWagashi
42d4c33a0b Add support for new Circus Voice.dat format
Delete unused namespace
2026-03-01 13:56:47 +08:00
Crsky
3beec0e668 Update header comment 2026-03-01 03:37:28 +08:00
Crsky
3de2e98d8d Add local package BCnEncoder.Net 2026-03-01 03:34:30 +08:00
Crsky
fe0e34c7f3 Add nuget local source configuration 2026-03-01 03:34:03 +08:00
Crsky
801b93aed4 feat: Support Khronos texture format 2026-03-01 03:32:40 +08:00
Crsky
52205b50b3 Update App.config 2026-03-01 03:30:56 +08:00
Crsky
ce4e36ff8a Merge pull request #166 from crskycode/net472
Migrate to .NET Framework 4.7.2
2026-02-28 19:48:43 +08:00
Crsky
654d25c765 Update translation 2026-02-28 12:52:02 +08:00
Crsky
deafc0729b Update README.md 2026-02-28 12:20:33 +08:00
Crsky
c030a1301f Fix IsTextBoxFocused property name 2026-02-28 12:11:54 +08:00
Crsky
6e8372ed69 Change main window title 2026-02-28 12:11:16 +08:00
Crsky
4e58bf3c96 Update build.yml 2026-02-28 11:43:01 +08:00
Crsky
d5a32a2058 Add SixLabors.ImageSharp 2026-02-28 11:37:21 +08:00
Crsky
d121f9b701 Copy libwebp native library files to output directory 2026-02-28 11:35:26 +08:00
Crsky
8de8332f20 Remove zstd native library files 2026-02-28 11:29:58 +08:00
Crsky
5157d43ebc Use ZstdSharp 2026-02-28 11:25:17 +08:00
Crsky
b5ce23cd71 Update App.config 2026-02-28 11:16:40 +08:00
Crsky
7e9da65cf1 Use ZstdSharp 2026-02-28 11:16:25 +08:00
Crsky
dc813737b4 Fix SharpZip.StringCodec warning 2026-02-28 11:00:49 +08:00
Crsky
9e6286d29a Update packages 2026-02-28 10:51:58 +08:00
Crsky
99707c57fd Compile SchemeTool 2026-02-28 10:21:26 +08:00
Crsky
a9b7ce49d0 Compile GARbro.GUI 2026-02-28 10:20:05 +08:00
Crsky
3719f65e1b Compile Legacy 2026-02-28 10:08:56 +08:00
Crsky
cd786726ec Compile Experimental 2026-02-28 10:06:42 +08:00
Crsky
9463157541 Compile ArcFormats 2026-02-28 09:55:46 +08:00
Crsky
2a82e2e4e3 Compile GameRes 2026-02-28 09:42:58 +08:00
Crsky
51e14b9291 Clean 2026-02-28 09:38:23 +08:00
Crsky
9f5be71846 Update README.md 2026-02-28 07:53:27 +08:00
Crsky
d0211f01bf Merge pull request #165 from zzwbdz/patch-4
Update download link to new release repository
2026-02-28 07:51:47 +08:00
Crsky
74011aa4e7 Merge pull request #164 from MLChinoo/master
Add Support: "Dracu-Riot! [Steam]"
2026-02-28 07:49:48 +08:00
zzwbdz
e580bc00bc Update download link to new release repository 2026-02-28 03:31:49 +08:00
MLChinoo
72088c2da3 feat: initial support for "Dracu-Riot! [Steam]" 2026-02-27 22:01:37 +08:00
Crsky
d132f95b4a style: Keep GARbro code style 2026-02-16 23:46:10 +08:00
zzwbdz
04cce56ab8 Add Repack support for ELF (.ArcAi6win)
Only tested on the ELF's Ai6win engine game "媚肉の香り," the repackaged .arc files can be read normally by the game, theoretically supporting all ELF's Ai6win engine games.
But it may not support .arc files of Silky and Silky Plus.

Silky and Silky Plus are derivative brands of ELF, ELF has gone bankrupt, but Silky Plus has survived to this day.

Games from the three brands share a set of unpacking logic, but it is not yet clear whether Silky and Silky Plus have encrypted .arc files afterward.
2026-02-15 01:41:55 +08:00
Crsky
d7a1f910ea feat: Add Frontier Works engine image format support 2026-02-10 08:30:57 +08:00
Crsky
a0b9084978 feat: Add Frontier Works engine resource archive support 2026-02-10 08:03:59 +08:00
Crsky
4159c888c9 Merge pull request #160 from gopicolo/feature/leaf-repack
Add Repack support for Leaf/Aquaplus (.pak)
2026-02-06 23:12:01 +08:00
gopicolo
99cc04c3a6 Add Repack support for Leaf/Aquaplus (.pak) 2026-02-05 21:34:49 -03:00
Crsky
66e4e40bff fix: Add offset check 2026-02-02 20:01:10 +08:00
Crsky
5893179d92 fix: Add offset check 2026-02-02 19:58:20 +08:00
Crsky
e5ffd784c5 feat: Add Edoire's resource archive 2026-02-02 19:30:03 +08:00
Crsky
4bc4ecb909 Add support "Daunya-san to Kainushi-kun" 2026-02-02 18:00:19 +08:00
Crsky
1bdeddbab0 Merge pull request #159 from MishaIac/master
Add support for NEKO WORKs Unity PACK/EXFS resource archive
2026-02-02 07:30:21 +08:00
MishaIac
181dd3a724 Add support for NEKO WORKs Unity PACK/EXFS resource archive
Tested on Nie no Hakoniwa (Steam version)
2026-02-01 13:14:09 +02:00
nanami5270
d162a02e59 Add support "Hanagane Kanade * Gram - Chapter:4 Ayase Kanade" 2026-01-30 17:27:17 +08:00
Crsky
214f09befb Merge pull request #158 from gopicolo/feature/psp-gim-support
Add PSP GIM support and support for guyzware Inc psp visual novels
2026-01-28 01:54:43 +08:00
gopicolo
fce112d99b Fix typo in Guyzware description 2026-01-27 13:48:13 -03:00
gopicolo
2dd7052e02 Fix typo in Guyzware description 2026-01-27 13:45:25 -03:00
gopicolo
31a1a4f42f Add PSP GIM support and support for guyzware Inc psp visual novels 2026-01-27 01:07:48 -03:00
nanami5270
9647b68729 Merge branch 'scientificworld-master' 2026-01-27 02:42:01 +08:00
nanami5270
ed1b39efdd Merge branch 'master' of https://github.com/scientificworld/GARbro-Mod into scientificworld-master 2026-01-27 02:41:39 +08:00
Crsky
ede00c430f Merge pull request #157 from gopicolo/new-formats
Add support for Kid P2T files, Tim files, Broccoli Pak/GRP/MPEG and Leaf Video
2026-01-27 00:08:08 +08:00
gopicolo
85c6ccfea9 Add support for Kid P2T files, Broccoli Pak/GRP/MPEG and Leaf Video 2026-01-26 11:53:30 -03:00
scientificworld
53395b5453 chore: update database 2026-01-26 19:40:26 +08:00
scientificworld
54023174b6 fix: add .exe extension to EVB to fix priority
See implementation of FormatCatalog.Instance.FindFormats<ArchiveFormat> for details.
2026-01-26 19:25:28 +08:00
nanami5270
2e89ad5832 (HZC): fix missing Dispose 2026-01-26 15:26:25 +08:00
nanami5270
dba750ba39 (Favorite): support TLG format within HZC 2026-01-26 15:13:38 +08:00
scientificworld
c1bef5d0b2 Merge remote-tracking branch 'add-catsystem-arc-zt' 2026-01-26 13:21:58 +08:00
nanami5270
c77112e586 Add support "Kioku no Kenban" 2026-01-26 06:26:35 +08:00
scientificworld
57a5e2a79c feat: support IRISPCK used by CatSystem Android
It appears that red<=>blue channel swapping is needed for hg3 images contained in this type of archives.
2026-01-25 23:53:46 +08:00
scientificworld
7c47c64083 feat: support FOG archive 2026-01-25 14:52:09 +08:00
scientificworld
718f255b25 Merge branch 'dev' 2026-01-24 01:28:15 +08:00
scientificworld
8c2746084b feat: support AGES mkII archive and audio
TODO: epk decrypt, raw PCM support
2026-01-19 15:12:35 +08:00
scientificworld
87195d8673 feat: support compressed and embedded EVB package
There might be a conflict with Experimental/Microsoft/ArcEXE.cs. Maybe add a option later to disable that?
2026-01-18 10:10:35 +08:00
Robert Jordan
3f5795a5e0 implemented '.zt' archives.
Add CatSystem2 `.zt` extension archive format (*CatSystem2 pack file*).

* Usage: Extras/export pack files for CatSystem2 - often used to save wallpapers, wav files, or other extras to the user's computer.
* Tag: `ZT/PACK` (chosen over *just* `ZT`, based on the devkit tool name: `ztpack.exe`, which also describes it as a *"pack file"*).
* Extension: `*.zt` (found in `export.int` archive).
* Signature: No file signature of any kind, immediately starts with an entry structure. A lot of sanity checks have been added.
* Hierarchic: Yes, although this is rarely used, and CS2's implementation is rather buggy.
    * Buggy enough that Frontwing gave up and started putting zip files **into** zt files!
	* The specification at least, is still well defined.
* Archive layout is the standard offset-next approach seen in other CS2 formats. But there's two offset-next fields, one for subdirectory entries, and one for the next flat (current) directory entry.
    * Folders have their own entries, which are what point to child file entries.
2021-05-25 22:44:41 -04:00
80 changed files with 5242 additions and 486 deletions

View File

@@ -15,7 +15,7 @@ jobs:
run: nuget restore
# Build the solution
- name: Build
run: msbuild /p:Configuration=Release /p:Platform="Any CPU" /p:TargetFrameworkVersion=v4.6.2 GARbro.sln
run: msbuild /p:Configuration=Release /p:Platform="Any CPU" GARbro.sln
# Publish the artifacts
- name: Publish Artifact
if: success()

View File

@@ -89,8 +89,8 @@ namespace GameRes.Formats.AirNovel
SharpZip.ZipFile zip = null;
try
{
SharpZip.ZipStrings.CodePage = Encoding.UTF8.CodePage;
zip = new SharpZip.ZipFile (input);
var sc = SharpZip.StringCodec.FromCodePage (Encoding.UTF8.CodePage);
zip = new SharpZip.ZipFile (input, false, sc);
var files = zip.Cast<SharpZip.ZipEntry>().Where (z => !z.IsDirectory);
bool has_encrypted = false;
var dir = new List<Entry>();

View File

@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>GameRes.Formats</RootNamespace>
<AssemblyName>ArcFormats</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
@@ -51,61 +51,95 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Crc32C.NET, Version=1.0.5.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Crc32C.NET.1.0.5.0\lib\net20\Crc32C.NET.dll</HintPath>
<Reference Include="BCnEncoder, Version=2.3.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\BCnEncoder.Net.2.3.0\lib\netstandard2.0\BCnEncoder.dll</HintPath>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=1.3.3.11, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.1.3.3\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
<Reference Include="CommunityToolkit.HighPerformance, Version=8.4.0.0, Culture=neutral, PublicKeyToken=4aff67a105548ee2, processorArchitecture=MSIL">
<HintPath>..\packages\CommunityToolkit.HighPerformance.8.4.0\lib\netstandard2.0\CommunityToolkit.HighPerformance.dll</HintPath>
</Reference>
<Reference Include="NAudio">
<HintPath>..\packages\NAudio.1.7.3\lib\net35\NAudio.dll</HintPath>
<Reference Include="ICSharpCode.SharpZipLib, Version=1.4.2.13, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.1.4.2\lib\netstandard2.0\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="NVorbis, Version=0.10.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NVorbis.0.10.4\lib\net45\NVorbis.dll</HintPath>
<Reference Include="K4os.Compression.LZ4, Version=1.3.8.0, Culture=neutral, PublicKeyToken=2186fa9121ef231d, processorArchitecture=MSIL">
<HintPath>..\packages\K4os.Compression.LZ4.1.3.8\lib\net462\K4os.Compression.LZ4.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.HashCode, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.HashCode.6.0.0\lib\net462\Microsoft.Bcl.HashCode.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.Numerics, Version=10.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.Numerics.10.0.5\lib\net462\Microsoft.Bcl.Numerics.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Win32.Registry, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll</HintPath>
</Reference>
<Reference Include="NAudio, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.2.2.1\lib\net472\NAudio.dll</HintPath>
</Reference>
<Reference Include="NAudio.Asio, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.Asio.2.2.1\lib\netstandard2.0\NAudio.Asio.dll</HintPath>
</Reference>
<Reference Include="NAudio.Core, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.Core.2.2.1\lib\netstandard2.0\NAudio.Core.dll</HintPath>
</Reference>
<Reference Include="NAudio.Midi, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.Midi.2.2.1\lib\netstandard2.0\NAudio.Midi.dll</HintPath>
</Reference>
<Reference Include="NAudio.Wasapi, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.Wasapi.2.2.1\lib\netstandard2.0\NAudio.Wasapi.dll</HintPath>
</Reference>
<Reference Include="NAudio.WinForms, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.WinForms.2.2.1\lib\net472\NAudio.WinForms.dll</HintPath>
</Reference>
<Reference Include="NAudio.WinMM, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.WinMM.2.2.1\lib\netstandard2.0\NAudio.WinMM.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<HintPath>..\packages\Newtonsoft.Json.13.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NVorbis, Version=0.10.5.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NVorbis.0.10.5\lib\net45\NVorbis.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="Snappy.NET, Version=1.1.1.8, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Snappy.NET.1.1.1.8\lib\net45\Snappy.NET.dll</HintPath>
<Reference Include="SixLabors.ImageSharp, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d998eea7b14cab13, processorArchitecture=MSIL">
<HintPath>..\packages\SixLabors.ImageSharp.2.1.13\lib\net472\SixLabors.ImageSharp.dll</HintPath>
</Reference>
<Reference Include="Snappier, Version=1.3.0.0, Culture=neutral, PublicKeyToken=a1b25124e6e13a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Snappier.1.3.0\lib\net472\Snappier.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
<Reference Include="System.Buffers, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.6.1\lib\net462\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.FileSystem, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath>
</Reference>
<Reference Include="System.IO.FileSystem.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath>
<Reference Include="System.Memory, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.6.3\lib\net462\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
<Reference Include="System.Numerics.Vectors, Version=4.1.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.6.1\lib\net462\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.1.2\lib\net462\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath>
<Reference Include="System.Security.AccessControl, Version=6.0.0.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.AccessControl.6.0.1\lib\net461\System.Security.AccessControl.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
<Reference Include="System.Security.Principal.Windows, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll</HintPath>
<Reference Include="System.Text.Encoding.CodePages, Version=10.0.0.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Encoding.CodePages.10.0.5\lib\net462\System.Text.Encoding.CodePages.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.4.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.6.3\lib\net462\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple" />
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
@@ -113,8 +147,8 @@
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
<Reference Include="ZstdNet, Version=1.4.5.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ZstdNet.1.4.5\lib\net45\ZstdNet.dll</HintPath>
<Reference Include="ZstdSharp, Version=0.8.7.0, Culture=neutral, PublicKeyToken=8d151af33a4ad5cf, processorArchitecture=MSIL">
<HintPath>..\packages\ZstdSharp.Port.0.8.7\lib\net462\ZstdSharp.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -139,6 +173,9 @@
<Compile Include="AdvSys\ImageGWD.cs" />
<Compile Include="Ail\ArcLNK2.cs" />
<Compile Include="AIRNovel\ArcAIR.cs" />
<Compile Include="aNCHOR\ArcFPD.cs" />
<Compile Include="aNCHOR\AudioFCD.cs" />
<Compile Include="FrontierWorks\ArcPCARC.cs" />
<Compile Include="Artemis\ImageNekoPNG.cs" />
<Compile Include="CsWare\AudioWAV.cs" />
<Compile Include="CsWare\ImageGDT.cs" />
@@ -154,18 +191,25 @@
<Compile Include="DxLib\WidgetDXA.xaml.cs">
<DependentUpon>WidgetDXA.xaml</DependentUpon>
</Compile>
<Compile Include="Edoire\ArcARC.cs" />
<Compile Include="FC01\ArcBDT.cs" />
<Compile Include="FC01\ArcSCXA.cs" />
<Compile Include="FC01\BdtTables.cs" />
<Compile Include="Fog\ArcDAT.cs" />
<Compile Include="FrontierWorks\ImageEXT.cs" />
<Compile Include="GScripter\ArcDATA.cs" />
<Compile Include="Guyzware\ArcDat.cs" />
<Compile Include="ImageKTX.cs" />
<Compile Include="Ism\ImagePNG.cs" />
<Compile Include="Kid\ArcDATRAW.cs" />
<Compile Include="Kid\ArcKLZ.cs" />
<Compile Include="Kid\ArcP2T.cs" />
<Compile Include="Kid\ImageBIP.cs" />
<Compile Include="Kid\ImageBIParc.cs" />
<Compile Include="Kid\ImageKLZ.cs" />
<Compile Include="Kid\ImageLBG.cs" />
<Compile Include="Kid\ImageSPC.cs" />
<Compile Include="KiriKiri\ArcTLG.cs" />
<Compile Include="Kogado\ArcARC.cs" />
<Compile Include="Ice\ImageIBM.cs" />
<Compile Include="Ice\ScriptISD.cs" />
@@ -177,6 +221,7 @@
<Compile Include="Illusion\ArcPP.cs" />
<Compile Include="Interheart\ImageBMP.cs" />
<Compile Include="Interheart\ImageHMP.cs" />
<Compile Include="CatSystem\ArcZT.cs" />
<Compile Include="JamCreation\ArcDAT.cs" />
<Compile Include="JamCreation\ImageDPO.cs" />
<Compile Include="AliceSoft\ArcAAR.cs" />
@@ -201,6 +246,7 @@
<Compile Include="ArcARCX.cs" />
<Compile Include="ArcASAR.cs" />
<Compile Include="Artemis\ArcMJA.cs" />
<Compile Include="Leaf\LeafVideo.cs" />
<Compile Include="Macintosh\ImagePICT.cs" />
<Compile Include="Macromedia\ArcDXR.cs" />
<Compile Include="Macromedia\AudioSND.cs" />
@@ -214,10 +260,13 @@
<Compile Include="MAGES\ImageBIN.cs" />
<Compile Include="Mugi\ArcBIN.cs" />
<Compile Include="Musica\ArcPAK.cs" />
<Compile Include="NEKOWORKs\ArcPACK.cs" />
<Compile Include="NipponIchi\ArcCASN.cs" />
<Compile Include="NipponIchi\ArcPSFS.cs" />
<Compile Include="NipponIchi\ImageNMT.cs" />
<Compile Include="NScripter\Script.cs" />
<Compile Include="Ps1\ImageTIM.cs" />
<Compile Include="Psp\ArcGim.cs" />
<Compile Include="Psp\ArcQPK.cs" />
<Compile Include="ScrPlayer\ImageIMG.cs" />
<Compile Include="SingleFileArchive.cs" />
@@ -923,6 +972,7 @@
<Compile Include="VnEngine\ImageZAW.cs" />
<EmbeddedResource Include="Abogado\keytable.dat" />
<EmbeddedResource Include="Strings\arcStrings.ja-JP.resx" />
<EmbeddedResource Include="Strings\arcStrings.zh-Hant.resx" />
<EmbeddedResource Include="Unity\strings.dat" />
<EmbeddedResource Include="ScrPlayer\ImgControlTable1" />
<EmbeddedResource Include="ScrPlayer\ImgControlTable2" />
@@ -1091,6 +1141,7 @@
<Compile Include="KiriKiri\KiriKiriCx.cs" />
<Compile Include="KogadoCocotte.cs" />
<Compile Include="AudioOGG.cs" />
<Compile Include="aPLibStream.cs" />
<Compile Include="LzssStream.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Settings.Designer.cs">
@@ -1364,18 +1415,11 @@ exit 0</PreBuildEvent>
<PostBuildEvent>if not exist "$(TargetDir)\GameData" mkdir "$(TargetDir)\GameData"
xcopy "$(ProjectDir)\Resources\*" "$(TargetDir)\GameData\" /D /Y &gt;NUL</PostBuildEvent>
</PropertyGroup>
<Import Project="..\packages\ZstdNet.1.4.5\build\ZstdNet.targets" Condition="Exists('..\packages\ZstdNet.1.4.5\build\ZstdNet.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\ZstdNet.1.4.5\build\ZstdNet.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\ZstdNet.1.4.5\build\ZstdNet.targets'))" />
<Error Condition="!Exists('..\packages\System.ValueTuple.4.6.2\build\net471\System.ValueTuple.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\System.ValueTuple.4.6.2\build\net471\System.ValueTuple.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<Import Project="..\packages\System.ValueTuple.4.6.2\build\net471\System.ValueTuple.targets" Condition="Exists('..\packages\System.ValueTuple.4.6.2\build\net471\System.ValueTuple.targets')" />
</Project>

View File

@@ -136,7 +136,7 @@ namespace GameRes.Formats
private static long GetDuration (IMFSourceReader reader)
{
var variantPtr = Marshal.AllocHGlobal (MarshalHelpers.SizeOf<PropVariant>());
var variantPtr = Marshal.AllocHGlobal (Marshal.SizeOf<PropVariant>());
try
{
int hResult = reader.GetPresentationAttribute (MediaFoundationInterop.MF_SOURCE_READER_MEDIASOURCE,
@@ -146,7 +146,7 @@ namespace GameRes.Formats
if (hResult != 0)
Marshal.ThrowExceptionForHR (hResult);
var variant = MarshalHelpers.PtrToStructure<PropVariant> (variantPtr);
var variant = Marshal.PtrToStructure<PropVariant> (variantPtr);
return (long)variant.Value;
}
finally

View File

@@ -0,0 +1,120 @@
//! \file ArcZT.cs
//! \date 2021 May 25
//! \brief CatSystem2 pack file.
//
// Copyright (C) 2021 by morkt
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using GameRes.Compression;
namespace GameRes.Formats.CatSystem
{
[Export(typeof(ArchiveFormat))]
public class ZtOpener : ArchiveFormat
{
public override string Tag { get { return "ZT/PACK"; } }
public override string Description { get { return "CatSystem2 pack file"; } }
public override uint Signature { get { return 0; } }
public override bool IsHierarchic { get { return true; } }
public override bool CanWrite { get { return false; } }
public ZtOpener ()
{
Extensions = new string[] { "zt" };
}
struct ZtSubdirectory
{
public string Name;
public long Offset;
}
public override ArcFile TryOpen (ArcView file)
{
if (file.MaxOffset < 0x11C)
return null;
if (0x110 > file.View.ReadUInt32 (8) || 1 < file.View.ReadUInt32 (0xC))
return null; // First entry is too small, or not a file or folder
var dir = new List<Entry> ();
var subdirs = new Queue<ZtSubdirectory> ();
const string sep = "\\";
string parent_name = "";
long offset = 0;
uint offset_next;
do
{
offset_next = file.View.ReadUInt32 (offset);
uint entry_size = file.View.ReadUInt32 (offset+8);
if (0 != offset_next && 0xC + entry_size > offset_next)
return null;
uint attributes = file.View.ReadUInt32 (offset+0xC);
string name = file.View.ReadString (offset+0x10, 0x104);
if (1 < attributes || 0 == name.Length)
return null;
if (0 == attributes)
{
var entry = FormatCatalog.Instance.Create<PackedEntry> (parent_name + name);
uint packed_size = file.View.ReadUInt32 (offset+0x114);
if (0x110 + packed_size != entry_size)
return null;
entry.Offset = offset + 0x11C;
entry.Size = packed_size;
entry.UnpackedSize = file.View.ReadUInt32 (offset+0x118);
entry.IsPacked = true;
if (!entry.CheckPlacement (file.MaxOffset))
return null;
dir.Add (entry);
}
else if (0 != file.View.ReadUInt32 (offset+4))
{
subdirs.Enqueue (new ZtSubdirectory { Name = parent_name + name + sep, Offset = offset });
}
if (0 == offset_next && 0 != subdirs.Count)
{ // No more entries in current directory, go to next subdirectory
var subdir = subdirs.Dequeue ();
parent_name = subdir.Name;
offset = subdir.Offset;
offset_next = file.View.ReadUInt32 (offset+4); // offset_child
if (0xC + file.View.ReadUInt32 (offset+8) > offset_next)
return null;
}
offset += offset_next;
}
while (0 != offset_next);
return new ArcFile (file, this, dir);
}
public override Stream OpenEntry (ArcFile arc, Entry entry)
{
var pentry = (PackedEntry)entry;
if (0 == pentry.UnpackedSize)
return Stream.Null;
var input = arc.File.CreateStream (entry.Offset, entry.Size);
return new ZLibStream (input, CompressionMode.Decompress);
}
}
}

View File

@@ -47,20 +47,46 @@ namespace GameRes.Formats.Circus
public override ArcFile TryOpen (ArcView file)
{
int count = file.View.ReadInt32 (0);
if (count <= 1 || count > 0xfffff)
return null;
var dir = ReadIndex (file, count, 0x24);
if (null == dir)
dir = ReadIndex (file, count, 0x30);
if (null == dir)
dir = ReadIndex (file, count, 0x3C);
if (null == dir)
return null;
return new ArcFile (file, this, dir);
var arcFile = TryOpenFromHeader(file);
if (null != arcFile)
{
return arcFile;
}
arcFile = TryOpenFromFooter(file);
return arcFile;
}
private List<Entry> ReadIndex (ArcView file, int count, int name_length)
public ArcFile TryOpenFromHeader(ArcView file)
{
int count = file.View.ReadInt32(0);
if (count <= 1 || count > 0xfffff)
return null;
var dir = ReadIndexV1(file, count, 0x24);
if (null == dir)
dir = ReadIndexV1(file, count, 0x30);
if (null == dir)
dir = ReadIndexV1(file, count, 0x3C);
if (null == dir)
return null;
return new ArcFile(file, this, dir);
}
public ArcFile TryOpenFromFooter(ArcView file)
{
int count = file.View.ReadInt32(file.MaxOffset - 4);
if(count <= 1 || count > 0xfffff)
{
return null;
}
var dir = ReadIndexV2(file, count, file.View.ReadInt32(file.MaxOffset - 0x8));
return new ArcFile(file, this, dir);
}
private List<Entry> ReadIndexV1 (ArcView file, int count, int name_length)
{
long index_offset = 4;
uint index_size = (uint)((name_length + 4) * count);
@@ -98,5 +124,36 @@ namespace GameRes.Formats.Circus
}
return dir;
}
private List<Entry> ReadIndexV2(ArcView file, int count, long start_offset)
{
uint max_index_size = (uint)(count * 0x4C);
long index_offset = start_offset;
var dir = new List<Entry> (count);
file.View.Reserve(start_offset, max_index_size);
for (int i = 0; i < count; i++)
{
int name_length = file.View.ReadByte(index_offset);
index_offset++;
string name = file.View.ReadString(index_offset, (uint)name_length);
index_offset += name_length;
uint entry_size = file.View.ReadUInt32(index_offset);
index_offset += 8;
long entry_offset = file.View.ReadInt32(index_offset);
index_offset += 4;
var entry = FormatCatalog.Instance.Create<Entry>(name);
entry.Size = entry_size;
entry.Offset = entry_offset;
dir.Add(entry);
}
return dir;
}
}
}

View File

@@ -0,0 +1,87 @@
//! \file ArcARC.cs
//! \date 2026 Feb 02
//! \brief Edoire's resource archive.
//
// Copyright (C) 2018 by morkt
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Text;
namespace GameRes.Formats.Edoire
{
[Export(typeof(ArchiveFormat))]
public class ArcOpener : ArchiveFormat
{
public override string Tag { get { return "ARC"; } }
public override string Description { get { return "Edoire's resource archive"; } }
public override uint Signature { get { return 0x43524140; } } // "@ARCH000"
public override bool IsHierarchic { get { return true; } }
public override bool CanWrite { get { return false; } }
public ArcOpener ()
{
Extensions = new string[] { "arc" };
}
public override ArcFile TryOpen (ArcView file)
{
if (!file.View.AsciiEqual (0, "@ARCH000"))
return null;
var index_offset = file.View.ReadInt64 (file.MaxOffset-8);
if (index_offset <= 0 || index_offset >= file.MaxOffset-12)
return null;
var count = file.View.ReadInt32 (index_offset);
if (!IsSaneCount (count))
return null;
index_offset += 4;
var dir = new List<Entry> (count);
for (var i = 0; i < count; i++)
{
var len = file.View.ReadByte (index_offset);
index_offset += 1;
var name = file.View.ReadString (index_offset, len, Encoding.UTF8);
index_offset += len;
var offset = file.View.ReadInt64 (index_offset);
index_offset += 8;
var size = file.View.ReadInt64 (index_offset);
index_offset += 9;
len = file.View.ReadByte (index_offset);
index_offset += 1;
var path = file.View.ReadString (index_offset, len, Encoding.UTF8);
index_offset += len;
if (path.StartsWith ("/"))
path = path.Substring (1);
if (!string.IsNullOrEmpty (path) && !path.EndsWith ("/"))
path += "/";
var entry = Create<Entry> (path+name);
entry.Offset = offset;
entry.Size = Convert.ToUInt32 (size);
if (!entry.CheckPlacement (file.MaxOffset))
return null;
dir.Add (entry);
}
return new ArcFile (file, this, dir);
}
}
}

View File

@@ -29,6 +29,7 @@ using System.IO;
using System.Linq;
using System.Text;
using GameRes.Utility;
using GameRes.Compression;
namespace GameRes.Formats.Enigma {
public enum NodeTypes {
@@ -45,14 +46,34 @@ namespace GameRes.Formats.Enigma {
public override bool IsHierarchic { get { return true; } }
public override bool CanWrite { get { return false; } }
public EvbPackOpener() {
Signatures = new uint[] { 0x425645, 0x905a4d, 0 };
Extensions = new[] { "exe" };
}
public override ArcFile TryOpen(ArcView file) {
uint index_size = file.View.ReadUInt32(0x40) + 68;
uint index_offset = 0x4F;
uint base_offset = 0;
if (file.View.AsciiEqual(0, "MZ")) {
var exe = new ExeFile(file);
var sig = new byte[] { 0x45, 0x56, 0x42, 0x00 };
if (exe.ContainsSection(".enigma1")) {
var ofs = exe.FindString(exe.Sections[".enigma1"], sig);
if (ofs != -1)
base_offset = (uint)ofs;
}
if (base_offset == 0)
return null;
}
else if (!file.View.AsciiEqual(0, "EVB"))
return null;
uint index_size = file.View.ReadUInt32(base_offset + 0x40) + base_offset + 68;
uint index_offset = base_offset + 0x4F;
uint file_offset = index_size;
var dir = new List<Entry>();
var name_buffer = new StringBuilder();
var counts = new List<uint> { file.View.ReadUInt32(0x4C) };
var counts = new List<uint> { file.View.ReadUInt32(base_offset + 0x4C) };
var names = new List<string> { "" };
while (index_offset < index_size - 4) {
@@ -73,12 +94,12 @@ namespace GameRes.Formats.Enigma {
index_offset++;
counts[counts.Count - 1]--;
if (type == NodeTypes.File) {
var entry = Create<Entry>(Path.Combine(names.Concat(new[] { name }).ToArray()));
var entry = Create<PackedEntry>(Path.Combine(names.Concat(new[] { name }).ToArray()));
uint unpacked_size = file.View.ReadUInt32(index_offset + 2);
uint size = file.View.ReadUInt32(index_offset + 49);
if (unpacked_size != size)
return null; // packed entry not implemented
entry.IsPacked = unpacked_size != size;
entry.Offset = file_offset;
entry.UnpackedSize = unpacked_size;
entry.Size = size;
file_offset += size;
if (!entry.CheckPlacement(file.MaxOffset))
@@ -106,5 +127,30 @@ namespace GameRes.Formats.Enigma {
return new ArcFile(file, this, dir);
}
public override Stream OpenEntry(ArcFile arc, Entry entry) {
var pent = entry as PackedEntry;
if (pent.IsPacked) {
uint header_size = arc.File.View.ReadUInt32(pent.Offset);
uint offset = header_size;
Stream input = null;
for (uint i = 8; i < header_size; i += 12) {
uint chunk_size = arc.File.View.ReadUInt32(pent.Offset + i);
var chunk = new aPLibStream(
arc.File.CreateStream(pent.Offset + offset, chunk_size)
);
if (input != null)
input = new ConcatStream(input, chunk);
else
input = chunk;
offset += chunk_size;
}
return input;
}
else
return arc.File.CreateStream(pent.Offset, pent.Size);
}
}
}

View File

@@ -29,6 +29,7 @@ using System.ComponentModel.Composition;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml;
using GameRes.Formats.Strings;
@@ -131,11 +132,27 @@ namespace GameRes.Formats.Entis
if (EncType.Raw == nent.Encryption || null == narc || null == narc.Password)
return input;
if (EncType.SimpleCrypt32 == nent.Encryption)
{
if (0 != size % 4)
throw new InvalidFormatException ();
using (input)
return DecodeSimpleCrypt32 (input, narc.Password, BitConverter.ToUInt32 (nent.Extra, 4));
}
if (EncType.BSHFCrypt == nent.Encryption)
{
using (input)
return DecodeBSHF (input, narc.Password);
}
if (EncType.ERISACrypt == nent.Encryption)
{
Stream enc;
using (input)
enc = DecodeBSHF (input, narc.Password);
return new ErisaNemesisStream (enc, (int)entry.Size);
}
Trace.WriteLine (string.Format ("{0}: encryption scheme 0x{1:x8} not implemented",
nent.Name, nent.Encryption));
return input;
@@ -232,6 +249,37 @@ namespace GameRes.Formats.Entis
return new MemoryStream (buf);
}
Stream DecodeSimpleCrypt32(Stream input, string password, uint imul_key)
{
var xor_key_map = Encoding.UTF8.GetBytes (password);
imul_key ^= Crc32.Compute (xor_key_map, 0, xor_key_map.Length);
for (int i = 0; i < xor_key_map.Length; i++)
{
var key_byte = (byte)~xor_key_map[i];
xor_key_map[i] = (byte)(key_byte ^ (key_byte * 7));
}
var buffer = new byte[input.Length];
input.Read(buffer, 0, (int)input.Length);
var buffer_span = MemoryMarshal.Cast<byte, uint> (buffer);
var xor_key_span = MemoryMarshal.Cast<byte, uint> (xor_key_map);
for (int i = 0; i < buffer_span.Length; i += xor_key_span.Length)
{
var window_size = Math.Min (buffer_span.Length - i, xor_key_span.Length);
var window_span = buffer_span.Slice (i, window_size);
for (int j = 0; j < window_size; j++)
{
window_span[j] = (window_span[j] * imul_key) ^ xor_key_span[j];
}
}
return new MemoryStream (buffer);
}
public override ResourceOptions GetDefaultOptions ()
{
return new NoaOptions {
@@ -306,7 +354,7 @@ namespace GameRes.Formats.Entis
entry.Encryption = m_file.View.ReadUInt32 (dir_offset);
m_found_encrypted = m_found_encrypted || (EncType.Raw != entry.Encryption && EncType.ERISACode != entry.Encryption);
bool is_packed = EncType.ERISACode == entry.Encryption;
bool is_packed = EncType.ERISACode == entry.Encryption || EncType.ERISACrypt == entry.Encryption;
dir_offset += 4;
entry.Offset = base_offset + m_file.View.ReadInt64 (dir_offset);

View File

@@ -69,6 +69,12 @@ namespace GameRes.Formats.FVP
if (null == image_info)
return null;
}
// This is a atlas image, all clips are placed into a single TLG image
if (file.View.AsciiEqual (0x2C, "TLG"))
return null;
// This is a diff image
if (0x64 == file.View.ReadByte (0x2C))
return null;
int count = file.View.ReadInt32 (0x20);
if (0 == count)
count = 1;

View File

@@ -28,6 +28,8 @@ using GameRes.Utility;
using System;
using System.ComponentModel.Composition;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
@@ -66,14 +68,112 @@ namespace GameRes.Formats.FVP
};
}
private static ImageFormat s_TlgFormat = null;
public override ImageData Read (IBinaryStream stream, ImageMetaData info)
{
stream.Position = 0x2C;
PixelFormat format = PixelFormats.Bgra32;
WriteableBitmap bitmap = null;
if (0x64 == stream.PeekByte ())
{
// This is a diff image, try to read base image
stream.Position += 1;
var name = stream.ReadCString (Encoding.UTF8);
if (!string.IsNullOrEmpty (name))
{
var entry = VFS.FindFile (Path.ChangeExtension (name, "hzc"));
if (null != entry)
{
var decoder = VFS.OpenImage (entry);
var image = decoder.Image;
decoder.Dispose();
if (null == image)
throw new InvalidFormatException ("Failed to decode base image.");
var converted = image.Bitmap;
if (converted.Format != format)
converted = new FormatConvertedBitmap (converted, format, null, 0);
var stride = converted.PixelWidth * 4;
var size = stride * converted.PixelHeight;
var pixels = new byte[size];
converted.CopyPixels (pixels, stride, 0);
bitmap = new WriteableBitmap (converted.PixelWidth, converted.PixelHeight,
ImageData.DefaultDpiX, ImageData.DefaultDpiY, format, null);
var rect = new Int32Rect (0, 0, converted.PixelWidth, converted.PixelHeight);
bitmap.WritePixels (rect, pixels, stride, 0);
}
}
}
if (stream.ReadBytes (3).AsciiEqual ("TLG"))
{
// Read the TLG image
var tlg_stream = new BinaryStream (new StreamRegion (stream.AsStream, stream.Position-3, true), stream.Name);
if (null == s_TlgFormat)
s_TlgFormat = FindByTag ("TLG");
var tlg_info = s_TlgFormat.ReadMetaData (tlg_stream);
var image = s_TlgFormat.Read (tlg_stream, tlg_info);
// No base image
if (null == bitmap)
return image;
// Size should be the same as the base image
if (image.Width != bitmap.PixelWidth || image.Height != bitmap.PixelHeight)
return image;
// Blend two images
var converted = image.Bitmap;
if (converted.Format != format)
converted = new FormatConvertedBitmap (converted, format, null, 0);
var rect = new Int32Rect (0, 0, converted.PixelWidth, converted.PixelHeight);
BlendBitmap (converted, rect, bitmap, 0, 0);
bitmap.Freeze ();
return new ImageData (bitmap, tlg_info);
}
var meta = (HzcMetaData)info;
stream.Position = 12 + meta.HeaderSize;
using (var decoder = new HzcDecoder (stream, meta, true))
return decoder.Image;
}
void BlendBitmap (BitmapSource bitmap, Int32Rect source, WriteableBitmap output, int x, int y)
{
int src_stride = source.Width * 4;
var pixels = new byte[src_stride * source.Height];
bitmap.CopyPixels (source, pixels, src_stride, 0);
unsafe
{
int dst_stride = output.BackBufferStride;
int offset = y * dst_stride + x * 4;
byte* buffer = (byte*)(output.BackBuffer + offset);
int src = 0;
for (int h = 0; h < source.Height; ++h)
{
int dst = 0;
for (int w = 0; w < source.Width; ++w)
{
byte src_alpha = pixels[src+3];
if (src_alpha > 0)
{
if (0xFF == src_alpha || 0 == buffer[dst+3])
{
buffer[dst ] = pixels[src];
buffer[dst+1] = pixels[src+1];
buffer[dst+2] = pixels[src+2];
}
else
{
buffer[dst+0] = (byte)((pixels[src+0] * src_alpha + buffer[dst+0] * (0xFF - src_alpha)) / 0xFF);
buffer[dst+1] = (byte)((pixels[src+1] * src_alpha + buffer[dst+1] * (0xFF - src_alpha)) / 0xFF);
buffer[dst+2] = (byte)((pixels[src+2] * src_alpha + buffer[dst+2] * (0xFF - src_alpha)) / 0xFF);
}
buffer[dst+3] = src_alpha;
}
dst += 4;
src += 4;
}
buffer += dst_stride;
}
}
}
public override void Write (Stream file, ImageData image)
{
throw new System.NotImplementedException ("HzcFormat.Write not implemented");

93
ArcFormats/Fog/ArcDAT.cs Normal file
View File

@@ -0,0 +1,93 @@
//! \file ArcDAT.cs
//! \date 2026-01-24
//! \brief FOG resource archive format.
//
// Copyright (C) 2026 by morkt
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using GameRes.Utility;
namespace GameRes.Formats.Fog {
internal class DatEntry : Entry {
public string FileName;
}
[Export(typeof(ArchiveFormat))]
public class DatOpener : ArchiveFormat {
public override string Tag { get { return "DAT/FOG"; } }
public override string Description { get { return "FOG resource archive"; } }
public override uint Signature { get { return 0; } }
public override bool IsHierarchic { get { return true; } }
public override bool CanWrite { get { return false; } }
public override ArcFile TryOpen(ArcView file) {
var base_name = Path.GetFileNameWithoutExtension(file.Name);
bool multipart = base_name.Contains("_");
if (multipart)
base_name = base_name.Split('_')[0];
var index_file_name = base_name + "File.dat";
if (!File.Exists(index_file_name))
return null;
var index = File.ReadAllBytes(index_file_name);
var transformer = new NotTransform();
transformer.TransformBlock(index, 0, index.Length, index, 0);
using (var mem = new MemoryStream(index))
using (var reader = new BinaryReader(mem)) {
var dir = new List<Entry>();
while (mem.Position < mem.Length) {
uint name_length = Binary.BigEndian(reader.ReadUInt32());
string name = Binary.GetCString(reader.ReadBytes((int)name_length), 0);
var entry = Create<DatEntry>(name);
if (multipart) {
uint part = Binary.BigEndian(reader.ReadUInt32());
entry.FileName = string.Format("{0}_{1:00}.dat", base_name, part);
if (!File.Exists(entry.FileName))
return null;
}
else {
entry.FileName = file.Name;
}
reader.ReadUInt32();
entry.Offset = Binary.BigEndian(reader.ReadUInt32());
reader.ReadUInt32();
entry.Size = Binary.BigEndian(reader.ReadUInt32());
dir.Add(entry);
}
return new ArcFile(file, this, dir);
}
}
public override Stream OpenEntry(ArcFile arc, Entry entry) {
var dent = entry as DatEntry;
using (var data_file = new ArcView(dent.FileName)) {
var input = data_file.CreateStream(dent.Offset, dent.Size);
return new XoredStream(input, 0xFF);
}
}
}
}

View File

@@ -0,0 +1,117 @@
//! \file ArcPCARC.cs
//! \date Tue Feb 10 2026 07:56:13
//! \brief Frontier Works engine resource archive.
//
// Copyright (C) 2015 by morkt
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GameRes.Formats.FrontierWorks
{
[Export(typeof(ArchiveFormat))]
public class PcArcOpener : ArchiveFormat
{
public override string Tag { get { return "PCARC"; } }
public override string Description { get { return "Frontier Works engine resource archive"; } }
public override uint Signature { get { return 0x30303130; } } // "0100"
public override bool IsHierarchic { get { return true; } }
public override bool CanWrite { get { return false; } }
public PcArcOpener()
{
Extensions = new string[] { "pcarc" };
}
public override ArcFile TryOpen (ArcView file)
{
if (!file.View.AsciiEqual (0, "0100"))
return null;
var dir_count = file.View.ReadInt32 (4);
if (dir_count <= 0 || dir_count > 32)
return null;
var data_offset = file.View.ReadInt64 (8);
if (data_offset < 0x190)
return null;
var offset = 0x10;
var dir = new List<Entry> ();
for (var i = 0; i < dir_count; i++)
{
var dir_offset = file.View.ReadInt64 (offset);
offset += 8;
if (dir_offset < 0x190)
break;
var path = file.View.ReadString (dir_offset, 0x40);
var entry_count = file.View.ReadInt32 (dir_offset+0x40);
dir_offset += 0x50;
if (!string.IsNullOrEmpty (path) && !path.EndsWith ("/"))
path += "/";
for (var j = 0; j < entry_count; j++)
{
var entry = new Entry ();
entry.Name = path+file.View.ReadString (dir_offset, 0x40);
entry.Offset = data_offset+file.View.ReadInt64 (dir_offset+0x40);
entry.Size = file.View.ReadUInt32 (dir_offset+0x48);
dir.Add (entry);
dir_offset += 0x50;
}
}
DetectFileTypes (dir);
return new ArcFile (file, this, dir);
}
public override Stream OpenEntry (ArcFile arc, Entry entry)
{
if (entry.Name.HasExtension (".gz"))
{
using (var input = arc.File.CreateStream (entry.Offset, entry.Size))
using (var gzs = new GZipStream (input, CompressionMode.Decompress))
{
var output = new MemoryStream ();
gzs.CopyTo (output);
return new BinMemoryStream (output, entry.Name.Substring (0, entry.Name.Length-3));
}
}
return base.OpenEntry (arc, entry);
}
static void DetectFileTypes (List<Entry> dir)
{
foreach (var entry in dir)
{
var name = entry.Name;
if (name.HasExtension (".gz"))
name = name.Substring (0, name.Length-3);
if (name.HasExtension (".oggl"))
entry.Type = "audio";
if (string.IsNullOrEmpty (entry.Type))
entry.Type = FormatCatalog.Instance.GetTypeFromName (name);
}
}
}
}

View File

@@ -0,0 +1,82 @@
//! \file ImageEXT.cs
//! \date Tue Feb 10 2026 08:21:40
//! \brief Frontier Works engine image format.
//
// Copyright (C) 2015 by morkt
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
using System;
using System.ComponentModel.Composition;
using System.IO;
using System.Windows.Media;
namespace GameRes.Formats.FrontierWorks
{
[Export(typeof(ImageFormat))]
public class ExtFormat : ImageFormat
{
public override string Tag { get { return "EXT"; } }
public override string Description { get { return "Frontier Works engine image format"; } }
public override uint Signature { get { return 0x30545845; } } // 'EXT0'
public ExtFormat ()
{
Extensions = new string[] { "ext" };
}
public override ImageMetaData ReadMetaData (IBinaryStream stream)
{
stream.Position = 0;
var signature = stream.ReadInt32 ();
if (0x30545845 != signature)
return null;
stream.Position = 0xC;
var width = stream.ReadUInt32 ();
var height = stream.ReadUInt32 ();
if (width > 0x1000 || height > 0x1000)
return null;
stream.Position = 0x24;
var bpp = stream.ReadByte ();
if (32 != bpp)
return null;
return new ImageMetaData
{
Width = width,
Height = height,
BPP = bpp,
};
}
public override ImageData Read (IBinaryStream stream, ImageMetaData info)
{
stream.Position = 0x100;
var pixels = new byte[info.Width*info.Height*4];
if (pixels.Length != stream.Read (pixels, 0, pixels.Length))
throw new EndOfStreamException ();
return ImageData.Create (info, PixelFormats.Bgra32, null, pixels);
}
public override void Write (Stream file, ImageData image)
{
throw new NotImplementedException ("ExtFormat.Write not implemented");
}
}
}

View File

@@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using GameRes.Utility;
namespace GameRes.Formats.Guyzware
{
[Export(typeof(ArchiveFormat))]
public class GdpOpener : ArchiveFormat
{
public override string Tag => "DAT/GDP";
public override string Description => "Guyzware engine";
public override uint Signature => 0;
public override bool IsHierarchic => false;
public override bool CanWrite => false;
public override ArcFile TryOpen(ArcView file)
{
int count = file.View.ReadInt32(0);
if (!IsSaneCount(count))
return null;
var dir = new List<Entry>(count);
long index_offset = 4;
// heuristic: small first byte = variable
byte checkByte = file.View.ReadByte(index_offset);
bool isVariableLength = checkByte < 64;
for (int i = 0; i < count; i++)
{
if (index_offset >= file.MaxOffset)
break;
string name;
uint offset, size;
if (isVariableLength)
{
// Variable length:
// [1 byte length (ignored)] [Shift-JIS string] [00]
index_offset++; // skip length byte
var nameBytes = new List<byte>();
while (index_offset < file.MaxOffset)
{
byte b = file.View.ReadByte(index_offset++);
if (b == 0)
break;
nameBytes.Add(b);
}
name = Encodings.cp932.GetString(nameBytes.ToArray());
}
else
{
// Fixed 32 bytes
name = file.View.ReadString(index_offset, 32, Encodings.cp932);
name = name.TrimEnd('\0', ' ');
index_offset += 32;
}
offset = file.View.ReadUInt32(index_offset);
size = file.View.ReadUInt32(index_offset + 4);
index_offset += 8;
var entry = new Entry
{
Name = name,
Offset = offset,
Size = size,
};
if (!entry.CheckPlacement(file.MaxOffset))
return null;
dir.Add(entry);
}
return new ArcFile(file, this, dir);
}
public override Stream OpenEntry(ArcFile arc, Entry entry)
{
return arc.File.CreateStream(entry.Offset, entry.Size);
}
}
}

110
ArcFormats/ImageKTX.cs Normal file
View File

@@ -0,0 +1,110 @@
//! \file ImageKTX.cs
//! \date 2026 March 01
//! \brief Khronos texture format.
//
// Copyright (C) 2017 by morkt
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
using BCnEncoder.Decoder;
using BCnEncoder.Shared;
using BCnEncoder.Shared.ImageFiles;
using System;
using System.ComponentModel.Composition;
using System.IO;
using System.Reflection;
using System.Windows.Media;
namespace GameRes.Formats
{
internal class KtxMetaData : ImageMetaData
{
public KtxHeader Header;
}
[Export(typeof(ImageFormat))]
public class KtxFormat : ImageFormat
{
public override string Tag { get { return "KTX"; } }
public override string Description { get { return "Khronos texture format"; } }
public override uint Signature { get { return 0x58544BAB; } }
public override bool CanWrite { get { return false; } }
public override ImageMetaData ReadMetaData (IBinaryStream file)
{
var signature = file.ReadInt32 ();
if (0x58544BAB != signature)
return null;
file.Position = 0xC;
var header = new KtxHeader
{
Endianness = file.ReadUInt32 (),
GlType = (GlType) file.ReadUInt32 (),
GlTypeSize = file.ReadUInt32 (),
GlFormat = (GlFormat) file.ReadUInt32 (),
GlInternalFormat = (GlInternalFormat) file.ReadUInt32 (),
GlBaseInternalFormat = (GlFormat) file.ReadUInt32 (),
PixelWidth = file.ReadUInt32 (),
PixelHeight = file.ReadUInt32 (),
PixelDepth = file.ReadUInt32 (),
NumberOfArrayElements = file.ReadUInt32 (),
NumberOfFaces = file.ReadUInt32 (),
NumberOfMipmapLevels = file.ReadUInt32 (),
BytesOfKeyValueData = file.ReadUInt32 (),
};
var ktx = new KtxFile (header);
var decoder = new BcDecoder ();
if (!decoder.IsSupportedFormat (ktx))
return null;
return new KtxMetaData
{
Width = header.PixelWidth,
Height = header.PixelHeight,
BPP = 32,
Header = header,
};
}
public override ImageData Read (IBinaryStream file, ImageMetaData info)
{
var ktx = KtxFile.Load (file.AsStream);
var decoder = new BcDecoder ();
var buffer = decoder.Decode (ktx);
var pixels = new byte[buffer.Length*4];
var src = 0;
var dst = 0;
while (src < buffer.Length)
{
pixels[dst ] = buffer[src].b;
pixels[dst+1] = buffer[src].g;
pixels[dst+2] = buffer[src].r;
pixels[dst+3] = buffer[src].a;
src += 1;
dst += 4;
}
return ImageData.Create (info, PixelFormats.Bgra32, null, pixels);
}
public override void Write (Stream file, ImageData image)
{
throw new NotImplementedException ("KtxFormat.Write not implemented");
}
}
}

View File

@@ -0,0 +1,109 @@
//! \file ArcTLG.cs
//! \date Tue Mar 17 2026 10:35:55
//! \brief KiriKiri TLG image implementation.
//---------------------------------------------------------------------------
// TLGqoi multi-layer image decoder
//
// C# port by crsky
//
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
namespace GameRes.Formats.KiriKiri
{
internal class TlgLayerEntry : Entry
{
public int Index;
}
[Export(typeof(ArchiveFormat))]
public class TlgOpener : ArchiveFormat
{
public override string Tag { get { return "TLG"; } }
public override string Description { get { return "KiriKiri game engine image format"; } }
public override uint Signature { get { return 0x71474C54; } } // 'TLGq'
public override bool IsHierarchic { get { return false; } }
public override bool CanWrite { get { return false; } }
public TlgOpener ()
{
Extensions = new string[] { "tlg" };
}
public override ArcFile TryOpen (ArcView file)
{
if (!file.View.AsciiEqual (0, "TLGqoi") || !file.View.AsciiEqual (7, "raw"))
return null;
var qhdr = Array.Empty<byte> ();
var offset = 0x14;
while (true)
{
var entry_signature = file.View.ReadInt32 (offset);
var entry_size = file.View.ReadInt32 (offset+4);
offset += 8;
if (0x52444851 == entry_signature) // 'QHDR'
{
if (0x30 != entry_size)
return null;
qhdr = file.View.ReadBytes (offset, (uint)entry_size);
if (entry_size != qhdr.Length)
return null;
offset += entry_size;
}
else if (0 == entry_signature && 0 == entry_size)
break;
else
return null;
}
if (0 == qhdr.Length)
return null;
var layer_count = qhdr.ToInt32 (4);
if (layer_count < 1)
return null;
var block_count = qhdr.ToInt32 (12);
if (0 == block_count)
return null;
var dir = new List<Entry> (layer_count);
for (var i = 0; i < layer_count; i++)
{
dir.Add (new TlgLayerEntry
{
Name = string.Format ("{0}#{1:D3}.tlg", Path.GetFileNameWithoutExtension (file.Name), i),
Size = (uint)file.MaxOffset,
Type = "image",
Index = i,
});
}
return new ArcFile (file, this, dir);
}
static readonly ResourceInstance<ImageFormat> s_TlgFormat = new ResourceInstance<ImageFormat> ("TLG");
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
{
var layer_entry = entry as TlgLayerEntry;
if (null == layer_entry)
return base.OpenImage (arc, entry);
var input = arc.File.CreateStream ();
try
{
var info = s_TlgFormat.Value.ReadMetaData (input);
if (null == info)
throw new InvalidFormatException ();
if (info is TlgMetaData tlg)
{
tlg.LayerIndex = layer_entry.Index;
}
return new ImageFormatDecoder (input, s_TlgFormat.Value, info);
}
catch
{
input.Dispose ();
throw;
}
}
}
}

View File

@@ -104,6 +104,22 @@ namespace GameRes.Formats.KiriKiri
input.Read (header, 0, 5);
uint signature = header.ToUInt32 (0);
GuessEntryTypeBySignature (entry, signature);
if (0x46464952 == signature) // 'RIFF'
{
if (entry.UnpackedSize >= 12)
{
var header_ext = new byte[12];
Array.Copy (header, header_ext, header.Length);
input.Read (header_ext, header.Length, header_ext.Length-header.Length);
header = header_ext;
if (header.AsciiEqual (8, "WAVE"))
entry.Type = "audio";
else if (header.AsciiEqual (8, "WEBP"))
entry.Type = "image";
else if (header.AsciiEqual (8, "AVI "))
entry.Type = "video";
}
}
if (0x184D2204 == signature) // LZ4 magic
{
// assume no scripts are compressed using LZ4, return decompressed stream right away

View File

@@ -16,13 +16,16 @@ using GameRes.Utility;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using K4os.Compression.LZ4;
using System.Threading.Tasks;
namespace GameRes.Formats.KiriKiri
{
internal class TlgMetaData : ImageMetaData
{
public int Version;
public int DataOffset;
public long DataOffset;
public int LayerIndex;
}
[Export(typeof(ImageFormat))]
@@ -35,7 +38,7 @@ namespace GameRes.Formats.KiriKiri
public TlgFormat ()
{
Extensions = new string[] { "tlg", "tlg5", "tlg6" };
Signatures = new uint[] { 0x30474C54, 0x35474C54, 0x36474C54, 0x35474CAB, 0x584D4B4A };
Signatures = new uint[] { 0x30474C54, 0x35474C54, 0x36474C54, 0x35474CAB, 0x584D4B4A, 0x6D474C54, 0x71474C54, 0x72474C54 };
}
public override ImageMetaData ReadMetaData (IBinaryStream stream)
@@ -45,7 +48,7 @@ namespace GameRes.Formats.KiriKiri
if (!header.AsciiEqual ("TLG0.0\x00sds\x1a"))
offset = 0;
int version;
if (!header.AsciiEqual (offset+6, "\x00raw\x1a"))
if (!header.AsciiEqual (offset+6, "\x00raw\x1a") && !header.AsciiEqual (offset+6, "\x00idx\x1a"))
return null;
if (0xAB == header[offset])
header[offset] = (byte)'T';
@@ -53,6 +56,12 @@ namespace GameRes.Formats.KiriKiri
version = 6;
else if (header.AsciiEqual (offset, "TLG5.0"))
version = 5;
else if (header.AsciiEqual (offset, "TLGmux"))
version = 0;
else if (header.AsciiEqual (offset, "TLGqoi"))
version = 1;
else if (header.AsciiEqual (offset, "TLGref"))
version = 2;
else if (header.AsciiEqual (offset, "XXXYYY"))
{
version = 5;
@@ -102,6 +111,9 @@ namespace GameRes.Formats.KiriKiri
{
var meta = (TlgMetaData)info;
if (2 == meta.Version)
return ReadREF (file, meta);
var image = ReadTlg (file, meta);
int tail_size = (int)Math.Min (file.Length - file.Position, 512);
@@ -137,6 +149,10 @@ namespace GameRes.Formats.KiriKiri
src.Position = info.DataOffset;
if (6 == info.Version)
return ReadV6 (src, info);
else if (0 == info.Version)
return ReadMUX (src, info);
else if (1 == info.Version)
return ReadQOI (src, info);
else
return ReadV5 (src, info);
}
@@ -1085,6 +1101,488 @@ namespace GameRes.Formats.KiriKiri
}
}
}
byte[] DecodeQOI (IBinaryStream src, uint width, uint height)
{
var count = 4*width*height;
var output = new byte [count];
var qoi = new QoiDecodeStream (src);
uint pixel = 0;
var run = 0;
var dst = 0;
while (dst < count)
{
if (run > 1)
--run;
else
{
run = qoi.Read (out pixel);
}
output[dst ] = (byte)pixel;
output[dst+1] = (byte)(pixel >> 8);
output[dst+2] = (byte)(pixel >> 16);
output[dst+3] = (byte)(pixel >> 24);
dst += 4;
}
return output;
}
class Lz4DecodeStream
{
readonly IBinaryStream m_input;
readonly byte[][] m_buffer;
readonly int[] m_size;
int m_index;
int m_pos;
const int BUFFER_SIZE = 0x8000;
public Lz4DecodeStream (IBinaryStream input)
{
m_input = input;
m_buffer = new byte[2][];
m_size = new int[2];
for (var i = 0; i < m_buffer.Length; i++)
m_buffer[i] = new byte[BUFFER_SIZE];
}
bool FillBuffer ()
{
if (m_input.Position == m_input.Length)
return false;
var v1 = m_input.ReadUInt16 ();
var v2 = m_input.ReadUInt16 ();
var input = m_input.ReadBytes (v2);
if (v2 != input.Length)
throw new EndOfStreamException ();
var size = v1 & 0x7FFF;
if (0 == size)
size = 0x8000;
var dst = m_index ^ 1;
var dic = m_index;
int num;
if (0 != (v1 & 0x8000))
{
if (0 == m_size[dic])
throw new InvalidFormatException ();
num = LZ4Codec.Decode (input, m_buffer[dst], m_buffer[dic].AsSpan (0, m_size[dic]));
}
else
num = LZ4Codec.Decode (input, m_buffer[dst]);
if (-1 == num || size != num)
throw new InvalidFormatException ();
m_size[dst] = num;
m_index ^= 1;
m_pos = 0;
return true;
}
public int ReadByte ()
{
if (m_pos == m_size[m_index])
{
if (!FillBuffer ())
return -1;
}
var idx = m_index;
if (m_pos == m_size[idx])
return -1;
return m_buffer[idx][m_pos++];
}
}
class RunDecodeStream
{
readonly Lz4DecodeStream m_input;
public RunDecodeStream (IBinaryStream input)
{
m_input = new Lz4DecodeStream (input);
}
public int Read ()
{
var value = 0;
var shift = 0;
while (shift < 32)
{
var b = m_input.ReadByte ();
if (-1 == b)
throw new EndOfStreamException ();
value |= (int)(b & 0x7F) << shift;
if (0 == (b & 0x80))
break;
shift += 7;
}
return value;
}
}
static class QoiCodec
{
public const int Index = 0x00;
public const int Diff = 0x40;
public const int Luma = 0x80;
public const int Run = 0xC0;
public const int Rgb = 0xFE;
public const int Rgba = 0xFF;
public const int Mask2 = 0xC0;
public const int HashTableSize = 64;
}
class QoiDecodeStream
{
readonly IBinaryStream m_input;
readonly byte[] m_table;
uint m_pixel;
public QoiDecodeStream (IBinaryStream input)
{
m_input = input;
m_table = new byte [4*QoiCodec.HashTableSize];
m_pixel = 0xFF000000;
}
public int Read (out uint output)
{
var r = (byte)m_pixel;
var g = (byte)(m_pixel >> 8);
var b = (byte)(m_pixel >> 16);
var a = (byte)(m_pixel >> 24);
var run = 1;
var b1 = m_input.ReadByte ();
if (-1 == b1)
throw new EndOfStreamException ();
if (QoiCodec.Rgb == b1)
{
var rgb = m_input.ReadInt24 ();
r = (byte)rgb;
g = (byte)(rgb >> 8);
b = (byte)(rgb >> 16);
}
else if (QoiCodec.Rgba == b1)
{
var rgba = m_input.ReadInt32 ();
r = (byte)rgba;
g = (byte)(rgba >> 8);
b = (byte)(rgba >> 16);
a = (byte)(rgba >> 24);
}
else if (QoiCodec.Index == (b1 & QoiCodec.Mask2))
{
var p1 = (b1 & ~QoiCodec.Mask2) * 4;
r = m_table[p1 ];
g = m_table[p1+1];
b = m_table[p1+2];
a = m_table[p1+3];
}
else if (QoiCodec.Diff == (b1 & QoiCodec.Mask2))
{
r += (byte)(((b1 >> 4) & 0x03) - 2);
g += (byte)(((b1 >> 2) & 0x03) - 2);
b += (byte)((b1 & 0x03) - 2);
}
else if (QoiCodec.Luma == (b1 & QoiCodec.Mask2))
{
var b2 = m_input.ReadByte ();
if (-1 == b2)
throw new EndOfStreamException ();
var vg = (b1 & 0x3F) - 32;
r += (byte)(vg - 8 + ((b2 >> 4) & 0x0F));
g += (byte)vg;
b += (byte)(vg - 8 + (b2 & 0x0F));
}
else if (QoiCodec.Run == (b1 & QoiCodec.Mask2))
{
run = (b1 & 0x3F) + 1;
}
var p2 = (r*3 + g*5 + b*7 + a*11) % QoiCodec.HashTableSize*4;
m_table[p2 ] = r;
m_table[p2+1] = g;
m_table[p2+2] = b;
m_table[p2+3] = a;
m_pixel = (uint)(r | (g << 8) | (b << 16) | (a << 24));
output = (uint)(b | (g << 8) | (r << 16) | (a << 24));
return run;
}
}
class QoiBlockDecoder
{
readonly QoiDecodeStream m_qoi;
readonly RunDecodeStream m_run;
readonly int m_pixel_count;
readonly int m_layer_index;
readonly int m_layer_count;
readonly byte[] m_output;
readonly int m_dst;
public QoiBlockDecoder (byte[] qoi, byte[] run, int pixel_count, int layer_index, int layer_count, byte[] output, int dst)
{
m_qoi = new QoiDecodeStream (new BinMemoryStream (qoi));
m_run = new RunDecodeStream (new BinMemoryStream (run));
m_pixel_count = pixel_count;
m_layer_index = layer_index;
m_layer_count = layer_count;
m_output = output;
m_dst = dst;
}
public void Decode ()
{
m_qoi.Read (out var p0);
m_qoi.Read (out var p1);
if (0 != p0 || 0xFF000000 != p1)
throw new InvalidFormatException ();
var r0 = m_run.Read ();
if (0 != r0)
throw new InvalidFormatException ();
var dst = m_dst;
var count = m_pixel_count;
var skip = m_layer_index;
while (count --> 0)
{
var r1 = m_qoi.Read (out var pixel);
var r2 = m_run.Read ();
var run = r1 + r2;
while (run --> 0)
{
if (skip > 0)
--skip;
else
{
skip = m_layer_count-1;
m_output[dst ] = (byte)pixel;
m_output[dst+1] = (byte)(pixel >> 8);
m_output[dst+2] = (byte)(pixel >> 16);
m_output[dst+3] = (byte)(pixel >> 24);
dst += 4;
}
}
}
}
}
long[] DecodeArray (ReadOnlySpan<byte> input)
{
var output = new List<long> (input.Length);
var i = 0;
while (i < input.Length)
{
long value = 0;
var shift = 0;
while (shift < 64)
{
var b = input[i++];
value |= (long)(b & 0x7F) << shift;
if (0 == (b & 0x80))
break;
shift += 7;
if (i >= input.Length)
throw new EndOfStreamException ();
}
output.Add (value);
}
return output.ToArray ();
}
long[] ReadArray (IBinaryStream src, long offset, int signature)
{
src.Position = offset;
if (signature != src.ReadInt32 ())
throw new InvalidFormatException ();
var length = src.ReadInt32 ();
var input = src.ReadBytes (length);
if (input.Length != length)
throw new EndOfStreamException ();
return DecodeArray (input);
}
byte[] DecodeMultiLayerQOI (IBinaryStream src, uint width, uint height, byte[] qhdr, int layer)
{
var data_offset = src.Position;
var layer_count = qhdr.ToInt32 (4);
var block_height = qhdr.ToInt32 (8);
var block_count = qhdr.ToInt32 (12);
var dtbl_offset = qhdr.ToInt64 (24);
var rtbl_offset = qhdr.ToInt64 (32);
if (layer_count < 1)
throw new InvalidFormatException ();
if (0 == block_count)
throw new NotImplementedException ();
if (layer >= layer_count)
throw new ArgumentOutOfRangeException ();
long[] dtbl = ReadArray (src, data_offset+dtbl_offset, 0x4C425444);
if (0 == dtbl.Length || dtbl.Length != 1+2*block_count || dtbl[0] != dtbl.Length-1)
throw new InvalidFormatException ();
long[] rtbl = ReadArray (src, data_offset+rtbl_offset, 0x4C425452);
if (0 == rtbl.Length || rtbl.Length != 1+block_count || rtbl[0] != rtbl.Length-1)
throw new InvalidFormatException ();
var tasks = new List<Task> (block_count);
var output = new byte[4*width*height];
var qoi_offset = data_offset;
var run_offset = src.Position;
for (var i = 0; i < block_count; i++)
{
var qoi_size = (int) dtbl[1+2*i];
var run_size = (int) rtbl[1+i];
var num_pixels = (int) dtbl[1+2*i+1];
src.Position = qoi_offset;
var qoi = src.ReadBytes (qoi_size);
if (qoi_size != qoi.Length)
throw new EndOfStreamException ();
src.Position = run_offset;
var run = src.ReadBytes (run_size);
if (run_size != run.Length)
throw new EndOfStreamException ();
qoi_offset += qoi_size;
run_offset += run_size;
var dst = block_height*i * 4*(int)width;
var decoder = new QoiBlockDecoder (qoi, run, num_pixels, layer, layer_count, output, dst);
var task = Task.Run (() => decoder.Decode ());
tasks.Add (task);
}
Task.WhenAll (tasks).Wait ();
return output;
}
byte[] ReadQOI (IBinaryStream src, TlgMetaData info)
{
var qhdr = Array.Empty<byte> ();
while (true)
{
var entry_signature = src.ReadInt32 ();
var entry_size = src.ReadInt32 ();
if (0x52444851 == entry_signature) // 'QHDR'
{
if (0x30 != entry_size)
throw new InvalidFormatException ();
qhdr = src.ReadBytes (entry_size);
if (qhdr.Length != entry_size)
throw new EndOfStreamException ();
}
else if (0 == entry_signature && 0 == entry_size)
break;
else
throw new InvalidFormatException ();
}
if (0 != qhdr.Length)
return DecodeMultiLayerQOI (src, info.Width, info.Height, qhdr, info.LayerIndex);
return DecodeQOI (src, info.Width, info.Height);
}
byte[] ReadMUX (IBinaryStream src, TlgMetaData info)
{
src.Position = info.DataOffset;
var slices = new List<TlgMetaData> ();
while (true)
{
var entry_signature = src.ReadInt32 ();
var entry_size = src.ReadInt32 ();
if (0x58554D43 == entry_signature) // 'CMUX'
{
var entry = src.ReadBytes (entry_size);
var count = entry.ToInt32 (0);
if (0 == count)
throw new InvalidFormatException ();
var offset = 4;
for (var i = 0; i < count; i++)
{
slices.Add (new TlgMetaData
{
OffsetX = entry.ToInt32 (offset),
OffsetY = entry.ToInt32 (offset+4),
Width = entry.ToUInt32 (offset+8),
Height = entry.ToUInt32 (offset+12),
DataOffset = entry.ToInt64 (offset+16)
});
offset += 24;
}
}
else if (0 == entry_signature && 0 == entry_size)
break;
else
throw new InvalidFormatException ();
}
var data_offset = src.Position;
var image = new byte [4*info.Width*info.Height];
foreach (var slice_info in slices)
{
src.Position = data_offset + slice_info.DataOffset;
byte[] slice;
var header = src.ReadBytes (11);
if (header.AsciiEqual (0, "TLGqoi") && header.AsciiEqual (7, "raw"))
{
var channels = src.ReadByte ();
var width = src.ReadUInt32 ();
var height = src.ReadUInt32 ();
if (3 != channels && 4 != channels)
throw new InvalidFormatException ();
if (width != slice_info.Width || height != slice_info.Height)
throw new InvalidFormatException ();
slice = ReadQOI (src, slice_info);
}
else
throw new NotImplementedException ();
BlendImage (image, info, slice, slice_info, 0);
}
return image;
}
ImageData ReadREF (IBinaryStream src, TlgMetaData info)
{
src.Position = info.DataOffset;
var qref = Array.Empty<byte> ();
while (true)
{
var entry_signature = src.ReadInt32 ();
var entry_size = src.ReadInt32 ();
if (0x46455251 == entry_signature) // 'QREF'
{
if (entry_size < 16)
throw new InvalidFormatException ();
qref = src.ReadBytes (entry_size);
if (qref.Length != entry_size)
throw new EndOfStreamException ();
}
else if (0 == entry_signature && 0 == entry_size)
break;
else
throw new InvalidFormatException ();
}
if (0 == qref.Length)
throw new InvalidFormatException ();
var layer_index = qref.ToInt32 (4);
var name_length = qref.ToInt32 (12);
if (name_length < 2)
throw new InvalidFormatException ();
var name = Encoding.Unicode.GetString (qref, 16, name_length);
if (string.IsNullOrEmpty (name))
throw new InvalidFormatException ();
using (var ref_tlg = VFS.OpenBinaryStream (name))
{
var ref_meta = ReadMetaData (ref_tlg) as TlgMetaData;
if (1 != ref_meta.Version)
throw new InvalidFormatException ();
ref_meta.LayerIndex = layer_index;
return Read (ref_tlg, ref_meta);
}
}
}
internal class TagsParser

View File

@@ -23,10 +23,14 @@
// IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Text;
using GameRes.Compression;
using GameRes.Utility;
using GameRes.Utility.Serialization;
namespace GameRes.Formats.Leaf
@@ -38,7 +42,7 @@ namespace GameRes.Formats.Leaf
public override string Description { get { return "Leaf resource archive"; } }
public override uint Signature { get { return 0x5041434B; } } // 'KCAP'
public override bool IsHierarchic { get { return false; } }
public override bool CanWrite { get { return false; } }
public override bool CanWrite { get { return true; } }
public KcapOpener ()
{
@@ -160,6 +164,87 @@ namespace GameRes.Formats.Leaf
input.Position = 0;
return ImageFormatDecoder.Create (input);
}
// --- REPACK IMPLEMENTATION ---
public override void Create (Stream output, IEnumerable<Entry> entries, ResourceOptions options, EntryCallback callback)
{
int count = entries.Count();
using (var writer = new BinaryWriter (output, Encoding.ASCII, true))
{
// 1. Write Header (KCAP v2)
writer.Write (0x5041434B); // "KCAP"
writer.Write (0xFFFFFFFF);
writer.Write (0x0000FFFF);
writer.Write (count);
long tableOffset = 16;
long dataOffset = tableOffset + (count * 44);
writer.BaseStream.Position = dataOffset;
var entryInfos = new List<EntryInfo>();
int i = 0;
foreach (var entry in entries)
{
if (callback != null)
callback (i + 1, entry, null);
long currentOffset = writer.BaseStream.Position;
using (var input = File.OpenRead(entry.Name))
{
byte[] rawData = new byte[input.Length];
input.Read (rawData, 0, (int)input.Length);
// Compress
byte[] compressedData = LeafLzss.Compress (rawData);
// Write Data (Prefix + LZSS)
writer.Write ((uint)compressedData.Length);
writer.Write ((uint)rawData.Length);
writer.Write (compressedData);
uint totalSize = (uint)(compressedData.Length + 8);
entryInfos.Add (new EntryInfo
{
Name = Path.GetFileName (entry.Name),
UnpackedSize = (uint)rawData.Length,
Offset = (uint)currentOffset,
PackedSize = totalSize
});
}
i++;
}
// Write File Table
writer.BaseStream.Position = tableOffset;
foreach (var info in entryInfos)
{
writer.Write (1); // Type
byte[] nameBytes = Encodings.cp932.GetBytes (info.Name);
if (nameBytes.Length > 23) Array.Resize (ref nameBytes, 23);
writer.Write (nameBytes);
for (int k = nameBytes.Length; k < 24; k++) writer.Write ((byte)0);
writer.Write (0xFFFFFFFF); // CRC
writer.Write (info.UnpackedSize);
writer.Write (info.Offset);
writer.Write (info.PackedSize);
}
}
}
struct EntryInfo
{
public string Name;
public uint UnpackedSize;
public uint Offset;
public uint PackedSize;
}
}
[Export(typeof(ScriptFormat))]
@@ -228,4 +313,168 @@ namespace GameRes.Formats.Leaf
public bool IsPacked { get { return _is_packed != 0; } }
}
#pragma warning restore 649,169
}
// --- LEAF LZSS COMPRESSION ---
internal static class LeafLzss
{
const int N = 4096;
const int F = 18;
const int THR = 2;
const int NIL = N;
public static byte[] Compress (byte[] input)
{
if (input.Length == 0) return new byte[0];
using (var outStream = new MemoryStream (input.Length))
{
// Arrays size = N + 257 to handle Root Nodes (N+1..N+256) safely
int[] lson = new int[N + 257];
int[] rson = new int[N + 257];
int[] dad = new int[N + 257];
byte[] text_buf = new byte[N + F - 1];
for (int j = N + 1; j <= N + 256; j++) rson[j] = NIL;
for (int j = 0; j < N; j++) dad[j] = NIL;
int match_position = 0, match_length = 0;
void InsertNode (int r_node)
{
int i, p, cmp;
int key_pos = r_node;
// Root for this character
p = N + 1 + text_buf[key_pos];
rson[r_node] = lson[r_node] = NIL;
match_length = 0;
cmp = 1; // Initial state
for (; ; )
{
if (cmp >= 0)
{
if (rson[p] != NIL) p = rson[p];
else { rson[p] = r_node; dad[r_node] = p; return; }
}
else
{
if (lson[p] != NIL) p = lson[p];
else { lson[p] = r_node; dad[r_node] = p; return; }
}
// Compare bytes only after finding a valid child node 'p' (buffer index)
for (i = 1; i < F; i++)
if ((cmp = text_buf[key_pos + i] - text_buf[p + i]) != 0) break;
if (i > match_length)
{
match_position = p;
match_length = i;
if (match_length >= F) break;
}
}
// Replace node logic
dad[r_node] = dad[p]; lson[r_node] = lson[p]; rson[r_node] = rson[p];
dad[lson[p]] = r_node; dad[rson[p]] = r_node;
if (rson[dad[p]] == p) rson[dad[p]] = r_node;
else lson[dad[p]] = r_node;
dad[p] = NIL;
}
void DeleteNode (int p)
{
int q;
if (dad[p] == NIL) return;
if (rson[p] == NIL) q = lson[p];
else if (lson[p] == NIL) q = rson[p];
else
{
q = lson[p];
if (rson[q] != NIL)
{
do { q = rson[q]; } while (rson[q] != NIL);
rson[dad[q]] = lson[q]; dad[lson[q]] = dad[q];
lson[q] = lson[p]; dad[lson[p]] = q;
}
rson[q] = rson[p]; dad[rson[p]] = q;
}
dad[q] = dad[p];
if (rson[dad[p]] == p) rson[dad[p]] = q;
else lson[dad[p]] = q;
dad[p] = NIL;
}
int code_buf_ptr = 1;
byte[] code_buf = new byte[17];
byte mask = 1;
int s = 0, r = N - F;
int len = 0;
for (int j = 0; j < r; j++) text_buf[j] = 0x20;
int bytes_read = 0;
for (len = 0; len < F && bytes_read < input.Length; len++)
text_buf[r + len] = input[bytes_read++];
if (len == 0) return new byte[0];
for (int j = 1; j <= F; j++) InsertNode (r - j);
InsertNode (r);
do
{
if (match_length > len) match_length = len;
if (match_length <= THR)
{
match_length = 1;
code_buf[0] |= mask;
code_buf[code_buf_ptr++] = text_buf[r];
}
else
{
code_buf[code_buf_ptr++] = (byte)(match_position & 0xFF);
code_buf[code_buf_ptr++] = (byte)(((match_position >> 4) & 0xF0) | (match_length - (THR + 1)));
}
if ((mask <<= 1) == 0)
{
outStream.Write (code_buf, 0, code_buf_ptr);
code_buf[0] = 0; code_buf_ptr = 1; mask = 1;
}
int last_match_length = match_length;
int i;
for (i = 0; i < last_match_length && bytes_read < input.Length; i++)
{
DeleteNode (s);
byte c = input[bytes_read++];
text_buf[s] = c;
if (s < F - 1) text_buf[s + N] = c;
s = (s + 1) & (N - 1);
r = (r + 1) & (N - 1);
InsertNode (r);
}
while (bytes_read == input.Length && i++ < last_match_length)
{
DeleteNode (s);
s = (s + 1) & (N - 1);
r = (r + 1) & (N - 1);
if (--len != 0) InsertNode (r);
}
} while (len > 0);
if (code_buf_ptr > 1)
outStream.Write (code_buf, 0, code_buf_ptr);
return outStream.ToArray();
}
}
}
}

View File

@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using GameRes.Utility;
namespace GameRes.Formats.Leaf
{
[Export(typeof(ArchiveFormat))]
public class VideoOpener : ArchiveFormat
{
public override string Tag { get { return "VIDEO/LEAF"; } }
public override string Description { get { return "Leaf/Aquaplus Video Container"; } }
public override uint Signature { get { return 0; } } // Dynamic verification
public override bool IsHierarchic { get { return false; } }
public override bool CanWrite { get { return false; } }
public override ArcFile TryOpen(ArcView file)
{
// Read the first 16 bytes to check the signature
if (file.MaxOffset < 16)
return null;
string ext = null;
uint head = file.View.ReadUInt32(0);
// 1. Check if it is WMV/ASF (Leaf standard)
// GUID: 30 26 B2 75 8E 66 CF 11 ...
// In Little Endian UInt64: 0x11CF668E75B22630
if (head == 0x75B22630)
{
ulong asfGuid = file.View.ReadUInt64(0);
if (asfGuid == 0x11CF668E75B22630)
{
ext = ".wmv";
}
}
// 2. Check if it is AVI (RIFF ... AVI )
else if (head == 0x46464952) // "RIFF"
{
// Check if the type at offset 8 is "AVI "
if (file.View.ReadUInt32(8) == 0x20495641)
{
ext = ".avi";
}
}
// 3. Check if it is MPEG (Reusing logic, in case an old game uses it)
else if (head == 0xBA010000)
{
ext = ".mpg";
}
if (ext == null)
return null;
// Create the virtual entry with the correct extension
var entry = new Entry
{
Name = Path.GetFileNameWithoutExtension(file.Name) + ext,
Type = "video",
Offset = 0,
Size = (uint)file.MaxOffset
};
return new ArcFile(file, this, new List<Entry> { entry });
}
}
}

View File

@@ -0,0 +1,99 @@
//! \file ArcPACK.cs
//! \date 2026 Feb 01
//! \brief NEKO WORKs Unity PACK resource archive.
//
// Copyright (C) 2026 by morkt
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using GameRes.Formats;
namespace GameRes.Formats.NEKOWORKs
{
[Export(typeof(ArchiveFormat))]
public class NekoWorksPackOpener : ArchiveFormat
{
public override string Tag { get { return "PACK/EXFS"; } }
public override string Description { get { return "NEKO WORKs resource archive"; } }
public override uint Signature { get { return 0x53465845; } } // 'EXFS'
public override bool IsHierarchic { get { return true; } }
public override bool CanWrite { get { return false; } }
public override ArcFile TryOpen(ArcView file)
{
if (!file.View.AsciiEqual(0, "EXFS"))
return null;
int fileCount = file.View.ReadInt32(0x0C);
uint infoOffset = file.View.ReadUInt32(0x10);
uint infoSize = file.View.ReadUInt32(0x18);
uint nameBlockSize = file.View.ReadUInt32(0x20);
uint baseDataOffset = file.View.ReadUInt32(0x28);
if (!IsSaneCount(fileCount))
return null;
long namesOffset = infoOffset + infoSize;
if (namesOffset + nameBlockSize > file.MaxOffset)
return null;
byte[] nameData = file.View.ReadBytes(namesOffset, nameBlockSize);
var nameList = new List<string>(fileCount);
int start = 0;
for (int i = 0; i < nameData.Length; ++i)
{
if (nameData[i] == (byte)'\n')
{
if (i > start)
nameList.Add(System.Text.Encoding.UTF8.GetString(nameData, start, i - start));
start = i + 1;
}
}
if (nameList.Count < fileCount)
return null;
var dir = new List<Entry>(fileCount);
long indexOffset = infoOffset;
for (int i = 0; i < fileCount; ++i)
{
long entryPos = indexOffset + i * 0x20;
uint dataOffset = file.View.ReadUInt32(entryPos + 0x10);
uint dataSize = file.View.ReadUInt32(entryPos + 0x18);
var entry = Create<Entry>(nameList[i]);
entry.Offset = baseDataOffset + dataOffset;
entry.Size = dataSize;
if (!entry.CheckPlacement(file.MaxOffset))
return null;
dir.Add(entry);
}
return new ArcFile(file, this, dir);
}
}
}

View File

@@ -313,7 +313,7 @@ namespace GameRes.Formats.NeXAS
static private byte[] ZstdDecompress (Stream s, uint unpackedSize)
{
using (var ds = new ZstdNet.DecompressionStream (s))
using (var ds = new ZstdSharp.DecompressionStream (s))
{
var dst = new byte[unpackedSize];
ds.Read (dst, 0, dst.Length);

View File

@@ -527,7 +527,7 @@ namespace GameRes.Formats.NitroPlus
m_stream = new DeflateStream (m_stream, CompressionMode.Decompress);
break;
case 3:
m_stream = new ZstdNet.DecompressionStream (m_stream);
m_stream = new ZstdSharp.DecompressionStream (m_stream);
break;
}
}

View File

@@ -126,8 +126,8 @@ namespace GameRes.Formats.PkWare
internal ArcFile OpenZipArchive (ArcView file, Stream input)
{
SharpZip.ZipStrings.CodePage = Properties.Settings.Default.ZIPEncodingCP;
var zip = new SharpZip.ZipFile (input);
var sc = SharpZip.StringCodec.FromCodePage (Properties.Settings.Default.ZIPEncodingCP);
var zip = new SharpZip.ZipFile (input, false, sc);
try
{
var files = zip.Cast<SharpZip.ZipEntry>().Where (z => !z.IsDirectory);

View File

@@ -12,7 +12,7 @@ namespace GameRes.Formats.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.10.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")]
public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -585,20 +585,7 @@ namespace GameRes.Formats.Properties {
this["BELLTitle"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string BELLDATATitle
{
get {
return ((string)(this["BELLDATATitle"]));
}
set {
this["BELLDATATitle"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
@@ -862,5 +849,17 @@ namespace GameRes.Formats.Properties {
this["TIM2AlphaFormat"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string BELLDATATitle {
get {
return ((string)(this["BELLDATATitle"]));
}
set {
this["BELLDATATitle"] = value;
}
}
}
}

View File

@@ -209,5 +209,8 @@
<Setting Name="TIM2AlphaFormat" Type="System.String" Scope="User">
<Value Profile="(Default)">RGBA</Value>
</Setting>
<Setting Name="BELLDATATitle" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
</Settings>
</SettingsFile>

374
ArcFormats/Psp/ArcGim.cs Normal file
View File

@@ -0,0 +1,374 @@
using System;
using System.ComponentModel.Composition;
using System.IO;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using GameRes.Utility;
namespace GameRes.Formats.Psp
{
internal class GimMetaData : ImageMetaData
{
public int ImageInfoOffset;
public int PaletteInfoOffset;
public int PaletteBlockEnd;
public bool IsLittleEndian;
public int Format;
public int Order; // 0=Linear, 1=Swizzled
public int ImgDataRelOffset;
public int PalDataRelOffset;
public int BufferWidth; // Aligned width
}
[Export(typeof(ImageFormat))]
public class GimFormat : ImageFormat
{
public override string Tag { get { return "GIM"; } }
public override string Description { get { return "Sony GIM Image"; } }
public override uint Signature { get { return 0; } }
public override ImageMetaData ReadMetaData(IBinaryStream file)
{
var header = file.ReadBytes(16);
if (header.Length < 16) return null;
// Header check for Endianness detection
bool littleEndian = true;
if (header[0] == 'M' && header[1] == 'I' && header[2] == 'G') littleEndian = true;
else if (header[0] == 'G' && header[1] == 'I' && header[2] == 'M') littleEndian = false;
else return null;
// Read the entire stream into an array to facilitate navigation
// GIMs are small, so this is safe and fast.
byte[] data = new byte[file.Length];
file.Position = 0;
file.Read(data, 0, (int)file.Length);
int imageInfoOffset = -1;
int paletteInfoOffset = -1;
int paletteBlockEnd = -1;
int offset = 0x10;
int loop = 0;
// Block scanning loop (Verviewer style)
while (offset + 0x10 <= data.Length && loop < 128)
{
ushort id = ReadUInt16(data, offset, littleEndian);
// 0x02=EndFile, 0x03=EndImage (Skip), 0x04=Image, 0x05=Palette, 0xFF=FileInfo
if (id == 0xFF) break;
uint size = ReadUInt32(data, offset + 4, littleEndian);
uint next = ReadUInt32(data, offset + 8, littleEndian);
uint headerSize = ReadUInt32(data, offset + 0xC, littleEndian);
if (size < headerSize || headerSize == 0) break; // Invalid data
// "Next" logic: If 0, usually the next block is sequential (size)
int nextOffset = (next != 0) ? (int)next : (int)size;
int blockStart = offset;
int blockEnd = blockStart + (int)size;
int subHeader = blockStart + (int)headerSize;
if (blockEnd > data.Length) break;
if (id == 4) // Image Section
{
if (imageInfoOffset < 0) imageInfoOffset = subHeader;
}
else if (id == 5) // Palette Section
{
if (paletteInfoOffset < 0)
{
paletteInfoOffset = subHeader;
paletteBlockEnd = blockEnd;
}
}
offset = blockStart + nextOffset;
loop++;
}
if (imageInfoOffset < 0) return null;
ushort imgFormat = ReadUInt16(data, imageInfoOffset + 4, littleEndian);
ushort pixelOrder = ReadUInt16(data, imageInfoOffset + 6, littleEndian);
ushort width = ReadUInt16(data, imageInfoOffset + 8, littleEndian);
ushort height = ReadUInt16(data, imageInfoOffset + 0xA, littleEndian);
ushort bpp = ReadUInt16(data, imageInfoOffset + 0xC, littleEndian);
uint imgRel = ReadUInt32(data, imageInfoOffset + 0x1C, littleEndian);
uint palRel = 0;
if (paletteInfoOffset > 0)
palRel = ReadUInt32(data, paletteInfoOffset + 0x1C, littleEndian);
// Texture Alignment (Buffer Width)
// PSP aligns in blocks of 16 bytes (128 bits)
int align = 16;
int pixelsPerBlock = (align * 8) / Math.Max(1, (int)bpp);
int bufferWidth = (width + pixelsPerBlock - 1) & ~(pixelsPerBlock - 1);
return new GimMetaData
{
Width = width,
Height = height,
BPP = bpp,
Format = imgFormat,
Order = pixelOrder,
BufferWidth = bufferWidth,
ImageInfoOffset = imageInfoOffset,
PaletteInfoOffset = paletteInfoOffset,
PaletteBlockEnd = paletteBlockEnd,
ImgDataRelOffset = (int)imgRel,
PalDataRelOffset = (int)palRel,
IsLittleEndian = littleEndian
};
}
public override ImageData Read(IBinaryStream file, ImageMetaData info)
{
var meta = (GimMetaData)info;
byte[] data = new byte[file.Length];
file.Position = 0;
file.Read(data, 0, (int)file.Length);
int imgDataOffset = meta.ImageInfoOffset + meta.ImgDataRelOffset;
// Safe pixel buffer reading
int width = (int)meta.Width;
int height = (int)meta.Height;
int bpp = meta.BPP;
int bufferWidth = meta.BufferWidth;
// Internal PSP Stride (can be larger than image width)
int bufferStride = (bufferWidth * bpp) / 8;
int totalBytes = bufferStride * height;
if (imgDataOffset + totalBytes > data.Length)
totalBytes = Math.Max(0, data.Length - imgDataOffset);
byte[] pixels = new byte[totalBytes];
Buffer.BlockCopy(data, imgDataOffset, pixels, 0, totalBytes);
// --- UNSWIZZLE ---
if (meta.Order == 1)
{
pixels = UnswizzlePSP(pixels, width, height, bufferWidth, bpp);
}
else
{
// If linear but with lateral padding, remove it
if (bufferWidth != width)
pixels = RemovePadding(pixels, width, height, bufferWidth, bpp);
// If 4bpp Linear, we still need to fix Nibbles
if (bpp == 4)
SwapNibbles(pixels);
}
// --- PALETTE ---
BitmapPalette palette = null;
if (meta.Format == 0x04 || meta.Format == 0x05)
{
if (meta.PaletteInfoOffset > 0 && meta.PaletteBlockEnd > 0)
{
int palDataOffset = meta.PaletteInfoOffset + meta.PalDataRelOffset;
ushort palFmt = ReadUInt16(data, meta.PaletteInfoOffset + 4, meta.IsLittleEndian);
int entrySize = (palFmt == 3) ? 4 : 2;
int palBytes = meta.PaletteBlockEnd - palDataOffset;
int colorCount = palBytes / entrySize;
// Limit colors by BPP
if (meta.Format == 0x04) colorCount = Math.Min(colorCount, 16);
else if (meta.Format == 0x05) colorCount = Math.Min(colorCount, 256);
if (palDataOffset + (colorCount * entrySize) <= data.Length)
{
Color[] colors = new Color[colorCount];
for(int i=0; i<colorCount; i++)
{
int pOff = palDataOffset + (i * entrySize);
if (entrySize == 4) // RGBA8888
{
byte r = data[pOff];
byte g = data[pOff+1];
byte b = data[pOff+2];
byte a = data[pOff+3];
// IMPORTANT: Swap R and B to fix "blue face"
colors[i] = Color.FromArgb(a, r, g, b);
}
else // 16 bit
{
ushort p = ReadUInt16(data, pOff, meta.IsLittleEndian);
colors[i] = DecodePspColor(p, palFmt);
}
}
palette = new BitmapPalette(colors);
}
}
}
PixelFormat format = PixelFormats.Bgra32;
int outputStride = (width * bpp + 7) / 8;
byte[] outputPixels = pixels;
if (bpp == 8) format = PixelFormats.Indexed8;
else if (bpp == 4) format = PixelFormats.Indexed4;
else if (bpp == 16)
{
format = PixelFormats.Bgra32;
outputPixels = Convert16to32(pixels, width, height, meta.Format, meta.IsLittleEndian);
outputStride = width * 4;
}
else if (bpp == 32) format = PixelFormats.Bgra32;
return ImageData.Create(info, format, palette, outputPixels, outputStride);
}
public override void Write(Stream file, ImageData image)
{
throw new NotImplementedException();
}
// --- HELPERS ---
static ushort ReadUInt16(byte[] data, int offset, bool littleEndian)
{
if (offset + 1 >= data.Length) return 0;
return littleEndian
? (ushort)(data[offset] | (data[offset + 1] << 8))
: (ushort)((data[offset] << 8) | data[offset + 1]);
}
static uint ReadUInt32(byte[] data, int offset, bool littleEndian)
{
if (offset + 3 >= data.Length) return 0;
return littleEndian
? (uint)(data[offset] | (data[offset + 1] << 8) | (data[offset + 2] << 16) | (data[offset + 3] << 24))
: (uint)((data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]);
}
static byte[] UnswizzlePSP(byte[] src, int width, int height, int bufferWidth, int bpp)
{
// 4BPP TRICK: Treat 4BPP as 8BPP with half width for coordinate calculation.
// This moves bytes correctly. THEN we swap nibbles.
int procBpp = bpp;
int procWidth = width;
int procBufferWidth = bufferWidth;
if (bpp == 4)
{
procBpp = 8;
procWidth = width / 2;
procBufferWidth = bufferWidth / 2;
}
int blockWidth = 16;
int blockHeight = 8;
if (procBpp == 16) { blockWidth = 16; blockHeight = 4; }
else if (procBpp == 32) { blockWidth = 8; blockHeight = 4; }
int dstStride = (procWidth * procBpp) / 8;
byte[] dst = new byte[dstStride * height];
int bppByte = procBpp / 8;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < procWidth; x++)
{
int bx = x / blockWidth;
int by = y / blockHeight;
int mx = x % blockWidth;
int my = y % blockHeight;
int blocksPerRow = procBufferWidth / blockWidth;
int blockSize = blockWidth * blockHeight * bppByte;
int blockIdx = (by * blocksPerRow) + bx;
int srcOffset = (blockIdx * blockSize) + ((my * blockWidth + mx) * bppByte);
int dstOffset = (y * dstStride) + (x * bppByte);
if (srcOffset + bppByte <= src.Length && dstOffset + bppByte <= dst.Length)
{
// For 4bpp, bppByte is 1 (because we simulate 8bpp).
byte val = src[srcOffset];
// 4BPP LINES FIX:
// Unswizzle moved the correct Byte to the correct place.
// Now we need to invert nibbles (High/Low) because WPF reads differently from PSP.
if (bpp == 4)
{
val = (byte)(((val & 0x0F) << 4) | ((val & 0xF0) >> 4));
}
dst[dstOffset] = val;
// For other formats (>8bpp), normal copy
if (bpp > 8)
{
for(int k=1; k<bppByte; k++) dst[dstOffset+k] = src[srcOffset+k];
}
}
}
}
return dst;
}
static byte[] RemovePadding(byte[] src, int width, int height, int bufferWidth, int bpp)
{
int srcStride = (bufferWidth * bpp + 7) / 8;
int dstStride = (width * bpp + 7) / 8;
byte[] dst = new byte[dstStride * height];
for (int y = 0; y < height; y++)
{
int copyLen = Math.Min(srcStride, dstStride);
int sOff = y * srcStride;
int dOff = y * dstStride;
if (sOff + copyLen <= src.Length)
Array.Copy(src, sOff, dst, dOff, copyLen);
}
return dst;
}
static void SwapNibbles(byte[] data)
{
for (int i = 0; i < data.Length; i++)
{
byte b = data[i];
data[i] = (byte)(((b & 0x0F) << 4) | ((b & 0xF0) >> 4));
}
}
Color DecodePspColor(ushort v, int fmt)
{
int r=0, g=0, b=0, a=255;
if (fmt == 0) { // 5650
r=(v&0x1F)<<3; g=((v>>5)&0x3F)<<2; b=((v>>11)&0x1F)<<3;
} else if (fmt == 1) { // 5551
r=(v&0x1F)<<3; g=((v>>5)&0x1F)<<3; b=((v>>10)&0x1F)<<3; a=(v>>15)!=0?255:0;
} else if (fmt == 2) { // 4444
r=(v&0xF)<<4; g=((v>>4)&0xF)<<4; b=((v>>8)&0xF)<<4; a=((v>>12)&0xF)<<4;
}
// Swap R and B to fix inverted colors
return Color.FromArgb((byte)a, (byte)b, (byte)g, (byte)r);
}
byte[] Convert16to32(byte[] inp, int w, int h, int fmt, bool le)
{
byte[] outp = new byte[w * h * 4];
for(int i=0; i<w*h; i++) {
if(i*2+1>=inp.Length) break;
ushort v = le
? (ushort)(inp[i*2] | (inp[i*2+1] << 8))
: (ushort)((inp[i*2] << 8) | inp[i*2+1]);
Color c = DecodePspColor(v, fmt);
int o = i*4;
outp[o]=c.B; outp[o+1]=c.G; outp[o+2]=c.R; outp[o+3]=c.A;
}
return outp;
}
}
}

View File

Binary file not shown.

View File

@@ -27,7 +27,9 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using GameRes.Compression;
using GameRes.Formats.Strings;
using GameRes.Utility;
namespace GameRes.Formats.Silky
@@ -39,7 +41,7 @@ namespace GameRes.Formats.Silky
public override string Description { get { return "AI6WIN engine resource archive"; } }
public override uint Signature { get { return 0; } }
public override bool IsHierarchic { get { return true; } }
public override bool CanWrite { get { return false; } }
public override bool CanWrite { get { return true; } }
public Ai6Opener ()
{
@@ -96,5 +98,108 @@ namespace GameRes.Formats.Silky
var input = arc.File.CreateStream (entry.Offset, entry.Size);
return new LzssStream (input);
}
public override void Create (Stream output, IEnumerable<Entry> list, ResourceOptions options, EntryCallback callback)
{
int count = list.Count ();
if (0 == count)
throw new InvalidOperationException ("Archive is empty");
uint index_size = (uint)(count * (0x104 + 12));
uint data_offset = 4 + index_size;
if (null != callback)
callback (count + 1, null, null);
var entries = new List<IndexEntry> (count);
uint current_offset = data_offset;
int callback_count = 0;
foreach (var entry in list)
{
if (null != callback)
callback (callback_count++, entry, arcStrings.MsgAddingFile);
string name = entry.Name;
if (name.Contains ("\\"))
name = name.Replace ("\\", "/");
try
{
long file_size = 0;
using (var input = File.OpenRead (entry.Name))
{
file_size = input.Length;
}
if (file_size > uint.MaxValue)
throw new FileLoadException ("File is too large for this format.");
var index_entry = new IndexEntry
{
SourcePath = entry.Name,
ArchiveName = name,
Size = (uint)file_size,
UnpackedSize = (uint)file_size,
Offset = current_offset
};
entries.Add (index_entry);
current_offset += (uint)file_size;
}
catch (Exception X)
{
// 修复点:此处改用硬编码字符串或尝试 MsgFileError
throw new InvalidFileName (entry.Name, "Error opening file", X);
}
}
if (null != callback)
callback (callback_count++, null, arcStrings.MsgWritingIndex);
using (var writer = new BinaryWriter (output))
{
writer.Write ((uint)count);
foreach (var entry in entries)
{
var name_bytes = Encodings.cp932.GetBytes (entry.ArchiveName);
var name_buf = new byte[0x104];
int copyLength = Math.Min (name_bytes.Length, name_buf.Length);
Array.Copy (name_bytes, name_buf, copyLength);
byte key = (byte)(name_bytes.Length + 1);
for (int i = 0; i < copyLength; ++i)
{
name_buf[i] = (byte)((name_buf[i] + key) & 0xFF);
key--;
}
writer.Write (name_buf);
writer.Write (Binary.BigEndian (entry.Size));
writer.Write (Binary.BigEndian (entry.UnpackedSize));
writer.Write (Binary.BigEndian (entry.Offset));
}
foreach (var entry in entries)
{
using (var input = File.OpenRead (entry.SourcePath))
{
input.CopyTo (output);
}
}
}
}
private class IndexEntry
{
public string SourcePath { get; set; }
public string ArchiveName { get; set; }
public uint Size { get; set; }
public uint UnpackedSize { get; set; }
public uint Offset { get; set; }
}
}
}

View File

@@ -754,14 +754,14 @@ namespace GameRes.Formats.Strings {
/// <summary>
/// Looks up a localized string similar to Choose Tim2 image alpha format.
/// It can&apos;t be read correctly from the file.
///It can&apos;t be read correctly from the file..
/// </summary>
public static string Tim2AlphaFormat {
get {
return ResourceManager.GetString("Tim2AlphaFormat", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Hex number.
/// </summary>

View File

@@ -0,0 +1,406 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AMIBaseArchive" xml:space="preserve">
<value>原壓縮檔案</value>
</data>
<data name="AMIBaseTooltip" xml:space="preserve">
<value>新的壓縮檔案將會包含原檔案中的項目。</value>
</data>
<data name="AMIChooseBase" xml:space="preserve">
<value>請選擇原壓縮檔案</value>
</data>
<data name="AMIDescription" xml:space="preserve">
<value>Amaterasu Translations Muv-Luv 壓縮檔案</value>
</data>
<data name="AMINoFiles" xml:space="preserve">
<value>未找到適合AMI壓縮檔案的項目。</value>
</data>
<data name="ArcEncryptedNotice" xml:space="preserve">
<value>壓縮檔案已加密。
請選擇正確的加密方式。</value>
</data>
<data name="ArcNoEncryption" xml:space="preserve">
<value>沒有加密。</value>
</data>
<data name="ArcReset" xml:space="preserve">
<value>重置</value>
</data>
<data name="GRPDescription" xml:space="preserve">
<value>âge專用圖像格式</value>
</data>
<data name="GSCDescription" xml:space="preserve">
<value>Liar-soft專用腳本格式</value>
</data>
<data name="INTCreationNotice" xml:space="preserve">
<value>尚不支持創建加密壓縮檔案。</value>
</data>
<data name="INTDescription" xml:space="preserve">
<value>CatSystem2引擎壓縮檔案</value>
</data>
<data name="INTKeyRequirement" xml:space="preserve">
<value>密鑰是一個32位的16進制整數</value>
</data>
<data name="INTLabelNumericKey" xml:space="preserve">
<value>密鑰</value>
</data>
<data name="INTNotice" xml:space="preserve">
<value>壓縮檔案目錄已加密。</value>
</data>
<data name="KogadoDescription" xml:space="preserve">
<value>工畫堂引擎壓縮檔案</value>
</data>
<data name="LabelPassphrase" xml:space="preserve">
<value>密碼</value>
</data>
<data name="LabelScheme" xml:space="preserve">
<value>方式</value>
</data>
<data name="LWGDescription" xml:space="preserve">
<value>Liar-soft圖像檔案</value>
</data>
<data name="MsgAddingFile" xml:space="preserve">
<value>正在添加檔案……</value>
</data>
<data name="MsgCalculatingChecksum" xml:space="preserve">
<value>正在計算校驗和……</value>
</data>
<data name="MsgCompressingIndex" xml:space="preserve">
<value>正在壓縮索引……</value>
</data>
<data name="MsgCreationKeyRequired" xml:space="preserve">
<value>創建壓縮檔案需要密鑰。</value>
</data>
<data name="MsgEncNotImplemented" xml:space="preserve">
<value>加密方式暫不支持。</value>
</data>
<data name="MsgExtensionTooLong" xml:space="preserve">
<value>檔案擴展名太長。</value>
</data>
<data name="MsgFileNameTooLong" xml:space="preserve">
<value>檔案名太長。</value>
</data>
<data name="MsgIllegalCharacters" xml:space="preserve">
<value>檔案名中包含非法字符。</value>
</data>
<data name="MsgInvalidImageFormat" xml:space="preserve">
<value>{0}: 無法識別圖像格式。</value>
</data>
<data name="MsgInvalidVersion" xml:space="preserve">
<value>無效的檔案版本。</value>
</data>
<data name="MsgNoExtension" xml:space="preserve">
<value>檔案名需要包含擴展名。</value>
</data>
<data name="MsgTooManyFiles" xml:space="preserve">
<value>檔案數目超過壓縮檔案限制。</value>
</data>
<data name="MsgUpdatingIndex" xml:space="preserve">
<value>正在更新索引……</value>
</data>
<data name="MsgWritingIndex" xml:space="preserve">
<value>正在建立索引……</value>
</data>
<data name="NPACompressContents" xml:space="preserve">
<value>壓縮內容</value>
</data>
<data name="NPADescription" xml:space="preserve">
<value>Nitro+壓縮檔案</value>
</data>
<data name="NPAKeys" xml:space="preserve">
<value>密鑰
(未加密內容仍需要)</value>
</data>
<data name="NPASteinsGateDescription" xml:space="preserve">
<value>Nitro+ Steins;Gate壓縮檔案</value>
</data>
<data name="NSADescription" xml:space="preserve">
<value>NScripter引擎壓縮檔案</value>
</data>
<data name="ONSArchiveType" xml:space="preserve">
<value>壓縮檔案類型</value>
</data>
<data name="ONSCompression" xml:space="preserve">
<value>壓縮方式</value>
</data>
<data name="ONSCompressionNone" xml:space="preserve">
<value>無</value>
</data>
<data name="PDDescription" xml:space="preserve">
<value>Flying Shine壓縮檔案</value>
</data>
<data name="PDScrambleContents" xml:space="preserve">
<value>打亂內容</value>
</data>
<data name="RPADescription" xml:space="preserve">
<value>Ren'Py引擎壓縮檔案</value>
</data>
<data name="RPALabelKey" xml:space="preserve">
<value>32位密鑰</value>
</data>
<data name="SCRDescription" xml:space="preserve">
<value>Amaterasu Translations Muv-Luv腳本檔案</value>
</data>
<data name="SGLabelEncoding" xml:space="preserve">
<value>檔案名編碼</value>
</data>
<data name="TooltipHex" xml:space="preserve">
<value>十六進制數</value>
</data>
<data name="WARCLabelLength" xml:space="preserve">
<value>檔案名最大長度
(不包括擴展名)</value>
</data>
<data name="XFLDescription" xml:space="preserve">
<value>Liar-soft遊戲壓縮檔案</value>
</data>
<data name="XP3CompressContents" xml:space="preserve">
<value>壓縮內容</value>
</data>
<data name="XP3CompressHeader" xml:space="preserve">
<value>壓縮目錄</value>
</data>
<data name="XP3Description" xml:space="preserve">
<value>KiriKiri引擎壓縮檔案</value>
</data>
<data name="XP3LabelVersion" xml:space="preserve">
<value>版本</value>
</data>
<data name="XP3RetainStructure" xml:space="preserve">
<value>保持目錄結構</value>
</data>
<data name="YPFDescription" xml:space="preserve">
<value>Yu-Ris引擎壓縮檔案</value>
</data>
<data name="YPFLabelKey" xml:space="preserve">
<value>8位密鑰</value>
</data>
<data name="YPFLabelVersion" xml:space="preserve">
<value>壓縮檔案版本</value>
</data>
<data name="YPFNotice" xml:space="preserve">
<value>壓縮檔案的目錄已加密。
請選擇正確的加密方式。</value>
</data>
<data name="LabelEncScheme" xml:space="preserve">
<value>加密方式</value>
</data>
<data name="DPKKeys" xml:space="preserve">
<value>密鑰</value>
</data>
<data name="ArcDefault" xml:space="preserve">
<value>預設</value>
</data>
<data name="ArcHex32Bit" xml:space="preserve">
<value>32位十六進制數</value>
</data>
<data name="KCAPDefault" xml:space="preserve">
<value>預設</value>
</data>
<data name="MBLNotice" xml:space="preserve">
<value>壓縮檔案包含已加密的腳本。
請選擇加密方式或輸入密碼。</value>
</data>
<data name="ArcTitleOrPassword" xml:space="preserve">
<value>請選擇遊戲名稱或輸入密碼</value>
</data>
<data name="RPMEncryptedNotice" xml:space="preserve">
<value>檔案與RPM壓縮檔案格式相似,
但無法猜測正確的密鑰。
請選擇正確的加密方式。</value>
</data>
<data name="QLIEDefaultScheme" xml:space="preserve">
<value>使用預設加密方式</value>
</data>
<data name="INTChooseExe" xml:space="preserve">
<value>請選擇遊戲的EXE檔案</value>
</data>
<data name="INTExeButton" xml:space="preserve">
<value>檢查EXE</value>
</data>
<data name="INTExeFiles" xml:space="preserve">
<value>可執行檔案</value>
</data>
<data name="INTMessage1" xml:space="preserve">
<value>請按「檢查EXE」按鈕在遊戲程序檔案中尋找密鑰。</value>
</data>
<data name="INTMessage2" xml:space="preserve">
<value>或者,您也可以輸入壓縮檔案的密鑰或者選擇一個現成的加密方式。</value>
</data>
<data name="INTKeyNotFound" xml:space="preserve">
<value>在{0}當中沒有找到密鑰。</value>
</data>
<data name="ArcIgnoreEncryption" xml:space="preserve">
<value>忽略加密。</value>
</data>
<data name="ArcImageEncrypted" xml:space="preserve">
<value>圖像已加密。</value>
</data>
<data name="MCGChoose" xml:space="preserve">
<value>請選擇遊戲名稱或輸入密鑰</value>
</data>
<data name="MCGLabelKey" xml:space="preserve">
<value>8位加密密鑰</value>
</data>
<data name="MCAEncryptedNotice" xml:space="preserve">
<value>壓縮檔案的內容已被加密。</value>
</data>
<data name="YPFTryGuess" xml:space="preserve">
<value>嘗試猜測</value>
</data>
<data name="AGSMightBeEncrypted" xml:space="preserve">
<value>壓縮檔案可能被加密,選擇適當的加密方案。</value>
</data>
<data name="XP3EncryptedNotice" xml:space="preserve">
<value>壓縮檔案可能被加密,選擇適當的加密方案。</value>
</data>
<data name="GALChoose" xml:space="preserve">
<value>請選擇遊戲名稱或輸入密鑰</value>
</data>
<data name="GYUImageEncrypted" xml:space="preserve">
<value>圖像已加密。
請選擇正確的加密方式。</value>
</data>
<data name="FJSYSNotice" xml:space="preserve">
<value>壓縮檔案包含已加密的腳本。
請選擇加密方式或輸入密碼。</value>
</data>
<data name="RCTApplyMask" xml:space="preserve">
<value>從RC8位圖中加載透明度數據</value>
</data>
<data name="RCTOverlayFrames" xml:space="preserve">
<value>自動組合增量幀</value>
</data>
<data name="ZIPEncryptedNotice" xml:space="preserve">
<value>壓縮檔案的內容已被加密。</value>
</data>
<data name="OGGFixCrc" xml:space="preserve">
<value>修復Ogg檔案校驗和</value>
</data>
<data name="DefaultEncoding" xml:space="preserve">
<value>預設檔案名編碼</value>
</data>
<data name="ODNAudioSampleRate" xml:space="preserve">
<value>預設音頻採樣率</value>
</data>
<data name="Tim2AlphaFormat" xml:space="preserve">
<value>選擇Tim2圖片透明度格式。
這無法從檔案中正確獲取。</value>
</data>
</root>

View File

@@ -102,8 +102,8 @@ namespace GameRes.Formats.VnMaker
internal ArcFile OpenZipArchive (ArcView file, Stream input)
{
SharpZip.ZipStrings.CodePage = Properties.Settings.Default.ZIPEncodingCP;
var zip = new SharpZip.ZipFile (input);
var sc = SharpZip.StringCodec.FromCodePage (Properties.Settings.Default.ZIPEncodingCP);
var zip = new SharpZip.ZipFile (input, false, sc);
try
{
var files = zip.Cast<SharpZip.ZipEntry>().Where (z => !z.IsDirectory);

View File

@@ -31,7 +31,6 @@ using System.ComponentModel.Composition;
using GameRes.Compression;
using GameRes.Formats.Strings;
using GameRes.Utility;
using Snappy;
namespace GameRes.Formats.YuRis
{
@@ -185,7 +184,7 @@ namespace GameRes.Formats.YuRis
{
var compress_data = new byte[entry.Size];
input.Read(compress_data, 0, compress_data.Length);
var decomprrss_data = SnappyCodec.Uncompress(compress_data);
var decomprrss_data = Snappier.Snappy.DecompressToArray (compress_data);
input = new BinMemoryStream(decomprrss_data, entry.Name);
break;
}

134
ArcFormats/aNCHOR/ArcFPD.cs Normal file
View File

@@ -0,0 +1,134 @@
//! \file ArcFPD.cs
//! \date 2026-01-19
//! \brief AGES Mk2 resource archive.
//
// Copyright (C) 2026 by morkt
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Text;
using GameRes.Compression;
using GameRes.Utility;
namespace GameRes.Formats.Anchor {
internal class FpdArchive : ArcFile {
public readonly byte[] Key;
public FpdArchive(ArcView arc, ArchiveFormat impl, ICollection<Entry> dir, byte[] key) : base (arc, impl, dir) {
Key = key;
}
}
[Export(typeof(ArchiveFormat))]
public class FpdOpener : ArchiveFormat {
public override string Tag { get { return "FPD"; } }
public override string Description { get { return "AGES Mk2 resource archive"; } }
public override uint Signature { get { return 0x00445046; } } // 'FPD\x00'
public override bool IsHierarchic { get { return true; } }
public override bool CanWrite { get { return false; } }
public override ArcFile TryOpen(ArcView file) {
int version = Binary.BigEndian(file.View.ReadInt32(4));
if (version != 2)
return null;
int count = (int)Binary.BigEndian(file.View.ReadInt64(8));
if (!IsSaneCount(count))
return null;
long data_start = Binary.BigEndian(file.View.ReadInt64(0x10));
long offset = 0x38;
if (data_start < count * 32 + offset)
return null;
uint index_size = (uint)(data_start - offset);
var key = QueryKey();
var dir = new List<Entry>(count);
using (var input = file.CreateStream(offset, (uint)(data_start - offset)))
using (var decrypted = new ByteStringEncryptedStream(input, key))
using (var reader = new BinaryReader(decrypted)) {
var name_offsets = new List<long>(count);
for (int i = 0; i < count; i++) {
long name_offset = Binary.BigEndian(reader.ReadInt64());
long data_offset = Binary.BigEndian(reader.ReadInt64());
long size = Binary.BigEndian(reader.ReadInt64());
long unpacked_size = Binary.BigEndian(reader.ReadInt64());
var entry = new PackedEntry {
Offset = data_start + data_offset,
Size = (uint)size,
UnpackedSize = (uint)unpacked_size,
IsPacked = unpacked_size != 0
};
if (!entry.CheckPlacement(file.MaxOffset))
return null;
dir.Add(entry);
name_offsets.Add(name_offset);
}
var name_block = reader.ReadBytes((int)(data_start - offset - count * 32));
using (var mem = new MemoryStream(name_block))
using (var stream = new ZLibStream(mem, CompressionMode.Decompress))
using (var output = new MemoryStream()) {
stream.CopyTo(output);
var names = output.ToArray();
for (int i = 0; i < count; i++) {
dir[i].Name = Binary.GetCString(names, (int)name_offsets[i], Encoding.UTF8);
dir[i].Type = FormatCatalog.Instance.GetTypeFromName(dir[i].Name);
}
}
return new FpdArchive(file, this, dir, key);
}
}
public override Stream OpenEntry(ArcFile arc, Entry entry) {
var farc = arc as FpdArchive;
var pent = entry as PackedEntry;
var input = farc.File.CreateStream(entry.Offset, entry.Size);
var decrypted = new ByteStringEncryptedStream(input, farc.Key);
if (pent.IsPacked)
return new ZLibStream(decrypted, CompressionMode.Decompress);
else
return decrypted;
// TODO: epk decryption
}
byte[] QueryKey() {
return DefaultScheme.ArchiveKey;
}
FpdScheme DefaultScheme = new FpdScheme();
public override ResourceScheme Scheme {
get { return DefaultScheme; }
set { DefaultScheme = (FpdScheme)value; }
}
}
[Serializable]
public class FpdScheme : ResourceScheme {
public byte[] ArchiveKey;
public byte[] EpkKey;
}
}

View File

@@ -0,0 +1,55 @@
//! \file AudioFCD.cs
//! \date 2026-01-19
//! \brief AGES Mk2 audio format.
//
// Copyright (C) 2026 by morkt
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
using System;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
namespace GameRes.Formats.Anchor
{
[Export(typeof(AudioFormat))]
public class FcdAudio : AudioFormat
{
public override string Tag { get { return "FCD"; } }
public override string Description { get { return "AGES Mk2 audio format"; } }
public override uint Signature { get { return 0x00444346; } } // 'FCD\x00'
public FcdAudio ()
{
Extensions = new string[] { "fcd" };
}
public override SoundInput TryOpen (IBinaryStream file)
{
file.Position = 4;
// guess: big endian, version=2, type=0 (ogg), offset=0xC
byte[] data = { 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x4F, 0x67, 0x67, 0x53 };
if (!file.ReadBytes (0x0C).SequenceEqual (data))
throw new NotSupportedException();
return new OggInput (new StreamRegion (file.AsStream, 0x0C));
}
}
}

188
ArcFormats/aPLibStream.cs Normal file
View File

@@ -0,0 +1,188 @@
//! \file aPLibStream.cs
//! \date 2026-01-09
/*
* aPLib compression library - the smaller the better :)
*
* C depacker
*
* Copyright (c) 1998-2014 Joergen Ibsen
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*/
// C# port by scientificworld
using System;
using System.Collections.Generic;
using System.IO;
namespace GameRes.Compression {
public sealed class aPLibCoroutine : Decompressor {
Stream m_input;
uint m_tag;
uint m_bitcount;
public override void Initialize (Stream input) {
m_input = input;
}
protected override IEnumerator<int> Unpack () {
uint offs, len, R0, LWM;
var hist = new List<byte>();
m_bitcount = 0;
R0 = uint.MaxValue; // (uint) -1
LWM = 0;
m_buffer[m_pos] = ReadByte();
hist.Add(m_buffer[m_pos++]);
if (--m_length == 0)
yield return m_pos;
while (true) {
if (GetBit() != 0) {
if (GetBit() != 0) {
if (GetBit() != 0) {
offs = 0;
for (int i = 0; i < 4; i++) {
offs = (offs << 1) + GetBit();
}
if (offs != 0) {
m_buffer[m_pos] = hist[(int)(hist.Count - offs)];
}
else {
m_buffer[m_pos] = 0x00;
}
hist.Add(m_buffer[m_pos++]);
LWM = 0;
if (--m_length == 0)
yield return m_pos;
}
else {
offs = (uint)ReadByte();
len = 2 + (offs & 0x0001);
offs >>= 1;
if (offs != 0) {
for (; len != 0; len--) {
m_buffer[m_pos] = hist[(int)(hist.Count - offs)];
hist.Add(m_buffer[m_pos++]);
if (--m_length == 0)
yield return m_pos;
}
}
else {
yield break;
}
R0 = offs;
LWM = 1;
}
}
else {
offs = GetGamma();
if ((LWM == 0) && (offs == 2)) {
offs = R0;
len = GetGamma();
for (; len != 0; len--) {
m_buffer[m_pos] = hist[(int)(hist.Count - offs)];
hist.Add(m_buffer[m_pos++]);
if (--m_length == 0)
yield return m_pos;
}
}
else {
if (LWM == 0) {
offs -= 3;
}
else {
offs -= 2;
}
offs <<= 8;
offs += (uint)ReadByte();
len = GetGamma();
if (offs >= 32000) {
len++;
}
if (offs >= 1280) {
len++;
}
if (offs < 128) {
len += 2;
}
for (; len != 0; len--) {
m_buffer[m_pos] = hist[(int)(hist.Count - offs)];
hist.Add(m_buffer[m_pos++]);
if (--m_length == 0)
yield return m_pos;
}
R0 = offs;
}
LWM = 1;
}
}
else {
m_buffer[m_pos] = ReadByte();
hist.Add(m_buffer[m_pos++]);
LWM = 0;
if (--m_length == 0)
yield return m_pos;
}
}
}
uint GetBit () {
uint bit;
if (m_bitcount-- == 0) {
m_tag = (uint)ReadByte();
m_bitcount = 7;
}
bit = (m_tag >> 7) & 0x01;
m_tag <<= 1;
return bit;
}
uint GetGamma () {
uint result = 1;
do {
result = (result << 1) + GetBit();
} while (GetBit() != 0);
return result;
}
byte ReadByte () {
int b = m_input.ReadByte();
if (b == -1)
throw new EndOfStreamException();
return (byte)b;
}
}
public class aPLibStream : PackedStream<aPLibCoroutine> {
public aPLibStream (Stream input, CompressionMode mode = CompressionMode.Decompress, bool leave_open = false) : base (input, leave_open) {
if (mode != CompressionMode.Decompress)
throw new NotImplementedException ("aPLibStream compression not implemented");
}
}
}

View File

@@ -31,9 +31,6 @@
<setting name="SGFileNameEncoding" serializeAs="String">
<value>shift-jis</value>
</setting>
<setting name="ONSCompression" serializeAs="String">
<value>None</value>
</setting>
<setting name="AMIBaseArchive" serializeAs="String">
<value />
</setting>
@@ -209,37 +206,50 @@
<value>932</value>
</setting>
<setting name="TIM2AlphaFormat" serializeAs="String">
<value>RGBA</value>
<value>RGBA</value>
</setting>
<setting name="BELLDATATitle" serializeAs="String">
<value />
</setting>
</GameRes.Formats.Properties.Settings>
</userSettings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /></startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.FileSystem.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Algorithms" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.Numerics" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.5" newVersion="10.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Win32.Registry" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.6.0" newVersion="4.1.6.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.3.0" newVersion="6.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Encoding.CodePages" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.5" newVersion="10.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.4.0" newVersion="4.2.4.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -1,18 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Crc32C.NET" version="1.0.5.0" targetFramework="net461" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net461" />
<package id="NVorbis" version="0.10.4" targetFramework="net461" />
<package id="SharpZipLib" version="1.3.3" targetFramework="net461" />
<package id="Snappy.NET" version="1.1.1.8" targetFramework="net461" />
<package id="System.Buffers" version="4.5.1" targetFramework="net461" />
<package id="System.IO.FileSystem" version="4.3.0" targetFramework="net461" />
<package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net461" />
<package id="System.Memory" version="4.5.4" targetFramework="net461" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net461" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.6.0" targetFramework="net461" />
<package id="System.Security.Cryptography.Algorithms" version="4.3.1" targetFramework="net461" />
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net461" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net461" />
<package id="ZstdNet" version="1.4.5" targetFramework="net461" />
<package id="BCnEncoder.Net" version="2.3.0" targetFramework="net472" />
<package id="CommunityToolkit.HighPerformance" version="8.4.0" targetFramework="net472" />
<package id="K4os.Compression.LZ4" version="1.3.8" targetFramework="net472" />
<package id="Microsoft.Bcl.HashCode" version="6.0.0" targetFramework="net472" />
<package id="Microsoft.Bcl.Numerics" version="10.0.5" targetFramework="net472" />
<package id="Microsoft.Win32.Registry" version="5.0.0" targetFramework="net472" />
<package id="NAudio" version="2.2.1" targetFramework="net472" />
<package id="NAudio.Asio" version="2.2.1" targetFramework="net472" />
<package id="NAudio.Core" version="2.2.1" targetFramework="net472" />
<package id="NAudio.Midi" version="2.2.1" targetFramework="net472" />
<package id="NAudio.Wasapi" version="2.2.1" targetFramework="net472" />
<package id="NAudio.WinForms" version="2.2.1" targetFramework="net472" />
<package id="NAudio.WinMM" version="2.2.1" targetFramework="net472" />
<package id="Newtonsoft.Json" version="13.0.4" targetFramework="net472" />
<package id="NVorbis" version="0.10.5" targetFramework="net472" />
<package id="SharpZipLib" version="1.4.2" targetFramework="net472" />
<package id="SixLabors.ImageSharp" version="2.1.13" targetFramework="net472" />
<package id="Snappier" version="1.3.0" targetFramework="net472" />
<package id="System.Buffers" version="4.6.1" targetFramework="net472" />
<package id="System.Memory" version="4.6.3" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.6.1" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.1.2" targetFramework="net472" />
<package id="System.Security.AccessControl" version="6.0.1" targetFramework="net472" />
<package id="System.Security.Principal.Windows" version="5.0.0" targetFramework="net472" />
<package id="System.Text.Encoding.CodePages" version="10.0.5" targetFramework="net472" />
<package id="System.Threading.Tasks.Extensions" version="4.6.3" targetFramework="net472" />
<package id="System.ValueTuple" version="4.6.2" targetFramework="net472" />
<package id="ZstdSharp.Port" version="0.8.7" targetFramework="net472" />
</packages>

View File

@@ -1,6 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.Numerics" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.5" newVersion="10.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Win32.Registry" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.6.0" newVersion="4.1.6.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.3.0" newVersion="6.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Encoding.CodePages" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.5" newVersion="10.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.4.0" newVersion="4.2.4.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>GARbro</RootNamespace>
<AssemblyName>GARbro.Console</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>

View File

@@ -0,0 +1,102 @@
//! \file ArcIRIS.cs
//! \date 2026-01-25
//! \brief CatSystem for Android resource archive.
//
// Copyright (C) 2026 by morkt
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Text;
using GameRes.Utility;
namespace GameRes.Formats.CatSystem {
[Export(typeof(ArchiveFormat))]
public class IrisPckOpener : ArchiveFormat {
public override string Tag { get { return "DAT/IRIS"; } }
public override string Description { get { return "CatSystem for Android resource archive"; } }
public override uint Signature { get { return 0x53495249; } } // 'IRISPCK'
public override bool IsHierarchic { get { return true; } }
public override bool CanWrite { get { return false; } }
public override ArcFile TryOpen(ArcView file) {
if (!file.View.AsciiEqual(4, "PCK"))
return null;
uint offset = 0x18;
var dir = new List<Entry>();
var name_buffer = new StringBuilder();
while (offset < file.MaxOffset) {
offset += 8;
uint name_length = file.View.ReadUInt32(offset);
offset += 8;
name_buffer.Clear();
for (int i = 0; i < name_length; i += 2) {
char c = (char)file.View.ReadUInt16(offset + i);
if (c == 0)
break;
name_buffer.Append(c);
}
var dirname = name_buffer.ToString().Replace("/", "\\");
offset += name_length;
offset += 4;
int count = (int)file.View.ReadUInt32(offset);
var dir_inner = new List<Entry>(count);
offset += 0xC;
uint prev = 0;
for (int i = 0; i < count; i++) {
offset += 8;
uint size = file.View.ReadUInt32(offset);
uint padded_size = file.View.ReadUInt32(offset + 4);
name_length = file.View.ReadUInt32(offset + 8);
offset += 0x18;
name_buffer.Clear();
for (int j = 0; j < name_length; j += 2) {
char c = (char)file.View.ReadUInt16(offset + j);
if (c == 0)
break;
name_buffer.Append(c);
}
var basename = name_buffer.ToString();
var entry = Create<Entry>(Path.Combine(dirname, basename));
entry.Offset = prev;
entry.Size = size;
prev += padded_size;
offset += name_length;
dir_inner.Add(entry);
}
for (int i = 0; i < count; i++) {
dir_inner[i].Offset += offset;
}
offset += prev;
dir.AddRange(dir_inner);
}
return new ArcFile(file, this, dir);
}
}
}

View File

@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>GameRes.Extra</RootNamespace>
<AssemblyName>ArcExtra</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
@@ -49,11 +49,11 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Concentus, Version=1.1.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Concentus.1.1.7\lib\portable-net45+win+wpa81+wp80\Concentus.dll</HintPath>
<Reference Include="Concentus, Version=2.2.2.0, Culture=neutral, PublicKeyToken=2f7fb9b49ffdfe20, processorArchitecture=MSIL">
<HintPath>..\packages\Concentus.2.2.2\lib\net452\Concentus.dll</HintPath>
</Reference>
<Reference Include="Concentus.Oggfile, Version=1.0.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Concentus.Oggfile.1.0.4\lib\net45\Concentus.Oggfile.dll</HintPath>
<Reference Include="Concentus.Oggfile, Version=1.0.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Concentus.Oggfile.1.0.6\lib\net452\Concentus.Oggfile.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Deployment.Compression, Version=3.0.0.0, Culture=neutral, PublicKeyToken=ce35f76fcda82bad, processorArchitecture=MSIL">
<HintPath>..\packages\MSFTCompressionCab.1.0.0\lib\Microsoft.Deployment.Compression.dll</HintPath>
@@ -61,75 +61,33 @@
<Reference Include="Microsoft.Deployment.Compression.Cab, Version=3.0.0.0, Culture=neutral, PublicKeyToken=ce35f76fcda82bad, processorArchitecture=MSIL">
<HintPath>..\packages\MSFTCompressionCab.1.0.0\lib\Microsoft.Deployment.Compression.Cab.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Win32.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="System" />
<Reference Include="System.AppContext, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll</HintPath>
</Reference>
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
<Reference Include="System.Buffers, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.6.1\lib\net462\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Console, Version=4.0.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Console.4.3.1\lib\net46\System.Console.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Data.SQLite, Version=1.0.115.5, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
<HintPath>..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.115.5\lib\net46\System.Data.SQLite.dll</HintPath>
<Reference Include="System.Data.SQLite, Version=1.0.119.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
<HintPath>..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.119.0\lib\net46\System.Data.SQLite.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Globalization.Calendars, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll</HintPath>
</Reference>
<Reference Include="System.IO.Compression, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll</HintPath>
</Reference>
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.IO.Compression.ZipFile, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll</HintPath>
</Reference>
<Reference Include="System.IO.FileSystem, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath>
</Reference>
<Reference Include="System.IO.FileSystem.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http, Version=4.1.1.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll</HintPath>
</Reference>
<Reference Include="System.Net.Sockets, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll</HintPath>
<Reference Include="System.Memory, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.6.3\lib\net462\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
<Reference Include="System.Numerics.Vectors, Version=4.1.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.6.1\lib\net462\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.1.2\lib\net462\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Numerics" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.4.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.6.3\lib\net462\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Xaml" />
@@ -138,17 +96,15 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.ReaderWriter, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Xml.ReaderWriter.4.3.1\lib\net46\System.Xml.ReaderWriter.dll</HintPath>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="ZstdNet, Version=1.4.5.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ZstdNet.1.4.5\lib\net45\ZstdNet.dll</HintPath>
<Reference Include="ZstdSharp, Version=0.8.7.0, Culture=neutral, PublicKeyToken=8d151af33a4ad5cf, processorArchitecture=MSIL">
<HintPath>..\packages\ZstdSharp.Port.0.8.7\lib\net462\ZstdSharp.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Artemis\ImageIPT.cs" />
<Compile Include="Cabinet\ArcCAB.cs" />
<Compile Include="CatSystem\ArcIRIS.cs" />
<Compile Include="CellWorks\ArcDB.cs" />
<Compile Include="Artemis\GplexBuffers.cs" />
<Compile Include="Microsoft\ArcEXE.cs" />
@@ -175,6 +131,8 @@
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<None Include="x64\libwebp.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@@ -208,16 +166,6 @@
</None>
<None Include="Artemis\IPT.parser" />
</ItemGroup>
<ItemGroup>
<None Include="x64\libzstd.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Include="x86\libzstd.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<PropertyGroup Label="YltParsers">
<Names>ipt</Names>
</PropertyGroup>
@@ -234,15 +182,6 @@ exit 0</PreBuildEvent>
<PropertyGroup Label="GenerateIPTProperties">
<IPTParser>$(ProjectDir)Artemis\IPT</IPTParser>
</PropertyGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
<Error Condition="!Exists('..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.115.5\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.115.5\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets'))" />
<Error Condition="!Exists('..\packages\ZstdNet.1.4.5\build\ZstdNet.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\ZstdNet.1.4.5\build\ZstdNet.targets'))" />
</Target>
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Target Name="BeforeBuild" DependsOnTargets="YltBuildGen" />
<Target Name="YltBuildGen" DependsOnTargets="GenerateIPT" />
<Target Name="GenerateIPT" Inputs="$(IPTParser).Language.analyzer.lex;$(IPTParser).Language.grammar.y" Outputs="$(IPTParser).Scanner.Generated.cs;$(IPTParser).Parser.Generated.cs">
@@ -255,21 +194,11 @@ exit 0</PreBuildEvent>
<Output TaskParameter="Outputs" ItemName="IPT" />
</Exec>
</Target>
<Import Project="..\packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('..\packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" />
<Import Project="..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.119.0\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets" Condition="Exists('..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.119.0\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets'))" />
<Error Condition="!Exists('..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.115.5\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.115.5\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets'))" />
<Error Condition="!Exists('..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.119.0\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.119.0\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets'))" />
</Target>
<Import Project="..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.115.5\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets" Condition="Exists('..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.115.5\build\net46\Stub.System.Data.SQLite.Core.NetFramework.targets')" />
<Import Project="..\packages\ZstdNet.1.4.5\build\ZstdNet.targets" Condition="Exists('..\packages\ZstdNet.1.4.5\build\ZstdNet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -26,6 +26,7 @@
using System;
using System.ComponentModel.Composition;
using System.IO;
using Concentus;
using Concentus.Oggfile;
using Concentus.Structs;
@@ -58,7 +59,7 @@ namespace GameRes.Formats.Opus
// int rate = header.ToInt32 (header_pos+0xC);
int rate = 48000;
file.Position = 0;
var decoder = OpusDecoder.Create (rate, channels);
var decoder = OpusCodecFactory.CreateDecoder (rate, channels);
var ogg_in = new OpusOggReadStream (decoder, file.AsStream);
var pcm = new MemoryStream();
try

View File

@@ -123,10 +123,10 @@ namespace GameRes.Formats.Sakana
internal static byte[] UnpackZstd (byte[] data)
{
int unpacked_size = BigEndian.ToInt32 (data, 0);
using (var dec = new ZstdNet.Decompressor())
using (var dec = new ZstdSharp.Decompressor())
{
var packed = new ArraySegment<byte> (data, 4, data.Length - 4);
return dec.Unwrap (packed, unpacked_size);
var packed = new Span<byte> (data, 4, data.Length - 4);
return dec.Unwrap (packed, unpacked_size).ToArray();
}
}

View File

@@ -1,15 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Concentus" publicKeyToken="2f7fb9b49ffdfe20" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.2.2.0" newVersion="2.2.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.Numerics" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.5" newVersion="10.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Win32.Registry" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.6.0" newVersion="4.1.6.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.3.0" newVersion="6.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Encoding.CodePages" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.5" newVersion="10.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.4.0" newVersion="4.2.4.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -1,32 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Concentus" version="1.1.7" targetFramework="net461" />
<package id="Concentus.Oggfile" version="1.0.4" targetFramework="net461" />
<package id="Microsoft.NETCore.Platforms" version="6.0.3" targetFramework="net461" />
<package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="net461" />
<package id="MSFTCompressionCab" version="1.0.0" targetFramework="net461" />
<package id="NETStandard.Library" version="2.0.3" targetFramework="net461" />
<package id="Stub.System.Data.SQLite.Core.NetFramework" version="1.0.115.5" targetFramework="net461" />
<package id="System.AppContext" version="4.3.0" targetFramework="net461" />
<package id="System.Buffers" version="4.5.1" targetFramework="net461" />
<package id="System.Console" version="4.3.1" targetFramework="net461" />
<package id="System.Data.SQLite.Core" version="1.0.115.5" targetFramework="net461" />
<package id="System.Globalization.Calendars" version="4.3.0" targetFramework="net461" />
<package id="System.IO.Compression" version="4.3.0" targetFramework="net461" />
<package id="System.IO.Compression.ZipFile" version="4.3.0" targetFramework="net461" />
<package id="System.IO.FileSystem" version="4.3.0" targetFramework="net461" />
<package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net461" />
<package id="System.Memory" version="4.5.4" targetFramework="net461" />
<package id="System.Net.Http" version="4.3.4" targetFramework="net461" />
<package id="System.Net.Sockets" version="4.3.0" targetFramework="net461" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net461" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.6.0" targetFramework="net461" />
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net461" />
<package id="System.Security.Cryptography.Algorithms" version="4.3.1" targetFramework="net461" />
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net461" />
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net461" />
<package id="System.Security.Cryptography.X509Certificates" version="4.3.2" targetFramework="net461" />
<package id="System.Xml.ReaderWriter" version="4.3.1" targetFramework="net461" />
<package id="YaccLexTools" version="0.2.2" targetFramework="net461" />
<package id="ZstdNet" version="1.4.5" targetFramework="net461" />
<package id="Concentus" version="2.2.2" targetFramework="net472" />
<package id="Concentus.Oggfile" version="1.0.6" targetFramework="net472" />
<package id="MSFTCompressionCab" version="1.0.0" targetFramework="net472" />
<package id="Stub.System.Data.SQLite.Core.NetFramework" version="1.0.119.0" targetFramework="net472" />
<package id="System.Buffers" version="4.6.1" targetFramework="net472" />
<package id="System.Data.SQLite.Core" version="1.0.119.0" targetFramework="net472" />
<package id="System.Memory" version="4.6.3" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.6.1" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.1.2" targetFramework="net472" />
<package id="System.Threading.Tasks.Extensions" version="4.6.3" targetFramework="net472" />
<package id="ZstdSharp.Port" version="0.8.7" targetFramework="net472" />
</packages>

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="GARbro.GUI.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
</startup>
<userSettings>
<GARbro.GUI.Properties.Settings>
@@ -99,8 +99,36 @@
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="4.0.4.1" newVersion="4.0.5.0"/>
<assemblyIdentity name="Microsoft.Bcl.Numerics" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.5" newVersion="10.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Win32.Registry" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.6.0" newVersion="4.1.6.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.3.0" newVersion="6.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Encoding.CodePages" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.5" newVersion="10.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.4.0" newVersion="4.2.4.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>

View File

@@ -48,11 +48,11 @@ namespace GARbro.GUI
public bool IsTextBoxFocused
{
get { return (bool)GetValue (HasFocusProperty); }
private set { SetValue (HasFocusProperty, value); }
get { return (bool)GetValue (IsTextBoxFocusedProperty); }
private set { SetValue (IsTextBoxFocusedProperty, value); }
}
public static readonly DependencyProperty HasFocusProperty =
public static readonly DependencyProperty IsTextBoxFocusedProperty =
DependencyProperty.RegisterAttached ("IsTextBoxFocused", typeof(bool), typeof(ExtAutoCompleteBox), new UIPropertyMetadata());
protected override void OnKeyDown (KeyEventArgs e)

View File

@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>GARbro.GUI</RootNamespace>
<AssemblyName>GARbro.GUI</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
@@ -89,22 +89,61 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualBasic" />
<Reference Include="Microsoft.WindowsAPICodePack, Version=1.1.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\WindowsAPICodePack-Core.1.1.2\lib\Microsoft.WindowsAPICodePack.dll</HintPath>
<Reference Include="Microsoft.Win32.Registry, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAPICodePack.Shell, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\WindowsAPICodePack-Shell.1.1.1\lib\Microsoft.WindowsAPICodePack.Shell.dll</HintPath>
<Reference Include="Microsoft.WindowsAPICodePack, Version=8.0.14.0, Culture=neutral, PublicKeyToken=8afb38e9204fc0a9, processorArchitecture=MSIL">
<HintPath>..\packages\WindowsAPICodePack.8.0.14\lib\net472\Microsoft.WindowsAPICodePack.dll</HintPath>
</Reference>
<Reference Include="NAudio, Version=1.10.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.1.10.0\lib\net35\NAudio.dll</HintPath>
<Reference Include="Microsoft.WindowsAPICodePack.Core, Version=8.0.14.0, Culture=neutral, PublicKeyToken=8afb38e9204fc0a9, processorArchitecture=MSIL">
<HintPath>..\packages\WindowsAPICodePack.8.0.14\lib\net472\Microsoft.WindowsAPICodePack.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAPICodePack.ExtendedLinguisticServices, Version=8.0.14.0, Culture=neutral, PublicKeyToken=8afb38e9204fc0a9, processorArchitecture=MSIL">
<HintPath>..\packages\WindowsAPICodePack.8.0.14\lib\net472\Microsoft.WindowsAPICodePack.ExtendedLinguisticServices.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAPICodePack.Sensors, Version=8.0.14.0, Culture=neutral, PublicKeyToken=8afb38e9204fc0a9, processorArchitecture=MSIL">
<HintPath>..\packages\WindowsAPICodePack.8.0.14\lib\net472\Microsoft.WindowsAPICodePack.Sensors.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAPICodePack.Shell, Version=8.0.14.0, Culture=neutral, PublicKeyToken=8afb38e9204fc0a9, processorArchitecture=MSIL">
<HintPath>..\packages\WindowsAPICodePack.8.0.14\lib\net472\Microsoft.WindowsAPICodePack.Shell.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAPICodePack.ShellExtensions, Version=8.0.14.0, Culture=neutral, PublicKeyToken=8afb38e9204fc0a9, processorArchitecture=MSIL">
<HintPath>..\packages\WindowsAPICodePack.8.0.14\lib\net472\Microsoft.WindowsAPICodePack.ShellExtensions.dll</HintPath>
</Reference>
<Reference Include="NAudio, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.2.2.1\lib\net472\NAudio.dll</HintPath>
</Reference>
<Reference Include="NAudio.Asio, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.Asio.2.2.1\lib\netstandard2.0\NAudio.Asio.dll</HintPath>
</Reference>
<Reference Include="NAudio.Core, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.Core.2.2.1\lib\netstandard2.0\NAudio.Core.dll</HintPath>
</Reference>
<Reference Include="NAudio.Midi, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.Midi.2.2.1\lib\netstandard2.0\NAudio.Midi.dll</HintPath>
</Reference>
<Reference Include="NAudio.Wasapi, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.Wasapi.2.2.1\lib\netstandard2.0\NAudio.Wasapi.dll</HintPath>
</Reference>
<Reference Include="NAudio.WinForms, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.WinForms.2.2.1\lib\net472\NAudio.WinForms.dll</HintPath>
</Reference>
<Reference Include="NAudio.WinMM, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.WinMM.2.2.1\lib\netstandard2.0\NAudio.WinMM.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Security.AccessControl, Version=6.0.0.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.AccessControl.6.0.1\lib\net461\System.Security.AccessControl.dll</HintPath>
</Reference>
<Reference Include="System.Security.Principal.Windows, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Controls.Input.Toolkit, Version=3.5.40128.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\WPFToolkit.3.5.50211.1\lib\System.Windows.Controls.Input.Toolkit.dll</HintPath>
<HintPath>..\packages\WPFToolkits.3.5.50211.1\lib\System.Windows.Controls.Input.Toolkit.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Controls.Layout.Toolkit, Version=3.5.40128.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\WPFToolkit.3.5.50211.1\lib\System.Windows.Controls.Layout.Toolkit.dll</HintPath>
<HintPath>..\packages\WPFToolkits.3.5.50211.1\lib\System.Windows.Controls.Layout.Toolkit.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
@@ -112,14 +151,12 @@
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xaml" />
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="WPFToolkit, Version=3.5.40128.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\WPFToolkit.3.5.50211.1\lib\WPFToolkit.dll</HintPath>
<HintPath>..\packages\WPFToolkits.3.5.50211.1\lib\WPFToolkit.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -277,6 +314,7 @@
<EmbeddedResource Include="Strings\guiStrings.ru-RU.resx" />
<EmbeddedResource Include="..\LICENSE" />
<EmbeddedResource Include="Strings\guiStrings.zh-Hans.resx" />
<EmbeddedResource Include="Strings\guiStrings.zh-Hant.resx" />
<None Include="packages.config" />
<None Include="Properties\app.manifest" />
<None Include="Properties\Settings.settings">
@@ -309,23 +347,6 @@
<EmbedInteropTypes>False</EmbedInteropTypes>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.5">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Resource Include="Images\Cursors\grab.cur" />
</ItemGroup>
@@ -347,11 +368,4 @@ exit 0</PreBuildEvent>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -5,7 +5,7 @@
xmlns:jv="clr-namespace:JustView"
xmlns:s="clr-namespace:GARbro.GUI.Strings"
xmlns:p="clr-namespace:GARbro.GUI.Properties"
Title="GARbro" MinHeight="250" ResizeMode="CanResizeWithGrip"
Title="GARbro-Mod" MinHeight="250" ResizeMode="CanResizeWithGrip"
Loaded="WindowLoaded"
KeyDown="WindowKeyDown"
AllowDrop="True" Drop="OnDropEvent"

View File

@@ -12,7 +12,7 @@ namespace GARbro.GUI.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.0.3.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

View File

@@ -790,7 +790,7 @@ namespace GARbro.GUI.Strings {
}
/// <summary>
/// Looks up a localized string similar to Image {0} x {1} x {2}bpp.
/// Looks up a localized string similar to Image {0} x {1} x {2}bpp [{3}].
/// </summary>
public static string MsgImageSize {
get {
@@ -1210,6 +1210,15 @@ namespace GARbro.GUI.Strings {
}
}
/// <summary>
/// Looks up a localized string similar to OK.
/// </summary>
public static string TextOK {
get {
return ResourceManager.GetString("TextOK", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Archive parameters.
/// </summary>
@@ -1318,6 +1327,24 @@ namespace GARbro.GUI.Strings {
}
}
/// <summary>
/// Looks up a localized string similar to Archive.
/// </summary>
public static string Type_archive {
get {
return ResourceManager.GetString("Type_archive", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Audio.
/// </summary>
public static string Type_audio {
get {
return ResourceManager.GetString("Type_audio", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &lt;DIR&gt;.
/// </summary>
@@ -1328,7 +1355,16 @@ namespace GARbro.GUI.Strings {
}
/// <summary>
/// Looks up a localized string similar to none.
/// Looks up a localized string similar to Image.
/// </summary>
public static string Type_image {
get {
return ResourceManager.GetString("Type_image", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to NONE.
/// </summary>
public static string Type_NONE {
get {
@@ -1336,6 +1372,24 @@ namespace GARbro.GUI.Strings {
}
}
/// <summary>
/// Looks up a localized string similar to Script.
/// </summary>
public static string Type_script {
get {
return ResourceManager.GetString("Type_script", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Video.
/// </summary>
public static string Type_video {
get {
return ResourceManager.GetString("Type_video", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Scale large images to fit window.
/// </summary>

View File

@@ -560,7 +560,7 @@ Overwrite?</comment>
<comment>Assign file type</comment>
</data>
<data name="Type_NONE" xml:space="preserve">
<value>none</value>
<value>NONE</value>
<comment>none</comment>
</data>
<data name="LabelDestinationDir" xml:space="preserve">
@@ -697,4 +697,22 @@ Overwrite?</comment>
<data name="winDownScaleImage" xml:space="preserve">
<value>Scale large images to fit window</value>
</data>
<data name="Type_archive" xml:space="preserve">
<value>アーカイブ</value>
</data>
<data name="Type_audio" xml:space="preserve">
<value>オーディオ</value>
</data>
<data name="Type_image" xml:space="preserve">
<value>画像</value>
</data>
<data name="Type_script" xml:space="preserve">
<value>スクリプト</value>
</data>
<data name="TextOK" xml:space="preserve">
<value>確認</value>
</data>
<data name="Type_video" xml:space="preserve">
<value>ビデオ</value>
</data>
</root>

View File

@@ -388,7 +388,7 @@
<value>미디어 변환</value>
</data>
<data name="MsgConvertingFile" xml:space="preserve">
<value>파일 변환</value>
<value>파일 변환 {0}</value>
</data>
<data name="TextMediaConvertError" xml:space="preserve">
<value>멀티미디어 변환 오류</value>
@@ -545,6 +545,12 @@
<data name="TextPreferences" xml:space="preserve">
<value>환경설정</value>
</data>
<data name="TextViewer" xml:space="preserve">
<value>이미지 뷰어</value>
</data>
<data name="winDownScaleImage" xml:space="preserve">
<value>큰 이미지 파일을 창 크기에 맞춤</value>
</data>
<data name="Type_archive" xml:space="preserve">
<value>아카이브</value>
</data>
@@ -557,10 +563,10 @@
<data name="Type_script" xml:space="preserve">
<value>스크립트</value>
</data>
<data name="TextViewer" xml:space="preserve">
<value>이미지 뷰어</value>
<data name="TextOK" xml:space="preserve">
<value>OK</value>
</data>
<data name="winDownScaleImage" xml:space="preserve">
<value>큰 이미지 파일을 창 크기에 맞춤</value>
<data name="Type_video" xml:space="preserve">
<value>Video</value>
</data>
</root>

View File

@@ -447,7 +447,7 @@ Overwrite?</value>
<value>Assign file type</value>
</data>
<data name="Type_NONE" xml:space="preserve">
<value>none</value>
<value>NONE</value>
</data>
<data name="LabelDestinationDir" xml:space="preserve">
<value>Destination directory</value>
@@ -551,4 +551,22 @@ Overwrite?</value>
<data name="winDownScaleImage" xml:space="preserve">
<value>Scale large images to fit window</value>
</data>
<data name="Type_archive" xml:space="preserve">
<value>Archive</value>
</data>
<data name="Type_audio" xml:space="preserve">
<value>Audio</value>
</data>
<data name="Type_image" xml:space="preserve">
<value>Image</value>
</data>
<data name="Type_script" xml:space="preserve">
<value>Script</value>
</data>
<data name="TextOK" xml:space="preserve">
<value>OK</value>
</data>
<data name="Type_video" xml:space="preserve">
<value>Video</value>
</data>
</root>

View File

@@ -123,6 +123,9 @@
<data name="ButtonExtract" xml:space="preserve">
<value>Извлечь</value>
</data>
<data name="ButtonOK" xml:space="preserve">
<value>OK</value>
</data>
<data name="CtxMenuClose" xml:space="preserve">
<value>_Закрыть</value>
</data>
@@ -216,6 +219,9 @@
<data name="MsgExtractComplete" xml:space="preserve">
<value>{0} извлечён в {1}</value>
</data>
<data name="MsgExtractedFiles1" xml:space="preserve">
<value>Извлечён {0} файл</value>
</data>
<data name="MsgExtractingArchive" xml:space="preserve">
<value>Извлекаются файлы из {0}</value>
</data>
@@ -270,6 +276,9 @@
<data name="TextCreateArchiveError" xml:space="preserve">
<value>Ошибка при создании архива</value>
</data>
<data name="Type_directory" xml:space="preserve">
<value>&lt;DIR&gt;</value>
</data>
<data name="TextEncoding" xml:space="preserve">
<value>Кодировка текста</value>
</data>
@@ -282,9 +291,6 @@
<data name="TextExtractTitle" xml:space="preserve">
<value>Извлечь из архива</value>
</data>
<data name="TextOK" xml:space="preserve">
<value>OK</value>
</data>
<data name="TextParametersTitle" xml:space="preserve">
<value>Параметры архива</value>
</data>
@@ -315,15 +321,6 @@
<data name="MsgCreatingArchive" xml:space="preserve">
<value>Создание архива {0}</value>
</data>
<data name="Type_archive" xml:space="preserve">
<value>архив</value>
</data>
<data name="Type_image" xml:space="preserve">
<value>изображение</value>
</data>
<data name="Type_script" xml:space="preserve">
<value>сценарий</value>
</data>
<data name="MenuOpen" xml:space="preserve">
<value>Открыть...</value>
</data>
@@ -342,24 +339,15 @@
<data name="MenuHelp" xml:space="preserve">
<value>_Справка</value>
</data>
<data name="MsgExtractedFiles1" xml:space="preserve">
<value>Извлечён {0} файл</value>
</data>
<data name="MsgExtractedFiles2" xml:space="preserve">
<value>Извлечено {0} файла</value>
</data>
<data name="MsgExtractedFiles3" xml:space="preserve">
<value>Извлечено {0} файлов</value>
</data>
<data name="MsgFiles1" xml:space="preserve">
<value>{0} файл</value>
</data>
<data name="MsgFiles2" xml:space="preserve">
<value>{0} файла</value>
</data>
<data name="MsgFiles3" xml:space="preserve">
<value>{0} файлов</value>
</data>
<data name="MsgConfirmDeleteFiles" xml:space="preserve">
<value>Вы действительно хотите удалить эти файлы?</value>
</data>
@@ -372,9 +360,6 @@
<data name="MsgDeletedItems2" xml:space="preserve">
<value>Удалено {0} файла</value>
</data>
<data name="MsgDeletedItems3" xml:space="preserve">
<value>Удалено {0} файлов</value>
</data>
<data name="MenuFitWindow" xml:space="preserve">
<value>Подогнать размер окна под изображение</value>
</data>
@@ -426,21 +411,18 @@
<data name="TextAboutLicense" xml:space="preserve">
<value>Лицензия</value>
</data>
<data name="Type_audio" xml:space="preserve">
<value>звук</value>
</data>
<data name="MsgUnableInterpretAudio" xml:space="preserve">
<value>не удалось интерпретировать формат аудио</value>
</data>
<data name="LabelSkipFailures" xml:space="preserve">
<value>Пропускать файлы, не поддавшиеся конверсии.</value>
</data>
<data name="MsgNoMediaFiles" xml:space="preserve">
<value>Среди выбранных файлов нет мультимедиа.</value>
</data>
<data name="TextAudioConversion" xml:space="preserve">
<value>Аудио-файлы будут преобразованы в WAV, MP3 или OGG.</value>
</data>
<data name="LabelSkipFailures" xml:space="preserve">
<value>Пропускать файлы, не поддавшиеся конверсии.</value>
</data>
<data name="MsgNoMatching" xml:space="preserve">
<value>Нет файлов, подходящих под маску "{0}"</value>
</data>
@@ -450,9 +432,6 @@
<data name="MsgSelectedFiles2" xml:space="preserve">
<value>{0} файла добавлено к выбранным</value>
</data>
<data name="MsgSelectedFiles3" xml:space="preserve">
<value>{0} файлов добавлено к выбранным</value>
</data>
<data name="LabelEnterMask" xml:space="preserve">
<value>Маска для имён файлов</value>
</data>
@@ -527,9 +506,6 @@
<data name="MenuCheckUpdates" xml:space="preserve">
<value>Проверить обновления...</value>
</data>
<data name="MsgDownloadFailed" xml:space="preserve">
<value>Не удалось обновить базу форматов.</value>
</data>
<data name="MsgNoUpdates" xml:space="preserve">
<value>Обновления недоступны.</value>
</data>
@@ -554,6 +530,9 @@
<data name="TextVisitPage" xml:space="preserve">
<value>Перейти на страницу загрузки</value>
</data>
<data name="MsgDownloadFailed" xml:space="preserve">
<value>Не удалось обновить базу форматов.</value>
</data>
<data name="ButtonApply" xml:space="preserve">
<value>Применить</value>
</data>
@@ -572,4 +551,34 @@
<data name="winDownScaleImage" xml:space="preserve">
<value>Масштабировать большие изображения</value>
</data>
<data name="Type_archive" xml:space="preserve">
<value>архив</value>
</data>
<data name="Type_audio" xml:space="preserve">
<value>звук</value>
</data>
<data name="Type_image" xml:space="preserve">
<value>изображение</value>
</data>
<data name="Type_script" xml:space="preserve">
<value>сценарий</value>
</data>
<data name="TextOK" xml:space="preserve">
<value>OK</value>
</data>
<data name="MsgExtractedFiles3" xml:space="preserve">
<value>Извлечено {0} файлов</value>
</data>
<data name="MsgFiles3" xml:space="preserve">
<value>{0} файлов</value>
</data>
<data name="MsgDeletedItems3" xml:space="preserve">
<value>Удалено {0} файлов</value>
</data>
<data name="MsgSelectedFiles3" xml:space="preserve">
<value>{0} файлов добавлено к выбранным</value>
</data>
<data name="Type_video" xml:space="preserve">
<value>Video</value>
</data>
</root>

View File

@@ -439,8 +439,7 @@
<value>选择文件</value>
</data>
<data name="TextErrorExtracting" xml:space="preserve">
<value>提取{0}时
发生错误。
<value>提取{0}时发生错误。
{1}</value>
</data>
<data name="CtxMenuFileType" xml:space="preserve">
@@ -456,6 +455,9 @@
<value>正在播放 {0} / {3} / {2}bps / {1}Hz</value>
<comment>{0}=filename, {1}=sampling rate, {2}=bitrate, {3}=total time </comment>
</data>
<data name="LabelDevSite" xml:space="preserve">
<value>项目主页</value>
</data>
<data name="CtxMenuSelectByMask" xml:space="preserve">
<value>用代号选择文件……</value>
</data>
@@ -503,9 +505,6 @@
<data name="MenuCheckUpdates" xml:space="preserve">
<value>检查更新……</value>
</data>
<data name="MsgDownloadFailed" xml:space="preserve">
<value>更新下载失败。</value>
</data>
<data name="MsgNoUpdates" xml:space="preserve">
<value>无可用更新。</value>
</data>
@@ -530,6 +529,9 @@
<data name="TextVisitPage" xml:space="preserve">
<value>访问下载页面</value>
</data>
<data name="MsgDownloadFailed" xml:space="preserve">
<value>更新下载失败。</value>
</data>
<data name="ButtonApply" xml:space="preserve">
<value>应用</value>
</data>
@@ -542,25 +544,28 @@
<data name="TextPreferences" xml:space="preserve">
<value>偏好设置</value>
</data>
<data name="TextViewer" xml:space="preserve">
<value>图像查看器</value>
</data>
<data name="winDownScaleImage" xml:space="preserve">
<value>缩放大图以适应窗口</value>
</data>
<data name="Type_archive" xml:space="preserve">
<value>档案</value>
</data>
<data name="Type_audio" xml:space="preserve">
<value>音频</value>
</data>
<data name="Type_video" xml:space="preserve">
<value>视频</value>
</data>
<data name="Type_image" xml:space="preserve">
<value>图像</value>
</data>
<data name="Type_script" xml:space="preserve">
<value>脚本</value>
</data>
<data name="TextViewer" xml:space="preserve">
<value>图像查看器</value>
<data name="TextOK" xml:space="preserve">
<value>确认</value>
</data>
<data name="winDownScaleImage" xml:space="preserve">
<value>缩放大图以适应窗口</value>
<data name="Type_video" xml:space="preserve">
<value>视频</value>
</data>
</root>
</root>

View File

@@ -0,0 +1,571 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ButtonCancel" xml:space="preserve">
<value>取消</value>
</data>
<data name="ButtonExtract" xml:space="preserve">
<value>提取</value>
</data>
<data name="ButtonOK" xml:space="preserve">
<value>確定</value>
</data>
<data name="CtxMenuClose" xml:space="preserve">
<value>_關閉</value>
</data>
<data name="CtxMenuCopy" xml:space="preserve">
<value>複製</value>
</data>
<data name="CtxMenuCreate" xml:space="preserve">
<value>創建壓縮檔案...</value>
</data>
<data name="CtxMenuCut" xml:space="preserve">
<value>剪切</value>
</data>
<data name="CtxMenuDelete" xml:space="preserve">
<value>_刪除</value>
</data>
<data name="CtxMenuExplorer" xml:space="preserve">
<value>在_資源管理器中瀏覽</value>
</data>
<data name="CtxMenuExtract" xml:space="preserve">
<value>提取</value>
</data>
<data name="CtxMenuOpen" xml:space="preserve">
<value>打開</value>
</data>
<data name="CtxMenuPaste" xml:space="preserve">
<value>粘貼</value>
</data>
<data name="CtxMenuRefresh" xml:space="preserve">
<value>刷新</value>
</data>
<data name="CtxMenuRename" xml:space="preserve">
<value>_重命名</value>
</data>
<data name="CtxMenuSortBy" xml:space="preserve">
<value>排序方式</value>
</data>
<data name="CtxMenuSortByName" xml:space="preserve">
<value>名稱</value>
</data>
<data name="CtxMenuSortBySize" xml:space="preserve">
<value>大小</value>
</data>
<data name="CtxMenuSortByType" xml:space="preserve">
<value>類型</value>
</data>
<data name="CtxMenuUnsorted" xml:space="preserve">
<value>未分類</value>
</data>
<data name="HeaderName" xml:space="preserve">
<value>名稱</value>
</data>
<data name="HeaderSize" xml:space="preserve">
<value>大小</value>
</data>
<data name="HeaderType" xml:space="preserve">
<value>類型</value>
</data>
<data name="LabelArchiveFormat" xml:space="preserve">
<value>壓縮檔案格式</value>
</data>
<data name="LabelArchiveName" xml:space="preserve">
<value>壓縮檔案名稱</value>
</data>
<data name="LabelArchiveOptions" xml:space="preserve">
<value>壓縮選項</value>
</data>
<data name="LabelExtractAllTo" xml:space="preserve">
<value>從{0}中提取檔案到</value>
</data>
<data name="LabelExtractFileTo" xml:space="preserve">
<value>將{0}解壓到</value>
</data>
<data name="MenuAbout" xml:space="preserve">
<value>關於遊戲資源瀏覽器(GARbro)</value>
</data>
<data name="MsgDeletedItem" xml:space="preserve">
<value>已刪除{0}</value>
</data>
<data name="MsgDirectoryNotFound" xml:space="preserve">
<value>未找到資料夾。</value>
</data>
<data name="MsgEmptyArchive" xml:space="preserve">
<value>壓縮包無內容。</value>
</data>
<data name="MsgErrorExtracting" xml:space="preserve">
<value>提取檔案失敗。</value>
</data>
<data name="MsgErrorOpening" xml:space="preserve">
<value>打開檔案失敗。</value>
</data>
<data name="MsgExtractComplete" xml:space="preserve">
<value>已將{0}提取至{1}。</value>
</data>
<data name="MsgExtractedFiles1" xml:space="preserve">
<value>已提取檔案:{0}。</value>
</data>
<data name="MsgExtractingArchive" xml:space="preserve">
<value>正在從{0}中提取檔案……</value>
</data>
<data name="MsgExtractingFile" xml:space="preserve">
<value>正在從{0}中提取檔案……</value>
</data>
<data name="MsgExtractingTo" xml:space="preserve">
<value>正在從{0}中提取檔案至{1}……</value>
</data>
<data name="MsgImageSize" xml:space="preserve">
<value>圖像 {0} x {1} x {2}bpp [{3}]</value>
</data>
<data name="MsgNoFiles" xml:space="preserve">
<value>沒有可以提取的檔案。</value>
</data>
<data name="MsgReady" xml:space="preserve">
<value>就緒</value>
</data>
<data name="MsgUnableInterpretImage" xml:space="preserve">
<value>無法讀取圖像格式。</value>
</data>
<data name="MsgVersion" xml:space="preserve">
<value>版本 {0}</value>
</data>
<data name="TextAboutBuiltin" xml:space="preserve">
<value>[內置]</value>
</data>
<data name="TextAboutArchives" xml:space="preserve">
<value>壓縮檔案</value>
</data>
<data name="TextAboutImages" xml:space="preserve">
<value>圖像</value>
</data>
<data name="TextAboutTitle" xml:space="preserve">
<value>關於遊戲資源瀏覽器(GARbro)</value>
</data>
<data name="TextAllFiles" xml:space="preserve">
<value>全部檔案</value>
</data>
<data name="TextAsIs" xml:space="preserve">
<value>保持原樣</value>
</data>
<data name="TextChooseArchive" xml:space="preserve">
<value>選擇壓縮檔案位置</value>
</data>
<data name="TextChooseDestDir" xml:space="preserve">
<value>選擇目標資料夾</value>
</data>
<data name="TextCreateArchive" xml:space="preserve">
<value>創建壓縮檔案</value>
</data>
<data name="TextCreateArchiveError" xml:space="preserve">
<value>創建壓縮檔案失敗。</value>
</data>
<data name="Type_directory" xml:space="preserve">
<value>&lt;資料夾&gt;</value>
</data>
<data name="TextEncoding" xml:space="preserve">
<value>文本編碼</value>
</data>
<data name="TextExtractImages" xml:space="preserve">
<value>提取圖像</value>
</data>
<data name="TextExtractText" xml:space="preserve">
<value>提取文字</value>
</data>
<data name="TextExtractTitle" xml:space="preserve">
<value>從壓縮檔案中提取</value>
</data>
<data name="TextParametersTitle" xml:space="preserve">
<value>壓縮檔案參數</value>
</data>
<data name="TextSaveAs" xml:space="preserve">
<value>另存為</value>
</data>
<data name="TextSaveImagesAs" xml:space="preserve">
<value>將圖像另存為</value>
</data>
<data name="TextTitle" xml:space="preserve">
<value>遊戲資源瀏覽器(GARbro)</value>
</data>
<data name="TooltipBack" xml:space="preserve">
<value>後退</value>
</data>
<data name="TooltipForward" xml:space="preserve">
<value>前進</value>
</data>
<data name="MsgOverwrite" xml:space="preserve">
<value>檔案{0}
已經存在。
是否覆蓋?</value>
</data>
<data name="TextConfirmOverwrite" xml:space="preserve">
<value>確認覆蓋</value>
</data>
<data name="MsgCreatingArchive" xml:space="preserve">
<value>正在創建壓縮檔案{0}</value>
</data>
<data name="MenuOpen" xml:space="preserve">
<value>打開...</value>
</data>
<data name="MenuRecent" xml:space="preserve">
<value>最近使用過的檔案</value>
</data>
<data name="MsgChooseFiles" xml:space="preserve">
<value>請選擇需要提取的檔案</value>
</data>
<data name="MenuExit" xml:space="preserve">
<value>_退出</value>
</data>
<data name="MenuFile" xml:space="preserve">
<value>_檔案</value>
</data>
<data name="MenuHelp" xml:space="preserve">
<value>_幫助</value>
</data>
<data name="MsgExtractedFiles2" xml:space="preserve">
<value>已提取{0}個檔案</value>
</data>
<data name="MsgFiles1" xml:space="preserve">
<value>{0}個檔案</value>
</data>
<data name="MsgFiles2" xml:space="preserve">
<value>{0}個檔案</value>
</data>
<data name="MsgConfirmDeleteFiles" xml:space="preserve">
<value>您確定要刪除這些檔案嗎?</value>
</data>
<data name="TextDeleteFiles" xml:space="preserve">
<value>刪除檔案</value>
</data>
<data name="MsgDeletedItems1" xml:space="preserve">
<value>已刪除{0}個檔案。</value>
</data>
<data name="MsgDeletedItems2" xml:space="preserve">
<value>已刪除{0}個檔案。</value>
</data>
<data name="MenuFitWindow" xml:space="preserve">
<value>讓預覽視窗適應圖像</value>
</data>
<data name="MenuToggleMenuBar" xml:space="preserve">
<value>顯示/隱藏_主選單爛</value>
</data>
<data name="MenuToggleStatusBar" xml:space="preserve">
<value>顯示/隱藏_狀態欄</value>
</data>
<data name="MenuToggleToolBar" xml:space="preserve">
<value>顯示/隱藏_工具欄</value>
</data>
<data name="MenuView" xml:space="preserve">
<value>_視圖</value>
</data>
<data name="CtxMenuConvert" xml:space="preserve">
<value>轉換多媒體檔案...</value>
</data>
<data name="ButtonConvert" xml:space="preserve">
<value>轉換</value>
</data>
<data name="LabelDestinationFormat" xml:space="preserve">
<value>請選擇目標檔案類型</value>
</data>
<data name="TextConvertMedia" xml:space="preserve">
<value>媒體轉換</value>
</data>
<data name="MsgConvertingFile" xml:space="preserve">
<value>正在轉換檔案{0}</value>
</data>
<data name="TextMediaConvertError" xml:space="preserve">
<value>轉換錯誤。</value>
</data>
<data name="LabelEncoding" xml:space="preserve">
<value>正在編碼</value>
</data>
<data name="TextConvertAudio" xml:space="preserve">
<value>將音頻轉換為常規格式</value>
</data>
<data name="TextExtractAudio" xml:space="preserve">
<value>提取音頻</value>
</data>
<data name="TooltipAudioFormats" xml:space="preserve">
<value>WAV,MP3或OGG</value>
</data>
<data name="TextAboutAudio" xml:space="preserve">
<value>音頻</value>
</data>
<data name="TextAboutLicense" xml:space="preserve">
<value>許可證書</value>
</data>
<data name="MsgUnableInterpretAudio" xml:space="preserve">
<value>無法讀取音頻格式。</value>
</data>
<data name="MsgNoMediaFiles" xml:space="preserve">
<value>沒有選擇媒體檔案。</value>
</data>
<data name="TextAudioConversion" xml:space="preserve">
<value>音頻檔案將被轉換為WAV,MP3或OGG格式。</value>
</data>
<data name="LabelSkipFailures" xml:space="preserve">
<value>跳過不可轉換的檔案</value>
</data>
<data name="MsgNoMatching" xml:space="preserve">
<value>沒有與「{0}」匹配的項目。</value>
</data>
<data name="MsgSelectedFiles1" xml:space="preserve">
<value>選中{0}個檔案。</value>
</data>
<data name="MsgSelectedFiles2" xml:space="preserve">
<value>選中{0}個檔案。</value>
</data>
<data name="LabelEnterMask" xml:space="preserve">
<value>請輸入通配符掩碼</value>
</data>
<data name="TextSelectFiles" xml:space="preserve">
<value>選擇檔案</value>
</data>
<data name="TextErrorExtracting" xml:space="preserve">
<value>提取{0}時發生錯誤。
{1}</value>
</data>
<data name="CtxMenuFileType" xml:space="preserve">
<value>選擇檔案類型</value>
</data>
<data name="Type_NONE" xml:space="preserve">
<value>無</value>
</data>
<data name="LabelDestinationDir" xml:space="preserve">
<value>目標資料夾</value>
</data>
<data name="MsgPlaying" xml:space="preserve">
<value>正在播放 {0} / {3} / {2}bps / {1}Hz</value>
<comment>{0}=filename, {1}=sampling rate, {2}=bitrate, {3}=total time </comment>
</data>
<data name="LabelDevSite" xml:space="preserve">
<value>項目主頁</value>
</data>
<data name="CtxMenuSelectByMask" xml:space="preserve">
<value>用代號選擇檔案……</value>
</data>
<data name="ButtonAbort" xml:space="preserve">
<value>中止</value>
</data>
<data name="ButtonContinue" xml:space="preserve">
<value>繼續</value>
</data>
<data name="LabelIgnoreErrors" xml:space="preserve">
<value>忽略錯誤</value>
</data>
<data name="TextExtractionError" xml:space="preserve">
<value>檔案提取錯誤</value>
</data>
<data name="ButtonOverwrite" xml:space="preserve">
<value>覆蓋</value>
</data>
<data name="ButtonRename" xml:space="preserve">
<value>重命名</value>
</data>
<data name="ButtonSkip" xml:space="preserve">
<value>跳過</value>
</data>
<data name="LabelApplyToAll" xml:space="preserve">
<value>應用於所有重複檔案</value>
</data>
<data name="LabelDuplicateFileQuestion" xml:space="preserve">
<value>應該做什麼?</value>
</data>
<data name="TextErrorConverting" xml:space="preserve">
<value>轉換檔案時發生錯誤
{0}
{1}</value>
</data>
<data name="TextFileAlreadyExists" xml:space="preserve">
<value>檔案{0}已經存在。</value>
</data>
<data name="ButtonDownload" xml:space="preserve">
<value>下載</value>
</data>
<data name="LabelReleaseNotes" xml:space="preserve">
<value>發行註記</value>
</data>
<data name="MenuCheckUpdates" xml:space="preserve">
<value>檢查更新……</value>
</data>
<data name="MsgNoUpdates" xml:space="preserve">
<value>無可用更新。</value>
</data>
<data name="MsgUpdateAvailable" xml:space="preserve">
<value>有可用格式數據庫更新。</value>
</data>
<data name="MsgUpdateComplete" xml:space="preserve">
<value>格式數據庫已更新。</value>
</data>
<data name="MsgUpdateFailed" xml:space="preserve">
<value>更新檢查失敗。</value>
</data>
<data name="MsgUpToDate" xml:space="preserve">
<value>GARbro 已是最新版本。</value>
</data>
<data name="TextNewVersion" xml:space="preserve">
<value>新版本已可用:</value>
</data>
<data name="TextUpdateTitle" xml:space="preserve">
<value>應用程序更新</value>
</data>
<data name="TextVisitPage" xml:space="preserve">
<value>訪問下載頁面</value>
</data>
<data name="MsgDownloadFailed" xml:space="preserve">
<value>更新下載失敗。</value>
</data>
<data name="ButtonApply" xml:space="preserve">
<value>應用</value>
</data>
<data name="MenuPreferences" xml:space="preserve">
<value>偏好設置</value>
</data>
<data name="TextFormats" xml:space="preserve">
<value>格式</value>
</data>
<data name="TextPreferences" xml:space="preserve">
<value>偏好設置</value>
</data>
<data name="TextViewer" xml:space="preserve">
<value>圖像查看器</value>
</data>
<data name="winDownScaleImage" xml:space="preserve">
<value>縮放大圖以適應視窗</value>
</data>
<data name="Type_archive" xml:space="preserve">
<value>檔案</value>
</data>
<data name="Type_audio" xml:space="preserve">
<value>音頻</value>
</data>
<data name="Type_image" xml:space="preserve">
<value>圖像</value>
</data>
<data name="Type_script" xml:space="preserve">
<value>腳本</value>
</data>
<data name="TextOK" xml:space="preserve">
<value>確認</value>
</data>
<data name="Type_video" xml:space="preserve">
<value>影片</value>
</data>
</root>

View File

@@ -1,7 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NAudio" version="1.10.0" targetFramework="net461" />
<package id="WindowsAPICodePack-Core" version="1.1.2" targetFramework="net461" />
<package id="WindowsAPICodePack-Shell" version="1.1.1" targetFramework="net461" />
<package id="WPFToolkit" version="3.5.50211.1" targetFramework="net461" />
<package id="Microsoft.Win32.Registry" version="5.0.0" targetFramework="net472" />
<package id="NAudio" version="2.2.1" targetFramework="net472" />
<package id="NAudio.Asio" version="2.2.1" targetFramework="net472" />
<package id="NAudio.Core" version="2.2.1" targetFramework="net472" />
<package id="NAudio.Midi" version="2.2.1" targetFramework="net472" />
<package id="NAudio.Wasapi" version="2.2.1" targetFramework="net472" />
<package id="NAudio.WinForms" version="2.2.1" targetFramework="net472" />
<package id="NAudio.WinMM" version="2.2.1" targetFramework="net472" />
<package id="System.Security.AccessControl" version="6.0.1" targetFramework="net472" />
<package id="System.Security.Principal.Windows" version="5.0.0" targetFramework="net472" />
<package id="WindowsAPICodePack" version="8.0.14" targetFramework="net472" />
<package id="WPFToolkits" version="3.5.50211.1" targetFramework="net472" />
</packages>

View File

@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>GameRes</RootNamespace>
<AssemblyName>GameRes</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
@@ -46,17 +46,44 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="NAudio, Version=1.10.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.1.10.0\lib\net35\NAudio.dll</HintPath>
<Reference Include="Microsoft.Win32.Registry, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll</HintPath>
</Reference>
<Reference Include="NAudio, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.2.2.1\lib\net472\NAudio.dll</HintPath>
</Reference>
<Reference Include="NAudio.Asio, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.Asio.2.2.1\lib\netstandard2.0\NAudio.Asio.dll</HintPath>
</Reference>
<Reference Include="NAudio.Core, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.Core.2.2.1\lib\netstandard2.0\NAudio.Core.dll</HintPath>
</Reference>
<Reference Include="NAudio.Midi, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.Midi.2.2.1\lib\netstandard2.0\NAudio.Midi.dll</HintPath>
</Reference>
<Reference Include="NAudio.Wasapi, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.Wasapi.2.2.1\lib\netstandard2.0\NAudio.Wasapi.dll</HintPath>
</Reference>
<Reference Include="NAudio.WinForms, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.WinForms.2.2.1\lib\net472\NAudio.WinForms.dll</HintPath>
</Reference>
<Reference Include="NAudio.WinMM, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\packages\NAudio.WinMM.2.2.1\lib\netstandard2.0\NAudio.WinMM.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<HintPath>..\packages\Newtonsoft.Json.13.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Security.AccessControl, Version=6.0.0.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.AccessControl.6.0.1\lib\net461\System.Security.AccessControl.dll</HintPath>
</Reference>
<Reference Include="System.Security.Principal.Windows, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
@@ -117,6 +144,7 @@
</EmbeddedResource>
<EmbeddedResource Include="Strings\garStrings.ru-RU.resx" />
<EmbeddedResource Include="Strings\garStrings.zh-Hans.resx" />
<EmbeddedResource Include="Strings\garStrings.zh-Hant.resx" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
@@ -131,11 +159,4 @@
<PreBuildEvent>perl "$(SolutionDir)inc-revision.pl" "$(ProjectPath)" $(ConfigurationName)
exit 0</PreBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -12,7 +12,7 @@ namespace GameRes.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.0.3.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")]
public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

View File

@@ -0,0 +1,150 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="BMPExtensionsDesc" xml:space="preserve">
<value>啟用各種擴展,如透明度支持</value>
</data>
<data name="BMPExtensionsText" xml:space="preserve">
<value>啟用 BMP 格式擴展</value>
</data>
<data name="JPEGQualityText" xml:space="preserve">
<value>JPEG 壓縮品質</value>
</data>
<data name="MsgFileIsEmpty" xml:space="preserve">
<value>檔案為空。</value>
</data>
<data name="MsgFileTooLarge" xml:space="preserve">
<value>檔案尺寸太大。</value>
</data>
<data name="MsgInvalidEncryption" xml:space="preserve">
<value>不正確的加密方式。</value>
</data>
<data name="MsgInvalidFileName" xml:space="preserve">
<value>無效的檔案名。</value>
</data>
<data name="MsgInvalidFormat" xml:space="preserve">
<value>無效的檔案格式。</value>
</data>
<data name="MsgUnknownEncryption" xml:space="preserve">
<value>未知的加密方式。</value>
</data>
<data name="MsgUnknownFormat" xml:space="preserve">
<value>無法作為壓縮包打開檔案。</value>
</data>
</root>

View File

@@ -113,6 +113,11 @@ namespace GameRes.Utility
return GetCString (data, index, length_limit, Encodings.cp932);
}
public static string GetCString (byte[] data, int index, Encoding enc)
{
return GetCString (data, index, data.Length - index, enc);
}
public static string GetCString (byte[] data, int index)
{
return GetCString (data, index, data.Length - index, Encodings.cp932);

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
@@ -18,4 +18,43 @@
</setting>
</GameRes.Properties.Settings>
</userSettings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/></startup></configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.Numerics" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.5" newVersion="10.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Win32.Registry" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.6.0" newVersion="4.1.6.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.3.0" newVersion="6.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Encoding.CodePages" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.5" newVersion="10.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.4.0" newVersion="4.2.4.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -1,5 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NAudio" version="1.10.0" targetFramework="net461" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net461" />
<package id="Microsoft.Win32.Registry" version="5.0.0" targetFramework="net472" />
<package id="NAudio" version="2.2.1" targetFramework="net472" />
<package id="NAudio.Asio" version="2.2.1" targetFramework="net472" />
<package id="NAudio.Core" version="2.2.1" targetFramework="net472" />
<package id="NAudio.Midi" version="2.2.1" targetFramework="net472" />
<package id="NAudio.Wasapi" version="2.2.1" targetFramework="net472" />
<package id="NAudio.WinForms" version="2.2.1" targetFramework="net472" />
<package id="NAudio.WinMM" version="2.2.1" targetFramework="net472" />
<package id="Newtonsoft.Json" version="13.0.4" targetFramework="net472" />
<package id="System.Security.AccessControl" version="6.0.1" targetFramework="net472" />
<package id="System.Security.Principal.Windows" version="5.0.0" targetFramework="net472" />
</packages>

View File

@@ -1,6 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.Numerics" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.5" newVersion="10.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Win32.Registry" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.6.0" newVersion="4.1.6.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.3.0" newVersion="6.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Encoding.CodePages" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.5" newVersion="10.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.4.0" newVersion="4.2.4.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Image.Convert</RootNamespace>
<AssemblyName>Image.Convert</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
@@ -69,11 +69,4 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,144 @@
using System;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq; // Added for list operations if necessary
using System.Windows.Media;
using System.Windows.Media.Imaging;
using GameRes.Utility;
namespace GameRes.Formats.Broccoli
{
[Export(typeof(ImageFormat))]
public class GrpFormat : ImageFormat
{
public override string Tag { get { return "GRP/BROCCOLI"; } }
public override string Description { get { return "Broccoli engine image"; } }
public override uint Signature { get { return 0; } }
public override ImageMetaData ReadMetaData (IBinaryStream file)
{
// We need to decompress to know the real size
using (var data = DecompressData(file))
{
if (data == null) return null;
var size = data.Length;
uint width = 0, height = 0;
int bpp = 32;
// Same resolution logic as your Python script
if (size == 1920000) { width = 800; height = 600; }
else if (size == 1228800) { width = 640; height = 480; }
else if (size == 1536000) { width = 800; height = 480; }
else if (size == 768000) { width = 640; height = 400; }
else if (size == 307200) { width = 640; height = 480; bpp = 8; }
else if (size == 96000) { width = 200; height = 120; }
else
{
// Fallback: Try to read 4-byte header (Width/Height)
if (size > 4)
{
data.Position = 0;
var reader = new BinaryReader(data);
ushort w = reader.ReadUInt16();
ushort h = reader.ReadUInt16();
if (w * h * 4 == size - 4)
{
width = w;
height = h;
}
}
}
if (width == 0) return null;
return new ImageMetaData
{
Width = width,
Height = height,
BPP = bpp,
};
}
}
public override ImageData Read (IBinaryStream file, ImageMetaData info)
{
using (var stream = DecompressData(file))
{
if (stream == null) throw new InvalidFormatException();
// Skip 4-byte header if fallback logic was used
int headerSkip = 0;
if (stream.Length != info.Width * info.Height * (info.BPP / 8))
{
if (stream.Length == (info.Width * info.Height * 4) + 4)
headerSkip = 4;
}
stream.Position = headerSkip;
// Case 1: Isolated Mask (Grayscale)
if (info.BPP == 8)
{
var gray = new byte[info.Width * info.Height];
stream.Read(gray, 0, gray.Length);
return ImageData.Create(info, PixelFormats.Gray8, null, gray);
}
// Case 2: Colored Image (BGRX)
// Due to API limitations, we won't load the mask (_m) here.
// GARbro will show the image with a black/solid background.
// Use your Python script to combine with the mask later.
var pixels = new byte[info.Width * info.Height * 4];
stream.Read(pixels, 0, pixels.Length);
// The format is usually Bgr32 (the 4th byte is garbage/padding, not real alpha)
return ImageData.Create(info, PixelFormats.Bgr32, null, pixels);
}
}
public override void Write (Stream file, ImageData image)
{
throw new System.NotImplementedException("Use repack.py");
}
private MemoryStream DecompressData(IBinaryStream input)
{
input.Position = 0;
byte[] buffer = input.ReadBytes(2048);
int zlibOffset = -1;
// Search for ZLIB signature (78 9C, etc)
for (int i = 0; i < buffer.Length - 1; i++)
{
if (buffer[i] == 0x78 &&
(buffer[i+1] == 0x9C || buffer[i+1] == 0xDA || buffer[i+1] == 0x01))
{
zlibOffset = i;
break;
}
}
if (zlibOffset == -1) return null;
try
{
// Skip ZLIB header (2 bytes) to use standard DeflateStream
input.Position = zlibOffset + 2;
using (var zStream = new System.IO.Compression.DeflateStream(input.AsStream, System.IO.Compression.CompressionMode.Decompress, true))
{
var output = new MemoryStream();
zStream.CopyTo(output);
output.Position = 0;
return output;
}
}
catch
{
return null;
}
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using GameRes.Utility;
namespace GameRes.Formats.Broccoli
{
[Export(typeof(ArchiveFormat))]
public class MpegVideoOpener : ArchiveFormat
{
public override string Tag { get { return "MPEG/BROCCOLI"; } }
public override string Description { get { return "Generic MPEG Video"; } }
public override uint Signature { get { return 0xBA010000; } }
public override bool IsHierarchic { get { return false; } }
public override bool CanWrite { get { return false; } }
public override ArcFile TryOpen(ArcView file)
{
if (file.View.ReadUInt32(0) != 0xBA010000)
return null;
var entry = new Entry
{
Name = Path.GetFileNameWithoutExtension(file.Name) + ".mpg",
Type = "video",
Offset = 0,
// FIX: Added (uint) cast for size conversion
Size = (uint)file.MaxOffset
};
return new ArcFile(file, this, new List<Entry> { entry });
}
}
}

View File

@@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using GameRes.Utility;
namespace GameRes.Formats.Broccoli
{
[Export(typeof(ArchiveFormat))]
public class PakOpener : ArchiveFormat
{
public override string Tag { get { return "PAK/BROCCOLI"; } }
public override string Description { get { return "Broccoli"; } }
public override uint Signature { get { return 0; } }
public override bool IsHierarchic { get { return true; } }
public override bool CanWrite { get { return false; } }
private static readonly byte[] FirstFileSignature = {
0x73, 0x65, 0x5F, 0x63, 0x31, 0x31, 0x2E, 0x77, 0x61, 0x76
};
public override ArcFile TryOpen(ArcView file)
{
int bufferSize = 2048;
if (file.MaxOffset < bufferSize)
bufferSize = (int)file.MaxOffset;
var buffer = file.View.ReadBytes(0, (uint)bufferSize);
int signaturePos = FindSignature(buffer, FirstFileSignature);
if (signaturePos == -1)
return null;
if (signaturePos < 8)
return null;
long countOffset = signaturePos - 8;
int count = file.View.ReadInt32(countOffset);
if (!IsSaneCount(count))
return null;
long tableStart = signaturePos;
long entrySize = 64;
long tableByteSize = count * entrySize;
long dataBlobStart = tableStart + tableByteSize;
if (dataBlobStart > file.MaxOffset)
return null;
var dir = new List<Entry>(count);
for (int i = 0; i < count; i++)
{
long entryPos = tableStart + (i * entrySize);
var nameBytes = file.View.ReadBytes(entryPos, 48);
// --- FIX APPLIED HERE ---
// Replaced Binary.Ascii with System.Text.Encoding.ASCII
if (nameBytes.Length >= 4 &&
(System.Text.Encoding.ASCII.GetString(nameBytes, 0, 4) == "RIFF" ||
System.Text.Encoding.ASCII.GetString(nameBytes, 0, 4) == "OggS"))
{
break;
}
// ------------------------
string name = Binary.GetCString(nameBytes, 0, nameBytes.Length, Encodings.cp932);
if (string.IsNullOrWhiteSpace(name))
continue;
name = name.TrimEnd('\0');
uint offset = file.View.ReadUInt32(entryPos + 48);
uint size = file.View.ReadUInt32(entryPos + 56);
if (size == 0)
continue;
var entry = FormatCatalog.Instance.Create<Entry>(name);
entry.Offset = dataBlobStart + offset;
entry.Size = size;
if (!entry.CheckPlacement(file.MaxOffset))
return null;
dir.Add(entry);
}
return new ArcFile(file, this, dir);
}
private int FindSignature(byte[] buffer, byte[] signature)
{
if (buffer.Length < signature.Length) return -1;
for (int i = 0; i <= buffer.Length - signature.Length; i++)
{
bool found = true;
for (int j = 0; j < signature.Length; j++)
{
if (buffer[i + j] != signature[j])
{
found = false;
break;
}
}
if (found) return i;
}
return -1;
}
}
}

View File

@@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>GameRes.Legacy</RootNamespace>
<AssemblyName>ArcLegacy</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
@@ -44,14 +44,30 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="ICSharpCode.SharpZipLib, Version=1.3.3.11, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.1.3.3\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
<Reference Include="ICSharpCode.SharpZipLib, Version=1.4.2.13, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.1.4.2\lib\netstandard2.0\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.6.1\lib\net462\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Memory, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.6.3\lib\net462\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.6.1\lib\net462\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.1.2\lib\net462\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.4.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.6.3\lib\net462\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
@@ -100,6 +116,9 @@
<Compile Include="Blucky\Aliases.cs" />
<Compile Include="Bom\ImageGRP.cs" />
<Compile Include="Broccoli\ArcP00.cs" />
<Compile Include="Broccoli\BroccoliGrp.cs" />
<Compile Include="Broccoli\BroccoliMpeg.cs" />
<Compile Include="Broccoli\BroccoliPak.cs" />
<Compile Include="CottonClub\ImageLMG.cs" />
<Compile Include="Desire\ArcDSV.cs" />
<Compile Include="Desire\ImageDES.cs" />
@@ -358,11 +377,4 @@
<PreBuildEvent>perl "$(SolutionDir)inc-revision.pl" "$(ProjectPath)" $(ConfigurationName)
exit 0</PreBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,15 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.Numerics" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.5" newVersion="10.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Win32.Registry" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.6.0" newVersion="4.1.6.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.3.0" newVersion="6.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Encoding.CodePages" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.5" newVersion="10.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.4.0" newVersion="4.2.4.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="SharpZipLib" version="1.3.3" targetFramework="net461" />
<package id="SharpZipLib" version="1.4.2" targetFramework="net472" />
<package id="System.Buffers" version="4.6.1" targetFramework="net472" />
<package id="System.Memory" version="4.6.3" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.6.1" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.1.2" targetFramework="net472" />
<package id="System.Threading.Tasks.Extensions" version="4.6.3" targetFramework="net472" />
</packages>

View File

@@ -3,11 +3,11 @@ GARbro
Visual Novels resource browser.
Requires .NET Framework v4.6 or newer (https://www.microsoft.com/net)
Requires .NET Framework v4.7.2 or newer (https://dotnet.microsoft.com/en-us/download/dotnet-framework/net472)
[Supported formats](https://morkt.github.io/GARbro/supported.html)
[Download latest release](https://github.com/morkt/GARbro/releases)
[Download latest release](https://github.com/crskycode/GARbro/releases)
Operation
---------
@@ -69,6 +69,6 @@ Japanese translation by [haniwa55](https://github.com/haniwa55)
Contributors
------
<a href="https://github.com/nanami5270/GARbro-Mod/graphs/contributors">
<img src="https://contrib.rocks/image?repo=nanami5270/GARbro-Mod" />
</a>
<a href="https://github.com/crskycode/GARbro/graphs/contributors">
<img src="https://contrib.rocks/image?repo=crskycode/GARbro" />
</a>

View File

@@ -1,22 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.Numerics" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.5" newVersion="10.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Win32.Registry" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.6.0" newVersion="4.1.6.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.3.0" newVersion="6.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Encoding.CodePages" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.5" newVersion="10.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.4.0" newVersion="4.2.4.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -8,10 +8,11 @@
<OutputType>Exe</OutputType>
<RootNamespace>SchemeTool</RootNamespace>
<AssemblyName>SchemeTool</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -34,19 +35,19 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
<Reference Include="System.Buffers, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.6.1\lib\net462\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath>
<Reference Include="System.Memory, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.6.3\lib\net462\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
<Reference Include="System.Numerics.Vectors, Version=4.1.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.6.1\lib\net462\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.1.2\lib\net462\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="System.Buffers" version="4.5.1" targetFramework="net461" />
<package id="System.Memory" version="4.5.4" targetFramework="net461" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net461" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.6.0" targetFramework="net461" />
<package id="System.Buffers" version="4.6.1" targetFramework="net472" />
<package id="System.Memory" version="4.6.3" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.6.1" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.1.2" targetFramework="net472" />
</packages>