Full Code of JKAnderson/UXM for AI

master 9b0000686e6f cached
39 files
9.1 MB
2.4M tokens
46 symbols
1 requests
Download .txt
Showing preview only (9,598K chars total). Download the full file or copy to clipboard to get everything.
Repository: JKAnderson/UXM
Branch: master
Commit: 9b0000686e6f
Files: 39
Total size: 9.1 MB

Directory structure:
gitextract_539c5h6b/

├── .gitattributes
├── .gitignore
├── .gitmodules
├── LICENSE
├── README.md
├── UXM/
│   ├── App.config
│   ├── ArchiveDictionary.cs
│   ├── ArchiveKeys.cs
│   ├── ArchiveUnpacker.cs
│   ├── CryptographyUtility.cs
│   ├── ExePatcher.cs
│   ├── FormMain.Designer.cs
│   ├── FormMain.cs
│   ├── FormMain.resx
│   ├── GameInfo.cs
│   ├── GameRestorer.cs
│   ├── Program.cs
│   ├── Properties/
│   │   ├── Resources.Designer.cs
│   │   ├── Resources.resx
│   │   ├── Settings.Designer.cs
│   │   └── Settings.settings
│   ├── UXM.csproj
│   ├── Util.cs
│   └── dist/
│       ├── readme.txt
│       └── res/
│           ├── ArmoredCore6Dictionary.txt
│           ├── ArmoredCore6GameInfo.xml
│           ├── DarkSouls2Dictionary.txt
│           ├── DarkSouls2GameInfo.xml
│           ├── DarkSouls3Dictionary.txt
│           ├── DarkSouls3GameInfo.xml
│           ├── EldenRingDictionary.txt
│           ├── EldenRingGameInfo.xml
│           ├── ScholarDictionary.txt
│           ├── ScholarGameInfo.xml
│           ├── SekiroBonusDictionary.txt
│           ├── SekiroBonusGameInfo.xml
│           ├── SekiroDictionary.txt
│           └── SekiroGameInfo.xml
└── UXM.sln

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto

###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs     diff=csharp

###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following 
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln       merge=binary
#*.csproj    merge=binary
#*.vbproj    merge=binary
#*.vcxproj   merge=binary
#*.vcproj    merge=binary
#*.dbproj    merge=binary
#*.fsproj    merge=binary
#*.lsproj    merge=binary
#*.wixproj   merge=binary
#*.modelproj merge=binary
#*.sqlproj   merge=binary
#*.wwaproj   merge=binary

###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg   binary
#*.png   binary
#*.gif   binary

###############################################################################
# diff behavior for common document formats
# 
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the 
# entries below.
###############################################################################
#*.doc   diff=astextplain
#*.DOC   diff=astextplain
#*.docx  diff=astextplain
#*.DOCX  diff=astextplain
#*.dot   diff=astextplain
#*.DOT   diff=astextplain
#*.pdf   diff=astextplain
#*.PDF   diff=astextplain
#*.rtf   diff=astextplain
#*.RTF   diff=astextplain


================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# DNX
project.lock.json
project.fragment.lock.json
artifacts/

*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

# SQL Server files
*.mdf
*.ldf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush
.cr/

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

================================================
FILE: .gitmodules
================================================
[submodule "SoulsFormatsNEXT"]
	path = SoulsFormatsNEXT
	url = https://github.com/soulsmods/SoulsFormatsNEXT


================================================
FILE: LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.


================================================
FILE: README.md
================================================
# UXM
Enables file modding for DS2, SotFS, DS3, and Sekiro by unpacking game archives and patching the executable to load loose files instead.  
Requires [.NET 4.7.2](https://www.microsoft.com/net/download/thank-you/net472) - Windows 10 users should already have this.  
[Nexus Page](https://www.nexusmods.com/sekiro/mods/26)  

# Usage
When first starting the app, the default Steam location of Sekiro will be selected. If the game you want is installed somewhere else, use the Browse button to correct it.

The Unpack button will extract all files from the game archives; any files that are already present will be skipped, so if you need to unmodify any file you can simply delete it and unpack again without having to sit through the entire process.

The Patch button will modify the executable to use those extracted files instead of looking in the archives; please note that for Sekiro, most users should use Mod Engine instead of patching. Patching the executable without also unpacking the archives will crash the game, so make sure you do both.

Finally, the Restore button will restore the original executable and delete the extracted files, and the Abort button will cancel any operation in progress.

# Bannability
UXM only edits data within the executable, not code, so anticheat should have no effect on it. File mods in general have never been grounds for a ban in any of the Souls games, but mods that alter your save may not be safe, so please consult your mod author's advice and play offline if using anything dubious.

# Credits
[BinderTool](https://github.com/Atvaark/BinderTool) by Atvaark

[Costura.Fody](https://github.com/Fody/Costura) by Simon Cropp, Cameron MacFarland

[Octokit](https://github.com/octokit/octokit.net) by GitHub

[Semver](https://github.com/maxhauser/semver) by Max Hauser

# Changelog
### 2.4
* Sekiro pre-order artbook/soundtrack thing support; just browse to DigitalArtwork_MiniSoundtrack.exe
* Identify more files for Sekiro (thank you horkrux!)

### 2.3
* Sekiro support

### 2.2
* Identified the final file in DS3 (thanks Meow)
* Identified files for Japanese DS2
* Show progress on the taskbar icon
* Make sure you really want to delete everything if you click Restore

### 2.1.3
* Support unpacking decrypted archives for BootBoost compatibility

### 2.1.2
* Fix the update link in the app not actually doing anything

### 2.1.1
* Fix DLC2 files still being loaded from archive (just click Patch again to fix it)

### 2.1
* Fix keybinding menu being broken because of a false positive
* Identify all but 1 file in DS3 (and support release version better)

### 2.0
* U3M has been mostly rewritten and is now UXM
* DS2 and SotFS are supported
* Performance improvements (20-30% faster unpacking)
* Patching and restoring now also display progress and are abortable
* Fixed some misidentified files in DS3 and identified 1 new one

================================================
FILE: UXM/App.config
================================================
<?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="UXM.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.7.2" />
    </startup>
    <userSettings>
        <UXM.Properties.Settings>
            <setting name="UpgradeRequired" serializeAs="String">
                <value>True</value>
            </setting>
            <setting name="WindowLocation" serializeAs="String">
                <value>200, 200</value>
            </setting>
            <setting name="WindowSize" serializeAs="String">
                <value>657, 234</value>
            </setting>
            <setting name="WindowMaximized" serializeAs="String">
                <value>False</value>
            </setting>
            <setting name="ExePath" serializeAs="String">
                <value>C:\Program Files (x86)\Steam\steamapps\common\Sekiro\sekiro.exe</value>
            </setting>
        </UXM.Properties.Settings>
    </userSettings>
</configuration>

================================================
FILE: UXM/ArchiveDictionary.cs
================================================
using SoulsFormats;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace UXM
{
    internal class ArchiveDictionary : Dictionary<ulong, string>
    {
        private const uint PRIME32 = 37;
        private const ulong PRIME64 = 133;

        public ArchiveDictionary(string dictionary, BHD5.Game game)
        {
            foreach (string line in Regex.Split(dictionary, "[\r\n]+"))
            {
                if (!string.IsNullOrWhiteSpace(line))
                {
                    string path = Normalize(line);
                    ulong hash = FromHash(path, game);
                    this[hash] = path;
                }
            }
        }

        public static string Normalize(string path)
        {
            if (path.Contains(':'))
                path = path[(path.IndexOf(':') + 1)..];

            path = path.ToLowerInvariant().Replace('\\', '/').Trim();

            if (!path.StartsWith('/'))
                path = '/' + path;

            return path;
        }

        public static ulong FromHash(string path, BHD5.Game game)
        {
            if (game == BHD5.Game.EldenRing)
                return path.Aggregate(0ul, (a, c) => a * PRIME64 + c);
            else
                return path.Aggregate(0u, (a, c) => a * PRIME32 + c);
        }
    }
}


================================================
FILE: UXM/ArchiveKeys.cs
================================================
using System.Collections.Generic;

namespace UXM
{
    static class ArchiveKeys
    {
        public static Dictionary<string, string> DarkSouls3Keys = new Dictionary<string, string>
        {
            ["Data1"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEA05hqyboW/qZaJ3GBIABFVt1X1aa0/sKINklvpkTRC+5Ytbxvp18L
M1gN6gjTgSJiPUgdlaMbptVa66MzvilEk60aHyVVEhtFWy+HzUZ3xRQm6r/2qsK3
8wXndgEU5JIT2jrBXZcZfYDCkUkjsGVkYqjBNKfp+c5jlnNwbieUihWTSEO+DA8n
aaCCzZD3e7rKhDQyLCkpdsGmuqBvl02Ou7QeehbPPno78mOYs2XkP6NGqbFFGQwa
swyyyXlQ23N15ZaFGRRR0xYjrX4LSe6OJ8Mx/Zkec0o7L28CgwCTmcD2wO8TEATE
AUbbV+1Su9uq2+wQxgnsAp+xzhn9og9hmwIEC35bSQ==
-----END RSA PUBLIC KEY-----",

            ["Data2"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEAvCZAK9UfPdk5JaTlG7n1r0LSVzIan3h0BSLaMXQHOwO7tTGpvtdX
m2ZLY9y8SVmOxWTQqRq14aVGLTKDyH87hPuKd47Y0E5K5erTqBbXW6AD4El1eir2
VJz/pwHt73FVziOlAnao1A5MsAylZ9B5QJyzHJQG+LxzMzmWScyeXlQLOKudfiIG
0qFw/xhRMLNAI+iypkzO5NKblYIySUV5Dx7649XdsZ5UIwJUhxONsKuGS+MbeTFB
mTMehtNj5EwPxGdT4CBPAWdeyPhpoHJHCbgrtnN9akwQmpwdBBxT/sTD16Adn9B+
TxuGDQQALed4S4KvM+fadx27pQz8pP9VLwIEL67iCQ==
-----END RSA PUBLIC KEY-----",

            ["Data3"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEAqLytWD20TSXPeAA1RGDwPW18nJwe2rBX+0HPtdzFmQc/KmQlWrP+
94k6KClK5f7m0xUHwT8+yFGLxPdRvUPyOhBEnRA6tkObVDSxij5y0Jh4h4ilAO73
I8VMcmscS71UKkck4444+eR4vVd+SPlzIu8VgqLefvEn/sX/pAevDp7w+gD0NgvO
e9U6iWEXKwTOPB97X+Y2uB03gSSognmV8h2dtUFJ4Ryn5jrpWmsuUbdvGp0CWBKH
CFruNXnfsG0hlf9LqbVmEzbFl/MhjBmbVjjtelorZsoLPK+OiPTHW5EcwwnPh1vH
FFGM7qRMc0yvHqJnniEWDsSz8Bvg+GxpgQIEC8XNVw==
-----END RSA PUBLIC KEY-----",

            ["Data4"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEArfUaZWjYAUaZ0q+5znpX55GeyepawCZ5NnsMjIW9CA3vrOgUGRkh
6aAU9frlafQ81LQMRgAznOnQGE7K3ChfySDpq6b47SKm4bWPqd7Ulh2DTxIgi6QP
qm4UUJL2dkLaCnuoya/pGMOOvhT1LD/0CKo/iKwfBcYf/OAnwSnxMRC3SNRugyvF
ylCet9DEdL5L8uBEa4sV4U288ZxZSZLg2tB10xy5SHAsm1VNP4Eqw5iJbqHEDKZW
n2LJP5t5wpEJvV2ACiA4U5fyjQLDzRwtCKzeK7yFkKiZI95JJhU/3DnVvssjIxku
gYZkS9D3k9m+tkNe0VVrd4mBEmqVxg+V9wIEL6Y6tw==
-----END RSA PUBLIC KEY-----",

            ["Data5"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEAvKTlU3nka4nQesRnYg1NWovCCTLhEBAnjmXwI69lFYfc4lvZsTrQ
E0Y25PtoP0ZddA3nzflJNz1rBwAkqfBRGTeeTCAyoNp/iel3EAkid/pKOt3JEkHx
rojRuWYSQ0EQawcBbzCfdLEjizmREepRKHIUSDWgu0HTmwSFHHeCFbpBA1h99L2X
izH5XFTOu0UIcUmBLsK6DYsIj5QGrWaxwwXcTJN/X+/syJ/TbQK9W/TCGaGiirGM
1u2wvZXSZ7uVM3CHwgNhAMiqLvqORygcDeNqxgq+dXDTxka43j7iPJWdHs8b25fy
aH3kbUxKlDGaEENNNyZQcQrgz8Q76jIE0QIEFUsz9w==
-----END RSA PUBLIC KEY-----",

            ["DLC1"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEAsCGM9dFwzaIOUIin3DXy7xrmI2otKGLZJQyKi5X3znKhSTywpcFc
KoW6hgjeh4fJW24jhzwBosG6eAzDINm+K02pHCG8qZ/D/hIbu+ui0ENDKqrVyFhn
QtX5/QJkVQtj8M4a0FIfdtE3wkxaKtP6IXWIy4DesSdGWONVWLfi2eq62A5ts5MF
qMoSV3XjTYuCgXqZQ6eOE+NIBQRqpZxLNFSzbJwWXpAg2kBMkpy5+ywOByjmWzUw
jnIFl1T17R8DpTU/93ojx+/q1p+b1o5is5KcoP7QwjOqzjHJH8bTytzRbgmRcDMW
3ahxgI070d45TMXK2YwRzI6/JbM1P29anQIEFezyYw==
-----END RSA PUBLIC KEY-----",

            ["DLC2"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEAtCXU9a/GBMVoqtpQox9p0/5sWPaIvDp8avLFnIBhN7vkgTwulZHi
u64vZAiUAdVeFX4F+Qtk+5ivK488Mu2CzAMJcz5RvyMQJtOQXuDDqzIv21Tr5zuu
sswoErHxxP8TZNxkHm7Ram7Oqtn7LQnMTYxsBgZZ34yJkRtAmZnGoCu5YaUR5euk
8lF75idi97ssczUNV212tLzIMa1YOV7sxOb7+gc0VTIqs3pa+OXLPI/bMfwUc/KN
jur5aLDDntQHGx5zuNtc78gMGwlmPqDhgTusKPO4VyKvoL0kITYvukoXJATaa1HI
WVUjhLm+/uj8r8PNgolerDeS+8FM5Bpe9QIEHwCZLw==
-----END RSA PUBLIC KEY-----",
        };

        public static Dictionary<string, string> SekiroKeys = new Dictionary<string, string>
        {
            ["Data1"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEA92l+AWx1aV7mzt+6r00bm/qnc4b6NH3VVr/v4UxMcfzushL8jsn9
ZSP1ss95ot/quk8dOJsp0+/bvxH+C9DEezzNLSqqAGd2jq2PYosj/6FhYAKjjMlK
jNxcVPsKQug0Zby+KYsENirmEXcmA1fzltrISf6d6LKB1UFHHN9NRkLCm3idE4Pu
9852kPHbiL14EqfDCDgwm7kLeQdt3kUbcmdhu/6dvP42HGxBmAYLNFD3iAe7qLML
MFzmKKHQD2fRQK/431Z3xPK6Jp245AdR0AwUYVvnXq+/97wMX0C6UKvAZ+b/1ytD
Nu8vZt++lhJ01SjTc2A4hVPz7g1EEO5/TQIEKkj5Jw==
-----END RSA PUBLIC KEY-----",

            ["Data2"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBDAKCAQEAqhjoThWX8VwsTKTI1kjp0JBloCXhV8i99P1KPTCTDBnmhVQPdu+7
UQ5g4//eh0oqKaOUjet+0SP94QscjIIrhV91OzfIouIWgJJK/ROOP/A3sb5AlzPa
6YPcN8ODxR+esyrWhc6rHCt4qGvXVXrgh6zpZM5h5VCTSaup4qqIWm44EF3+FeYS
7faFg14rH0QEosieIIZFZmpI6SCJanlrVd+Zh13s4XcZfk0JdC2AEjxCQ2lKi3Un
WAMOcJc+8uHoMuNNo1PMpYQ6Z8Nzg5Cii7EnwbCDmuJw58tFBmbOVHZpkY93VIeF
maJXSE7ztTp0qTa05YZUsiU3g9HplkeTUwIFAP/xKZE=
-----END RSA PUBLIC KEY-----",

            ["Data3"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBDAKCAQEAx5jlgIvoHQLwSFsAwKFZbNo3fgZ89C7tj4hwiZsQVg8QnNZohXl5
S5Ep9pS2biOFsSkuZMXKmfYErh2CsdFbr7QR7kvPPianXNrkCI4xlfQwJvMmkLm9
6/JmRIUzTWp0kKJUJZJH/UIrXNn7fmk8Vmx1bQIi8bumGSl3gxeMhutv/lC9khsY
Tn0ABTJAbIbwNZ5GPXxzQZuQPXXDY52Gm+Fx7Yy1LiK/B6isIDJUN0xdgxdaXxGN
f5pPocMJjng0Ob3cjhGvdkysll/jYFnRx0La3CGmtLcXMtHheEQxzGueGDa/lkkl
AvvEXtcpKfyFQWcUheQZ8LngAh/UTJHtQwIFAOpVoU8=
-----END RSA PUBLIC KEY-----",

            ["Data4"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEAq8RyArk+eqMAcxLAHUDRYV7yScNKZpKSxGmgJZQ7y6Y8f5wdrNCt
byXfmsdQECStIGlkwWjtfm8t/bRZuxxPciAYaFsWo0Ze2BB6uY6ZteNpLJn82qbL
TXATf+af3kSrvICfvJwRzbfA/PRJRkHj2gJ6Tc7g6HK7S/4TiCZirq+c/zLY3gb8
A8uIFNI4j0qxTzfoAlS7K6spZjfnhZ6l7pYFh+glz15wAbppC9Oy/u5vUacozf4v
nacbUHD47ds9EZPZDHk3LfJbioHwtUzJfyBqZmIpI33yiwImPpb96zwvQU86TaXK
sJrTmSs/48BeDsQwXuaqOg+6noETBx3pgQIEGM2Ohw==
-----END RSA PUBLIC KEY-----",

            ["Data5"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBDAKCAQEAu75/UbXwHdvu/p49TwnY7Ou6DAuZYFAtLUkw/R4nvm0HWVlRsZiB
LG3MOG6sPmK2Zc3JLBU2QK4uKazZ9VrmotM4OpYr03q2tiFnv3NfCvB1UeIJIKe3
kVhHNZIbvrwEP9a5UCnrSHD+u+Fj5MQBr4yrEitwrNVvIC4J0Ez1Ppn3+D8ff8Xg
QRP9qCVLI3X/wdQDea+B5o8PWaYEL9MKnnL1Tq4h+4PRYHcQR8/GXBTrc3x9q3cP
QRDWHbRYhIfWSP9urtagjcsmcuG+p34fp+KyWOwkil3FJqwH1KgSTbk9Tb0oBPzq
TCJKeE/wgu6hY++lBi5T3ArHZZcsbXzV6wIFAPlRTMc=
-----END RSA PUBLIC KEY-----",
        };

        public static Dictionary<string, string> SekiroBonusKeys = new Dictionary<string, string>
        {
            ["Data"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBDAKCAQEAxFOPK7c3E2Tu8HSS3NUlWUHdlJZIJiHf/0DhyLZUP68iEhJ8SLQ0
sDAgFBxIAEZQcVZBKLhTZiTyqaqIolgCDH6ZcMlWOGOWj3G6PuhPeb/7ZeQSo7Xv
plGCovqnioRoaFf4gVZDsbpVXIGNXwWsL5kArQiQo3ZrMs17/t77yZ6avC/1hnFp
ks1k3uQ269NKZOpU6Q73I8yolUFGJFBlm9uHqRfZC0wcA+IXjo96C1PoTKJQktkh
J07MPeoeckkAGdUv9S+kcDN04SAGMJJBWB9OOvn2Qle938gmCY6beeuk8c/l67zs
ChgwGmsLdVr7W6hZL3aNvsf/BWFQ+e7+tQIFANZbM50=
-----END RSA PUBLIC KEY-----",
        };

        public static Dictionary<string, string> EldenRingKeys = new Dictionary<string, string>
        {
            ["Data0"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEA9Rju2whruXDVQZpfylVEPeNxm7XgMHcDyaaRUIpXQE0qEo+6Y36L
P0xpFvL0H0kKxHwpuISsdgrnMHJ/yj4S61MWzhO8y4BQbw/zJehhDSRCecFJmFBz
3I2JC5FCjoK+82xd9xM5XXdfsdBzRiSghuIHL4qk2WZ/0f/nK5VygeWXn/oLeYBL
jX1S8wSSASza64JXjt0bP/i6mpV2SLZqKRxo7x2bIQrR1yHNekSF2jBhZIgcbtMB
xjCywn+7p954wjcfjxB5VWaZ4hGbKhi1bhYPccht4XnGhcUTWO3NmJWslwccjQ4k
sutLq3uRjLMM0IeTkQO6Pv8/R7UNFtdCWwIERzH8IQ==
-----END RSA PUBLIC KEY-----",

            ["Data1"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEAxaBCHQJrtLJiJNdG9nq3deA9sY4YCZ4dbTOHO+v+YgWRMcE6iK6o
ZIJq+nBMUNBbGPmbRrEjkkH9M7LAypAFOPKC6wMHzqIMBsUMuYffulBuOqtEBD11
CAwfx37rjwJ+/1tnEqtJjYkrK9yyrIN6Y+jy4ftymQtjk83+L89pvMMmkNeZaPON
4O9q5M9PnFoKvK8eY45ZV/Jyk+Pe+xc6+e4h4cx8ML5U2kMM3VDAJush4z/05hS3
/bC4B6K9+7dPwgqZgKx1J7DBtLdHSAgwRPpijPeOjKcAa2BDaNp9Cfon70oC+ZCB
+HkQ7FjJcF7KaHsH5oHvuI7EZAl2XTsLEQIENa/2JQ==
-----END RSA PUBLIC KEY-----",

            ["Data2"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBDAKCAQEA0iDVVQ230RgrkIHJNDgxE7I/2AaH6Li1Eu9mtpfrrfhfoK2e7y4O
WU+lj7AGI4GIgkWpPw8JHaV970Cr6+sTG4Tr5eMQPxrCIH7BJAPCloypxcs2BNfT
GXzm6veUfrGzLIDp7wy24lIA8r9ZwUvpKlN28kxBDGeCbGCkYeSVNuF+R9rN4OAM
RYh0r1Q950xc2qSNloNsjpDoSKoYN0T7u5rnMn/4mtclnWPVRWU940zr1rymv4Jc
3umNf6cT1XqrS1gSaK1JWZfsSeD6Dwk3uvquvfY6YlGRygIlVEMAvKrDRMHylsLt
qqhYkZNXMdy0NXopf1rEHKy9poaHEmJldwIFAP////8=
-----END RSA PUBLIC KEY-----",

            ["Data3"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEAvRRNBnVq3WknCNHrJRelcEA2v/OzKlQkxZw1yKll0Y2Kn6G9ts94
SfgZYbdFCnIXy5NEuyHRKrxXz5vurjhrcuoYAI2ZUhXPXZJdgHywac/i3S/IY0V/
eDbqepyJWHpP6I565ySqlol1p/BScVjbEsVyvZGtWIXLPDbx4EYFKA5B52uK6Gdz
4qcyVFtVEhNoMvg+EoWnyLD7EUzuB2Khl46CuNictyWrLlIHgpKJr1QD8a0ld0PD
PHDZn03q6QDvZd23UW2d9J+/HeBt52j08+qoBXPwhndZsmPMWngQDaik6FM7EVRQ
etKPi6h5uprVmMAS5wR/jQIVTMpTj/zJdwIEXszeQw==
-----END RSA PUBLIC KEY-----",

            ["DLC"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEAmYJ/5GJU4boJSvZ81BFOHYTGdBWPHnWYly3yWo01BYjGRnz8NTkz
DHUxsbjIgtG5XqsQfZstZILQ97hgSI5AaAoCGrT8sn0PeXg2i0mKwL21gRjRUdvP
Dp1Y+7hgrGwuTkjycqqsQ/qILm4NvJHvGRd7xLOJ9rs2zwYhceRVrq9XU2AXbdY4
pdCQ3+HuoaFiJ0dW0ly5qdEXjbSv2QEYe36nWCtsd6hEY9LjbBX8D1fK3D2c6C0g
NdHJGH2iEONUN6DMK9t0v2JBnwCOZQ7W+Gt7SpNNrkx8xKEM8gH9na10g9ne11Mi
O1FnLm8i4zOxVdPHQBKICkKcGS1o3C2dfwIEXw/f3w==
-----END RSA PUBLIC KEY-----",

            ["sd\\sd"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEAmYJ/5GJU4boJSvZ81BFOHYTGdBWPHnWYly3yWo01BYjGRnz8NTkz
DHUxsbjIgtG5XqsQfZstZILQ97hgSI5AaAoCGrT8sn0PeXg2i0mKwL21gRjRUdvP
Dp1Y+7hgrGwuTkjycqqsQ/qILm4NvJHvGRd7xLOJ9rs2zwYhceRVrq9XU2AXbdY4
pdCQ3+HuoaFiJ0dW0ly5qdEXjbSv2QEYe36nWCtsd6hEY9LjbBX8D1fK3D2c6C0g
NdHJGH2iEONUN6DMK9t0v2JBnwCOZQ7W+Gt7SpNNrkx8xKEM8gH9na10g9ne11Mi
O1FnLm8i4zOxVdPHQBKICkKcGS1o3C2dfwIEXw/f3w==
-----END RSA PUBLIC KEY-----",

            ["sd\\sd_dlc02"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEAmYJ/5GJU4boJSvZ81BFOHYTGdBWPHnWYly3yWo01BYjGRnz8NTkz
DHUxsbjIgtG5XqsQfZstZILQ97hgSI5AaAoCGrT8sn0PeXg2i0mKwL21gRjRUdvP
Dp1Y+7hgrGwuTkjycqqsQ/qILm4NvJHvGRd7xLOJ9rs2zwYhceRVrq9XU2AXbdY4
pdCQ3+HuoaFiJ0dW0ly5qdEXjbSv2QEYe36nWCtsd6hEY9LjbBX8D1fK3D2c6C0g
NdHJGH2iEONUN6DMK9t0v2JBnwCOZQ7W+Gt7SpNNrkx8xKEM8gH9na10g9ne11Mi
O1FnLm8i4zOxVdPHQBKICkKcGS1o3C2dfwIEXw/f3w==
-----END RSA PUBLIC KEY-----",
        };

        public static Dictionary<string, string> ArmoredCore6Keys = new Dictionary<string, string>
        {
            ["Data0"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBDAKCAQEA7F43Ss9kroawBSUW6GBhSUo6GtxYtUV8zCPkcHhSJLGPASHhwsaX
zMRrd+Ul9qB3oYchb4xYtdMWKFe0/ZDi9vgYXvF3rlWaZKAu1k/F6RwVAd//I3Kj
JsYlhayskInKqB3BvB/KL2Ga8QBsZ/G9cLlUYsqIj3as9oqbfEXVmGVeuhg0I+NQ
NL+2sThqp5eOQstfXQgqduOt0ixd/r9e5VjLhyj2z4hCEF2TVsDw9wGEBem1TkcO
C/E8obl9fTHwEK7l2i8a4HafY7flU220r8y4UwQ+9Aq94xUYT2xdcTjdyBIaZtyS
YmR86B680OyL9oiEonEFhh4cor/84PSmNQIFAOHX27k=
-----END RSA PUBLIC KEY-----",

            ["Data1"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEAsM5QTi6Fo1li23fkvP7jXqFlanR61VS1znElmsZH0Ez4LtuM7WUC
QnZyi9u15T89WmIKCGpfgHZBgJEVFqW9FMhBxrA5/gXcqnGESjc+NNF71rfug/qg
Ue7B9tXlq18/bdD7qPEjYY02H5fh4Z/g0+oClSNyZR46G/MXZSw8KMV4QHikCAxJ
N40Nxd+MpQcpc3J5SXfsXxi9gNSxHO1+KzGwRrEh1/9d7bPyd4jBuTR+SEd+ZDHR
3jTbbRNUypB/x780KXuJnGrC8UfB6ttxfBmLs7nmhteO6R1rr5zWuHJBry7Of9t4
JEQRDwb2VT3fpQ2oHgOc5zDYMOdObdX/tQIEZYdnGQ==
-----END RSA PUBLIC KEY-----",

            ["Data2"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBDAKCAQEApvNV8cCaxTBtW6kB94Gd5/+NuQnVLxRo6b0QUSSXh8KGWCRNPjpq
LEyu0kuHCTG5xfomzB5vlq9INu0odZAWZu+NWvz+YydnIQO+UPDF9J/wE92SMzBj
n7d4uEglevPswQLiJVQThCtrl1B8dCz7vFvlSknx23jdUQ/0hfxVnLvP2GpNW/v5
iDK+J2RJFxpd8td9FpHMF+OMxT3pvQyOBleWgEcmiaA1O6AxZA3YGWaL7qnKgx4M
Pi5Ex1Cjnw66+A25kc34UvDA4pteJHC+AwTvjLN3nF2jr3l61jEcXULCWpA4rdWT
dm77dL2KwxXDiYxNAecEFVuG/PRV7J8hHQIFAP3yuSk=
-----END RSA PUBLIC KEY-----",

            ["Data3"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBDAKCAQEAvS4XXheufoQvvfTksJhO7JrH1ykMa2ogHtqHhAOZXorLLXvsWfVO
Q+enFY7kBjKyVbUOlqj3M6Ho2S8QgJTO/Xz3DhD3YlHva59RnIXI2gmSyvrTB0Z/
GopmJzVfc9o7763CMy/27tS4/dBM9qKs+csvjE6fG470Z025yECgtTtXzltg4pht
GkjV5+tNjrFt5+wxIydNB56Xow9QCxtpZJ4TstdZvbgq1K06mpLrRTRDxpLPgdDA
9KKwyewYliU2tl78bU5jcgL3s78KbiJ2VSrlOL2AxI6TpID+kFcDy055JsMkKR2V
nRPreV08oQchzQ5miTezWUAk7mIcZoFHwwIFAP////8=
-----END RSA PUBLIC KEY-----",

            ["sd\\sd"] =
@"-----BEGIN RSA PUBLIC KEY-----
MIIBCwKCAQEAvbz2HnG3JaP3imwnZJMWCyzW9ZjrgzgxZ/EtzFrzpeYPFdYGmBim
XFfBarWpREW7M4y6Z7iy4UAbNmF9SLDp6RLiKauI9AxQK3ICYf+2UuDaXO6QeeXM
JgwQhIugkQFobZOnJLpGT4ynWvH0iR2LO/aFivAPry+bkKXCX9y5zfod2at6j0Ri
7jJ+SECnWs7rDxsBo/98aJpmoyl+Z24yvBU+sknUVn7giaFPTOet9YvBzNmAing4
6fBFXV6T4sX+hyCY2Qs2arnH+TSDTUcxK/3lobC7lSy+B+sTinqN0a+SWeaCACYe
viCKV6AQNxb8J1CHev0OJv9r+bMSy+1kxwIEILt78w==
-----END RSA PUBLIC KEY-----",
        };
    }
}


================================================
FILE: UXM/ArchiveUnpacker.cs
================================================
using SoulsFormats;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace UXM
{
    static class ArchiveUnpacker
    {
        private const int WRITE_LIMIT = 1024 * 1024 * 100;

        public static string Unpack(string exePath, IProgress<(double value, string status)> progress, CancellationToken ct)
        {
            progress.Report((0, "Preparing to unpack..."));
            string gameDir = Path.GetDirectoryName(exePath);

            Util.Game game;
            GameInfo gameInfo;
            try
            {
                game = Util.GetExeVersion(exePath);
                gameInfo = GameInfo.GetGameInfo(game);
            }
            catch (Exception ex)
            {
                return $"Failed to get game info.\r\n\r\n{ex}";
            }

            Dictionary<string, string> keys;
            try
            {
                Dictionary<string, string> loadDs2Keys()
                {
                    var keys = new Dictionary<string, string>();
                    foreach (string archive in gameInfo.Archives)
                    {
                        string pemPath = $@"{gameDir}\{archive.Replace("Ebl", "KeyCode")}.pem";
                        keys[archive] = File.ReadAllText(pemPath);
                    }
                    return keys;
                }

                keys = game switch
                {
                    Util.Game.DarkSouls2 => loadDs2Keys(),
                    Util.Game.Scholar => loadDs2Keys(),
                    Util.Game.DarkSouls3 => ArchiveKeys.DarkSouls3Keys,
                    Util.Game.Sekiro => ArchiveKeys.SekiroKeys,
                    Util.Game.SekiroBonus => ArchiveKeys.SekiroBonusKeys,
                    Util.Game.EldenRing => ArchiveKeys.EldenRingKeys,
                    Util.Game.ArmoredCore6 => ArchiveKeys.ArmoredCore6Keys,
                    _ => throw new NotImplementedException(),
                };
            }
            catch (Exception ex)
            {
                return $"Failed to load archive keys.\r\n\r\n{ex}";
            }

            string drive = Path.GetPathRoot(Path.GetFullPath(gameDir));
            DriveInfo driveInfo = new DriveInfo(drive);

            if (driveInfo.AvailableFreeSpace < gameInfo.RequiredGB * 1024 * 1024 * 1024)
            {
                DialogResult choice = MessageBox.Show(
                    $"{gameInfo.RequiredGB} GB of free space is required to fully unpack this game; " +
                    $"only {driveInfo.AvailableFreeSpace / (1024f * 1024 * 1024):F1} GB available.\r\n" +
                    "If you're only doing a partial unpack to restore some files you may ignore this warning, " +
                    "otherwise it will most likely fail.\r\n\r\n" +
                    "Do you want to continue?",
                    "Space Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);

                if (choice == DialogResult.No)
                    return null;
            }

            if (ct.IsCancellationRequested)
                return null;

            try
            {
                for (int i = 0; i < gameInfo.BackupDirs.Count; i++)
                {
                    string backup = gameInfo.BackupDirs[i];
                    progress.Report(((1.0 + (double)i / gameInfo.BackupDirs.Count) / (gameInfo.Archives.Count + 2.0),
                        $"Backing up directory \"{backup}\" ({i + 1}/{gameInfo.BackupDirs.Count})..."));

                    string backupSource = $@"{gameDir}\{backup}";
                    string backupTarget = $@"{gameDir}\_backup\{backup}";

                    if (Directory.Exists(backupSource) && !Directory.Exists(backupTarget))
                    {
                        foreach (string file in Directory.GetFiles(backupSource, "*", SearchOption.AllDirectories))
                        {
                            string relative = file.Substring(backupSource.Length + 1);
                            string target = backupTarget + "\\" + relative;
                            Directory.CreateDirectory(Path.GetDirectoryName(target));
                            File.Copy(file, target);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                return $"Failed to back up directories.\r\n\r\n{ex}";
            }

            for (int i = 0; i < gameInfo.Archives.Count; i++)
            {
                if (ct.IsCancellationRequested)
                    return null;

                string archive = gameInfo.Archives[i];
                string error = UnpackArchive(gameDir, archive, keys[archive], i,
                    gameInfo.Archives.Count, gameInfo.BHD5Game, gameInfo.Dictionary, progress, ct).Result;
                if (error != null)
                    return error;
            }

            progress.Report((1, "Unpacking complete!"));
            return null;
        }

        private static async Task<string> UnpackArchive(string gameDir, string archive, string key, int index, int total,
            BHD5.Game gameVersion, ArchiveDictionary archiveDictionary,
            IProgress<(double value, string status)> progress, CancellationToken ct)
        {
            progress.Report(((index + 2.0) / (total + 2.0), $"Loading {archive}..."));
            string bhdPath = $@"{gameDir}\{archive}.bhd";
            string bdtPath = $@"{gameDir}\{archive}.bdt";
            string outDir = Path.GetDirectoryName(bhdPath);

            if (File.Exists(bhdPath) && File.Exists(bdtPath))
            {
                BHD5 bhd;
                try
                {
                    bool encrypted = true;
                    using (FileStream fs = File.OpenRead(bhdPath))
                    {
                        byte[] magic = new byte[4];
                        fs.Read(magic, 0, 4);
                        encrypted = Encoding.ASCII.GetString(magic) != "BHD5";
                    }

                    if (encrypted)
                    {
                        using MemoryStream bhdStream = CryptographyUtility.DecryptRsa(bhdPath, key);
                        bhd = BHD5.Read(bhdStream, gameVersion);
                    }
                    else
                    {
                        using FileStream bhdStream = File.OpenRead(bhdPath);
                        bhd = BHD5.Read(bhdStream, gameVersion);
                    }
                }
                catch (OverflowException ex)
                {
                    return $"Failed to open BHD:\n{bhdPath}\n\n{ex}";
                }

                int fileCount = bhd.Buckets.Sum(b => b.Count);

                try
                {
                    var asyncFileWriters = new List<Task<long>>();
                    using (FileStream bdtStream = File.OpenRead(bdtPath))
                    {
                        int currentFile = -1;
                        long writingSize = 0;

                        foreach (BHD5.Bucket bucket in bhd.Buckets)
                        {
                            if (ct.IsCancellationRequested)
                                break;

                            foreach (BHD5.FileHeader header in bucket)
                            {
                                if (ct.IsCancellationRequested)
                                    break;

                                currentFile++;

                                string path;
                                bool unknown;
                                if (archiveDictionary.TryGetValue(header.FileNameHash, out path))
                                {
                                    unknown = false;
                                    path = $@"{outDir}\{path.Replace('/', '\\')}";
                                    if (File.Exists(path))
                                        continue;
                                }
                                else
                                {
                                    unknown = true;
                                    string filename = $"{archive}_{header.FileNameHash:x16}";
                                    string directory = $@"{outDir}\_unknown";
                                    path = $@"{directory}\{filename}";
                                    if (File.Exists(path) || Directory.Exists(directory) && Directory.GetFiles(directory, $"{filename}.*").Length > 0)
                                        continue;
                                }

                                progress.Report(((index + 2.0 + currentFile / (double)fileCount) / (total + 2.0),
                                    $"Unpacking {archive} ({currentFile + 1}/{fileCount})..."));

                                while (asyncFileWriters.Count > 0 && writingSize + header.PaddedFileSize > WRITE_LIMIT)
                                {
                                    for (int i = 0; i < asyncFileWriters.Count; i++)
                                    {
                                        if (asyncFileWriters[i].IsCompleted)
                                        {
                                            writingSize -= await asyncFileWriters[i];
                                            asyncFileWriters.RemoveAt(i);
                                        }
                                    }

                                    if (asyncFileWriters.Count > 0 && writingSize + header.PaddedFileSize > WRITE_LIMIT)
                                        Thread.Sleep(10);
                                }

                                byte[] bytes;
                                try
                                {
                                    bytes = header.ReadFile(bdtStream);
                                    if (header.UnpaddedFileSize != -1 && header.UnpaddedFileSize != 0)
                                        Array.Resize(ref bytes, (int)header.UnpaddedFileSize);

                                    if (unknown)
                                    {
                                        var br = new BinaryReaderEx(false, bytes);
                                        if (bytes.Length >= 3 && br.GetASCII(0, 3) == "GFX")
                                            path += ".gfx";
                                        else if (bytes.Length >= 4 && br.GetASCII(0, 4) == "FSB5")
                                            path += ".fsb";
                                        else if (bytes.Length >= 0x19 && br.GetASCII(0xC, 0xE) == "ITLIMITER_INFO")
                                            path += ".itl";
                                        else if (bytes.Length >= 0x10 && br.GetASCII(8, 8) == "FEV FMT ")
                                            path += ".fev";
                                        else if (bytes.Length >= 4 && br.GetASCII(1, 3) == "Lua")
                                            path += ".lua";
                                        else if (bytes.Length >= 4 && br.GetASCII(0, 4) == "DDS ")
                                            path += ".dds";
                                        else if (bytes.Length >= 4 && br.GetASCII(0, 4) == "#BOM")
                                            path += ".txt";
                                        else if (bytes.Length >= 4 && br.GetASCII(0, 4) == "BHF4")
                                            path += ".bhd";
                                        else if (bytes.Length >= 4 && br.GetASCII(0, 4) == "BDF4")
                                            path += ".bdt";
                                        else if (bytes.Length >= 4 && br.GetASCII(0, 4) == "ENFL")
                                            path += ".entryfilelist";
                                        else if (bytes.Length >= 4 && br.GetASCII(0, 4) == "DCX\0")
                                            path += ".dcx";
                                        br.Stream.Close();
                                    }
                                }
                                catch (Exception ex)
                                {
                                    return $"Failed to read file:\r\n{path}\r\n\r\n{ex}";
                                }

                                try
                                {
                                    Directory.CreateDirectory(Path.GetDirectoryName(path));
                                    writingSize += bytes.Length;
                                    asyncFileWriters.Add(WriteFileAsync(path, bytes));
                                }
                                catch (Exception ex)
                                {
                                    return $"Failed to write file:\r\n{path}\r\n\r\n{ex}";
                                }
                            }
                        }
                    }

                    foreach (Task<long> task in asyncFileWriters)
                        await task;
                }
                catch (Exception ex)
                {
                    return $"Failed to unpack BDT:\r\n{bdtPath}\r\n\r\n{ex}";
                }
            }

            return null;
        }

        private static async Task<long> WriteFileAsync(string path, byte[] bytes)
        {
            using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 4096, true))
            {
                await fs.WriteAsync(bytes);
            }
            return bytes.Length;
        }
    }
}


================================================
FILE: UXM/CryptographyUtility.cs
================================================
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.OpenSsl;
using System;
using System.IO;

namespace UXM
{
    /// <summary>
    /// These RSA functions are copy-pasted straight from BinderTool. Thank you Atvaark!
    /// </summary>
    internal static class CryptographyUtility
    {
        /// <summary>
        ///     Decrypts a file with a provided decryption key.
        /// </summary>
        /// <param name="filePath">An encrypted file</param>
        /// <param name="key">The RSA key in PEM format</param>
        /// <exception cref="ArgumentNullException">When the argument filePath is null</exception>
        /// <exception cref="ArgumentNullException">When the argument keyPath is null</exception>
        /// <returns>A memory stream with the decrypted file</returns>
        public static MemoryStream DecryptRsa(string filePath, string key)
        {
            if (filePath == null)
            {
                throw new ArgumentNullException(nameof(filePath));
            }

            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            AsymmetricKeyParameter keyParameter = GetKeyOrDefault(key);
            RsaEngine engine = new RsaEngine();
            engine.Init(false, keyParameter);

            MemoryStream outputStream = new MemoryStream();
            using (FileStream inputStream = File.OpenRead(filePath))
            {

                int inputBlockSize = engine.GetInputBlockSize();
                int outputBlockSize = engine.GetOutputBlockSize();
                byte[] inputBlock = new byte[inputBlockSize];
                while (inputStream.Read(inputBlock, 0, inputBlock.Length) > 0)
                {
                    byte[] outputBlock = engine.ProcessBlock(inputBlock, 0, inputBlockSize);

                    int requiredPadding = outputBlockSize - outputBlock.Length;
                    if (requiredPadding > 0)
                    {
                        byte[] paddedOutputBlock = new byte[outputBlockSize];
                        outputBlock.CopyTo(paddedOutputBlock, requiredPadding);
                        outputBlock = paddedOutputBlock;
                    }

                    outputStream.Write(outputBlock, 0, outputBlock.Length);
                }
            }

            outputStream.Seek(0, SeekOrigin.Begin);
            return outputStream;
        }

        public static AsymmetricKeyParameter GetKeyOrDefault(string key)
        {
            try
            {
                PemReader pemReader = new PemReader(new StringReader(key));
                return (AsymmetricKeyParameter)pemReader.ReadObject();
            }
            catch
            {
                return null;
            }
        }
    }
}


================================================
FILE: UXM/ExePatcher.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace UXM
{
    class ExePatcher
    {
        private static readonly Encoding UTF16 = Encoding.Unicode;

        public static string Patch(string exePath, IProgress<(double value, string status)> progress, CancellationToken ct)
        {
            progress.Report((0, "Preparing to patch..."));
            string gameDir = Path.GetDirectoryName(exePath);
            string exeName = Path.GetFileName(exePath);

            Util.Game game;
            GameInfo gameInfo;
            try
            {
                game = Util.GetExeVersion(exePath);
                gameInfo = GameInfo.GetGameInfo(game);
            }
            catch (Exception ex)
            {
                return ex.Message;
            }

            if (game == Util.Game.Sekiro)
            {
                DialogResult choice = MessageBox.Show("For Sekiro, most users should use Mod Engine instead of patching with UXM. Patching a vanilla exe will cause the game to crash on startup.\n" +
                    "Are you sure you want to patch?", "Caution", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                if (choice == DialogResult.No)
                {
                    progress.Report((1, "Patching cancelled."));
                    return null;
                }
            }

            if (!File.Exists(gameDir + "\\_backup\\" + exeName))
            {
                try
                {
                    Directory.CreateDirectory(gameDir + "\\_backup");
                    File.Copy(exePath, gameDir + "\\_backup\\" + exeName);
                }
                catch (Exception ex)
                {
                    return $"Failed to backup file:\r\n{exePath}\r\n\r\n{ex}";
                }
            }

            byte[] bytes;
            try
            {
                bytes = File.ReadAllBytes(exePath);
            }
            catch (Exception ex)
            {
                return $"Failed to read file:\r\n{exePath}\r\n\r\n{ex}";
            }

            try
            {
                for (int i = 0; i < gameInfo.Replacements.Count; i++)
                {
                    if (ct.IsCancellationRequested)
                        return null;

                    string target = gameInfo.Replacements[i];
                    string replacement = "." + new string('/', target.Length - 1);

                    // Add 1.0 for preparation step
                    progress.Report(((i + 1.0) / (gameInfo.Replacements.Count + 1.0), $"Patching alias \"{target}\" ({i + 1}/{gameInfo.Replacements.Count})..."));

                    replace(bytes, target, replacement);
                }
            }
            catch (Exception ex)
            {
                return $"Failed to patch file:\r\n{exePath}\r\n\r\n{ex}";
            }

            try
            {
                File.WriteAllBytes(exePath, bytes);
            }
            catch (Exception ex)
            {
                return $"Failed to write file:\r\n{exePath}\r\n\r\n{ex}";
            }

            progress.Report((1, "Patching complete!"));
            return null;
        }

        private static void replace(byte[] bytes, string target, string replacement)
        {
            byte[] targetBytes = UTF16.GetBytes(target);
            byte[] replacementBytes = UTF16.GetBytes(replacement);
            if (targetBytes.Length != replacementBytes.Length)
                throw new ArgumentException($"Target length: {targetBytes.Length} | Replacement length: {replacementBytes.Length}");

            List<int> offsets = findBytes(bytes, targetBytes);
            foreach (int offset in offsets)
                Array.Copy(replacementBytes, 0, bytes, offset, replacementBytes.Length);
        }

        private static List<int> findBytes(byte[] bytes, byte[] find)
        {
            List<int> offsets = new List<int>();
            for (int i = 0; i < bytes.Length - find.Length; i++)
            {
                bool found = true;
                for (int j = 0; j < find.Length; j++)
                {
                    if (find[j] != bytes[i + j])
                    {
                        found = false;
                        break;
                    }
                }

                if (found)
                    offsets.Add(i);
            }
            return offsets;
        }
    }
}


================================================
FILE: UXM/FormMain.Designer.cs
================================================
namespace UXM
{
    partial class FormMain
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            components = new System.ComponentModel.Container();
            System.Windows.Forms.Label lblBreak;
            System.Windows.Forms.Label lblExePath;
            System.Windows.Forms.Label lblStatus;
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormMain));
            btnPatch = new System.Windows.Forms.Button();
            btnUnpack = new System.Windows.Forms.Button();
            btnRestore = new System.Windows.Forms.Button();
            btnAbort = new System.Windows.Forms.Button();
            btnExplore = new System.Windows.Forms.Button();
            btnBrowse = new System.Windows.Forms.Button();
            txtExePath = new System.Windows.Forms.TextBox();
            txtStatus = new System.Windows.Forms.TextBox();
            pbrProgress = new System.Windows.Forms.ProgressBar();
            ofdExe = new System.Windows.Forms.OpenFileDialog();
            toolTip1 = new System.Windows.Forms.ToolTip(components);
            lblBreak = new System.Windows.Forms.Label();
            lblExePath = new System.Windows.Forms.Label();
            lblStatus = new System.Windows.Forms.Label();
            SuspendLayout();
            // 
            // lblBreak
            // 
            lblBreak.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
            lblBreak.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            lblBreak.Location = new System.Drawing.Point(-17, 131);
            lblBreak.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
            lblBreak.Name = "lblBreak";
            lblBreak.Size = new System.Drawing.Size(887, 3);
            lblBreak.TabIndex = 31;
            // 
            // lblExePath
            // 
            lblExePath.AutoSize = true;
            lblExePath.Location = new System.Drawing.Point(16, 14);
            lblExePath.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
            lblExePath.Name = "lblExePath";
            lblExePath.Size = new System.Drawing.Size(113, 20);
            lblExePath.TabIndex = 30;
            lblExePath.Text = "Executable Path";
            // 
            // lblStatus
            // 
            lblStatus.AutoSize = true;
            lblStatus.Location = new System.Drawing.Point(16, 143);
            lblStatus.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
            lblStatus.Name = "lblStatus";
            lblStatus.Size = new System.Drawing.Size(49, 20);
            lblStatus.TabIndex = 32;
            lblStatus.Text = "Status";
            // 
            // btnPatch
            // 
            btnPatch.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
            btnPatch.Location = new System.Drawing.Point(523, 80);
            btnPatch.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
            btnPatch.Name = "btnPatch";
            btnPatch.Size = new System.Drawing.Size(100, 35);
            btnPatch.TabIndex = 27;
            btnPatch.Text = "Patch";
            btnPatch.UseVisualStyleBackColor = true;
            btnPatch.Click += btnPatch_Click;
            // 
            // btnUnpack
            // 
            btnUnpack.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
            btnUnpack.Location = new System.Drawing.Point(415, 80);
            btnUnpack.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
            btnUnpack.Name = "btnUnpack";
            btnUnpack.Size = new System.Drawing.Size(100, 35);
            btnUnpack.TabIndex = 26;
            btnUnpack.Text = "Unpack";
            btnUnpack.UseVisualStyleBackColor = true;
            btnUnpack.Click += btnUnpack_Click;
            // 
            // btnRestore
            // 
            btnRestore.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
            btnRestore.Location = new System.Drawing.Point(631, 80);
            btnRestore.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
            btnRestore.Name = "btnRestore";
            btnRestore.Size = new System.Drawing.Size(100, 35);
            btnRestore.TabIndex = 28;
            btnRestore.Text = "Restore";
            btnRestore.UseVisualStyleBackColor = true;
            btnRestore.Click += btnRestore_Click;
            // 
            // btnAbort
            // 
            btnAbort.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
            btnAbort.Enabled = false;
            btnAbort.Location = new System.Drawing.Point(739, 80);
            btnAbort.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
            btnAbort.Name = "btnAbort";
            btnAbort.Size = new System.Drawing.Size(100, 35);
            btnAbort.TabIndex = 29;
            btnAbort.Text = "Abort";
            btnAbort.UseVisualStyleBackColor = true;
            btnAbort.Click += btnAbort_Click;
            // 
            // btnExplore
            // 
            btnExplore.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
            btnExplore.Location = new System.Drawing.Point(739, 35);
            btnExplore.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
            btnExplore.Name = "btnExplore";
            btnExplore.Size = new System.Drawing.Size(100, 35);
            btnExplore.TabIndex = 25;
            btnExplore.Text = "Explore";
            btnExplore.UseVisualStyleBackColor = true;
            btnExplore.Click += btnExplore_Click;
            // 
            // btnBrowse
            // 
            btnBrowse.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
            btnBrowse.Location = new System.Drawing.Point(631, 35);
            btnBrowse.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
            btnBrowse.Name = "btnBrowse";
            btnBrowse.Size = new System.Drawing.Size(100, 35);
            btnBrowse.TabIndex = 24;
            btnBrowse.Text = "Browse";
            btnBrowse.UseVisualStyleBackColor = true;
            btnBrowse.Click += btnBrowse_Click;
            // 
            // txtExePath
            // 
            txtExePath.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
            txtExePath.Location = new System.Drawing.Point(16, 38);
            txtExePath.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
            txtExePath.Name = "txtExePath";
            txtExePath.Size = new System.Drawing.Size(605, 27);
            txtExePath.TabIndex = 23;
            txtExePath.Text = "C:\\Program Files (x86)\\Steam\\steamapps\\common\\DARK SOULS III\\Game\\DarkSoulsIII.exe";
            // 
            // txtStatus
            // 
            txtStatus.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
            txtStatus.Location = new System.Drawing.Point(16, 168);
            txtStatus.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
            txtStatus.Name = "txtStatus";
            txtStatus.ReadOnly = true;
            txtStatus.Size = new System.Drawing.Size(821, 27);
            txtStatus.TabIndex = 33;
            // 
            // pbrProgress
            // 
            pbrProgress.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
            pbrProgress.Location = new System.Drawing.Point(16, 205);
            pbrProgress.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
            pbrProgress.Maximum = 1000;
            pbrProgress.Name = "pbrProgress";
            pbrProgress.Size = new System.Drawing.Size(823, 35);
            pbrProgress.TabIndex = 34;
            // 
            // ofdExe
            // 
            ofdExe.FileName = "DarkSoulsIII.exe";
            ofdExe.Filter = "Dark Souls Executable|*.exe";
            ofdExe.Title = "Select Dark Souls executable...";
            // 
            // FormMain
            // 
            AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
            AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            ClientSize = new System.Drawing.Size(855, 254);
            Controls.Add(txtStatus);
            Controls.Add(lblStatus);
            Controls.Add(pbrProgress);
            Controls.Add(lblBreak);
            Controls.Add(btnPatch);
            Controls.Add(btnUnpack);
            Controls.Add(btnRestore);
            Controls.Add(btnAbort);
            Controls.Add(btnExplore);
            Controls.Add(btnBrowse);
            Controls.Add(txtExePath);
            Controls.Add(lblExePath);
            Icon = (System.Drawing.Icon)resources.GetObject("$this.Icon");
            Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
            MaximumSize = new System.Drawing.Size(2661, 301);
            MinimumSize = new System.Drawing.Size(470, 301);
            Name = "FormMain";
            Text = "UXM <version>";
            Activated += FormMain_Activated;
            FormClosing += FormMain_FormClosing;
            Load += FormMain_Load;
            ResumeLayout(false);
            PerformLayout();
        }

        #endregion

        private System.Windows.Forms.Button btnPatch;
        private System.Windows.Forms.Button btnUnpack;
        private System.Windows.Forms.Button btnRestore;
        private System.Windows.Forms.Button btnAbort;
        private System.Windows.Forms.Button btnExplore;
        private System.Windows.Forms.Button btnBrowse;
        private System.Windows.Forms.TextBox txtExePath;
        private System.Windows.Forms.TextBox txtStatus;
        private System.Windows.Forms.ProgressBar pbrProgress;
        private System.Windows.Forms.OpenFileDialog ofdExe;
        private System.Windows.Forms.ToolTip toolTip1;
    }
}



================================================
FILE: UXM/FormMain.cs
================================================
using Microsoft.WindowsAPICodePack.Taskbar;
using System;
using System.Diagnostics;
using System.IO;
using System.Media;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace UXM
{
    public partial class FormMain : Form
    {
        private static Properties.Settings settings = Properties.Settings.Default;

        private bool closing;
        private CancellationTokenSource cts;
        private IProgress<(double value, string status)> progress;

        public FormMain()
        {
            InitializeComponent();

            closing = false;
            cts = null;
            progress = new Progress<(double value, string status)>(ReportProgress);
        }

        private void FormMain_Load(object sender, EventArgs e)
        {
            Text = "UXM " + Application.ProductVersion;
            EnableControls(true);

            Location = settings.WindowLocation;
            if (settings.WindowSize.Width >= MinimumSize.Width && settings.WindowSize.Height >= MinimumSize.Height)
                Size = settings.WindowSize;
            if (settings.WindowMaximized)
                WindowState = FormWindowState.Maximized;

            txtExePath.Text = settings.ExePath;
        }

        private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (cts != null)
            {
                txtStatus.Text = "Aborting...";
                closing = true;
                btnAbort.Enabled = false;
                cts.Cancel();
                e.Cancel = true;
            }
            else
            {
                settings.WindowMaximized = WindowState == FormWindowState.Maximized;
                if (WindowState == FormWindowState.Normal)
                {
                    settings.WindowLocation = Location;
                    settings.WindowSize = Size;
                }
                else
                {
                    settings.WindowLocation = RestoreBounds.Location;
                    settings.WindowSize = RestoreBounds.Size;
                }

                settings.ExePath = txtExePath.Text;
            }
        }

        private void btnAbort_Click(object sender, EventArgs e)
        {
            txtStatus.Text = "Aborting...";
            btnAbort.Enabled = false;
            cts.Cancel();
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            ofdExe.InitialDirectory = Path.GetDirectoryName(txtExePath.Text);
            if (ofdExe.ShowDialog() == DialogResult.OK)
                txtExePath.Text = ofdExe.FileName;
        }

        private void btnExplore_Click(object sender, EventArgs e)
        {
            string dir = Path.GetDirectoryName(txtExePath.Text);
            if (Directory.Exists(dir))
                Process.Start(new ProcessStartInfo(dir) { UseShellExecute = true });
            else
                SystemSounds.Hand.Play();
        }

        private async void btnPatch_Click(object sender, EventArgs e)
        {
            EnableControls(false);
            cts = new CancellationTokenSource();
            string error = await Task.Run(() => ExePatcher.Patch(txtExePath.Text, progress, cts.Token));

            if (cts.Token.IsCancellationRequested)
            {
                progress.Report((0, "Patching aborted."));
            }
            else if (error != null)
            {
                progress.Report((0, "Patching failed."));
                ShowError(error);
            }
            else
            {
                SystemSounds.Asterisk.Play();
            }

            cts.Dispose();
            cts = null;
            EnableControls(true);

            if (closing)
                Close();
        }

        private async void btnRestore_Click(object sender, EventArgs e)
        {
            DialogResult choice = MessageBox.Show("Restoring the game will delete any modified files you have installed.\n" +
                "Do you want to proceed?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
            if (choice == DialogResult.No)
                return;

            EnableControls(false);
            cts = new CancellationTokenSource();
            string error = await Task.Run(() => GameRestorer.Restore(txtExePath.Text, progress, cts.Token));

            if (cts.Token.IsCancellationRequested)
            {
                progress.Report((0, "Restoration aborted."));
            }
            else if (error != null)
            {
                progress.Report((0, "Restoration failed."));
                ShowError(error);
            }
            else
            {
                SystemSounds.Asterisk.Play();
            }

            cts.Dispose();
            cts = null;
            EnableControls(true);

            if (closing)
                Close();
        }

        private async void btnUnpack_Click(object sender, EventArgs e)
        {
            EnableControls(false);
            cts = new CancellationTokenSource();
            string error = await Task.Run(() => ArchiveUnpacker.Unpack(txtExePath.Text, progress, cts.Token));

            if (cts.Token.IsCancellationRequested)
            {
                progress.Report((0, "Unpacking aborted."));
            }
            else if (error != null)
            {
                progress.Report((0, "Unpacking failed."));
                ShowError(error);
            }
            else
            {
                SystemSounds.Asterisk.Play();
            }

            cts.Dispose();
            cts = null;
            EnableControls(true);

            if (closing)
                Close();
        }

        private void ShowError(string message)
        {
            MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        private void EnableControls(bool enable)
        {
            txtExePath.Enabled = enable;
            btnBrowse.Enabled = enable;
            btnAbort.Enabled = !enable;
            btnRestore.Enabled = enable;
            btnPatch.Enabled = enable;
            btnUnpack.Enabled = enable;
        }

        private void ReportProgress((double value, string status) report)
        {
            if (report.value < 0 || report.value > 1)
                throw new ArgumentOutOfRangeException("Progress value must be between 0 and 1, inclusive.");

            int percent = (int)Math.Floor(report.value * pbrProgress.Maximum);
            pbrProgress.Value = percent;
            txtStatus.Text = report.status;
            if (TaskbarManager.IsPlatformSupported)
            {
                TaskbarManager.Instance.SetProgressValue(percent, pbrProgress.Maximum);
                if (percent == pbrProgress.Maximum && ActiveForm == this)
                    TaskbarManager.Instance.SetProgressState(TaskbarProgressBarState.NoProgress);
            }
        }

        private void FormMain_Activated(object sender, EventArgs e)
        {
            if (TaskbarManager.IsPlatformSupported && pbrProgress.Value == pbrProgress.Maximum)
            {
                TaskbarManager.Instance.SetProgressState(TaskbarProgressBarState.NoProgress);
            }
        }
    }
}


================================================
FILE: UXM/FormMain.resx
================================================
<?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>
  <metadata name="lblBreak.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <value>False</value>
  </metadata>
  <metadata name="lblExePath.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <value>False</value>
  </metadata>
  <metadata name="lblStatus.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <value>False</value>
  </metadata>
  <metadata name="ofdExe.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
    <value>17, 17</value>
  </metadata>
  <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
    <value>105, 17</value>
  </metadata>
  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
    <value>
        AAABAAUAEBAAAAEAIABoBAAAVgAAABgYAAABACAAiAkAAL4EAAAgIAAAAQAgAKgQAABGDgAAMDAAAAEA
        IACoJQAA7h4AAAAAAAABACAAI4EAAJZEAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAADDDgAAww4AAAAA
        AAAAAAAAAAAAAAAAAAAHCw0AAgICEQ8WHVcVHia0BggKNwAAAAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAcKzUAGicxAx4tOF4gMD2uHSo22xojLEsAAAAcAAAAFAAAAAIAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAGCYwAH2drQAlNUBcLD5LpSU1Q9gmNECRAAAAAwAAACIAAAAzAAAAHgAA
        ABMAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAvQEsAMEFMIzBDTqMtP0uRJjVAsBckLSMAAAASAAAAMgAA
        ADgAAAAkAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAM0ZRADRIUwU6UVwa////ACw9SloiMT5YKz1MAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACU1QwAlNkMcIjI+ghQh
        KQoTHiYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiLzoAADQwAC0+
        SnAkMz45JjZBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADNF
        UwAyRFI1KDlFcwAAAAEUICcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAA5SVYAQFJgCC4/TIMeKzUjHCgyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAS1ZeACQxOwAsO0ZxJTE5cig3QwAlLzQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAACcmJgAzRE8ANERPJSMwOKYWICYhR0dKAB4mKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAJTI7ACc0PhcnN0DKIS41wCQzPGQnNT0MHyw0ACIoLQAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAIi0zACMwOQAlMjpXJTM73yQyOeQmNT7aJjI7dzE5PwUtNj4AAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAADFARgAkN0QALD1HcSk5Q+QrO0TvJzQ99Ck3QIEyOj0DKzY9AAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3SU8ADRcfADFDTFQnNj/FJDM7/SMxOvMlNT5NITA5AJnO
        1wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADVESwA/T1UFKTlCNyg3QqErOUOsKDU9Eio4
        PwAAAAAAAAAAAOD/AADAPwAA4AcAAOAHAADk/wAA/H8AAP5/AAD+PwAA/j8AAP8/AAD/HwAA/wcAAP8D
        AAD/AwAA/wcAAP8HAAAoAAAAGAAAADAAAAABACAAAAAAAAAJAADDDgAAww4AAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAIAAAAaAAAAIhQaIYoTGR+rAAAAMgAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHyw0ACEwOQMXIikiFiMraxcj
        LtMbJjDdCg4QRQAAADIAAAAWAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAHCs2ABwqNSYeLTmmIzZDuCAxPckeLDjyISw2XgAAAAgAAAApAAAAJQAA
        AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCcxABUj
        Lg8jMz6WL0FOnSg7SIUjMkDsKDZCtRcfIwkAAAABAAAAGwAAADYAAAAdAAAACQAAAAUAAAACAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIC03ADhLVgAuP0tBL0FNuik7R8wpOUbzJzZD7RYh
        KUMVHSQAAAAAEAAAAEMAAABWAAAATQAAAEcAAAAvAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAADBASgAvP0khMURQuDJFUIIyRE9dLTxIrBsoM5Ryj6cAAAAACwAAABoAAAAlAAAALAAA
        ACwAAAATAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC9BTQAvQU0EO1NfKEde
        ag0tP04ANkdVNig5RrcRHSUYEh4mAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaKDIAHCs2BiY3RZ8cKjVWITA8AAgR
        FgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAACA4ALD5MACY1Q1UhMTygAAYIBg4YHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALTpHADE/
        TBUsPEmyGykyNBooMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANTxDAC1HWQA1R1R5JTZBgnaVsAAPHSMAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAADRHVQA1R1UsKjpGtBckLBkYJS0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhHUQBGU1wENUZUmSU0
        QFstP0wABhAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAADg1NwAwQ1MAM0VTXSIwO7wTHCETGSMpAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsa
        GgAvPkoAMUBMMyo4QtwiLjRNHysxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIXGgAh63GAi8+SJIfKjGhDxYaCBYe
        IgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAKDdDACs7R1QfLTbvGCMqcCErMikyQkkFHiszAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeJCUAfeL/ACg3
        QGQsPUf2IjA37yEuN78oOUJ4IisxCxMdJwA4Q0UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmMzoAJTE4IiIuNsAmNDzvIi409SIvNssmNT7eIy83kSw2
        PRgrNDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAArO0UAKzpDNyc3QNQlMzrOKjtD0ik4P+opOELrKDU+syw3PTwuOUEAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuP0gAMEBJSiw9SNUqOkXyLT5H+So4
        Qf8lMDnyKTlCni47QRMvPEMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAA0SVMANktUTik5QrQnNT/jJDI5/SMxOf8eLDX8JDQ9gAYSGABdcXsAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHXmgAS2NtCTA/
        R08mNj+aIS847yg3Q/8nNkDcKTpDNCc3PwBLXWYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADVJUgA2SVMXJzdCYDJAS6IqNj+MGBYXAy42
        OwAAAAAAAAAAAAAAAAAAAAAA8B//APAH/wDwA/8A8AA/APgQHwD4EB8A+I//AP+P/wD/x/8A/8f/AP/n
        /wD/4/8A/+P/AP/x/wD/8f8A//D/AP/4PwD/+B8A//APAP/wDwD/8A8A//AfAP/wHwD//B8AKAAAACAA
        AABAAAAAAQAgAAAAAAAAEAAAww4AAMMOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAgAAAAbAAAAGQcJDDcXHSTJDRIWiQAAACsAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAABQAAAB8DBQY+DhYdchkjL+wYISnGAgMDUAAAAD0AAAAYAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAGSUuACc5RAAlNkEYJDVATCAwPIAcLDfgFyMu9SAsN+wWHiI8AAAAHAAAAD0AAAAmAAAABgAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAVHicAGyo1ABspNHcdLDfJIjVCpyc6SNIdLDm/IC07/yEsNoVcdpMAAAAACQAA
        ACwAAAA2AAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsQGQAbKjUAGCcxNCIyPcMtQEyyMUVTeiEyP4oiMT//KDZC0xcg
        JhoXICYAAAAAAQAAABkAAAA/AAAALQAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIxPAAfLjoKMEJNZjNFUIwrPUm6JDVCuyc3
        Rf0sPEr7ICw1YSo3QgABAwQAAAAAAgAAACEAAABQAAAASwAAADYAAAAsAAAAJwAAABcAAAAJAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADBAWAC0+SAAqO0VALT9L2S9C
        TrspOkXfKjtG5yk4RPEYIyzCCRQaEQgOEgAAAAAPAAAAQAAAAEsAAABYAAAAWgAAAFoAAABUAAAAMwAA
        AA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANUNMADRC
        SxwxRFDENUlUoDZIU1U7T1srOktWeyIxPO4QGyQ6ERwkAAAAAAMAAAALAAAADwAAABkAAAAdAAAAIgAA
        ABcAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAqPEgAJTRCAjtTXzJJY28ex8rNADRBTAA+S1YWMEJRyR0rNnw7UWEACxQcAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKzI3AD9acQArPUt3JDRBxQcQFBEOGR8AAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHi06AB8vPCkkNELYFiMsTRgm
        LwAKERgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASGyUAAAAAAyg4
        Rp8fLjmkAAAABA4YHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgR
        HAAzQlAAMD9NSSk5RdkSHiUsEx8mAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAADRASgA6RlEPNkhVwSAvOHw6TV0AEyIpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAQEZLADdQYwA2SVdvKDlEyQ0ZHxUTISgAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMkRRADVHVSMtPkvVHCozVB4sNgAeLTUAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/T1gARUM3ATlKWJcoOESpAAICBRgk
        LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        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
        JX8WISzpHCYy/xghKL0BAQFMAAAAVAAAAE0AAAAqAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEZfXgAhNUQAKj5KCSc4
        RB8gMDtJIDI+zRsrNvQUICv+Gycz/yIuOOYTGh0yAAAADgAAADAAAABSAAAANQAAAAsAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADRMYACQ1
        QAAiMj0uIjI9ryEyPtEhMj93HzA86iAvOsUZJzLMGSYy/yQxPf8XICZ7Iy82AAAAAAEAAAAWAAAAQgAA
        AEgAAAAeAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAACxAWABopNAAZJzJPGSYx8hsrNqAiM0GEJztJ4iw/TtIhM0GOGig1/CMxQP8jLzrLDRIXFhIZ
        HwAAAAAAAAAABgAAACkAAABLAAAANgAAAAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAABUiLAAUIiwVGik0lSAvO9kpO0fxL0RRlDFFVKglN0VRGyk25iIx
        QP8rOUb4GSMqVhwnLwAWHyQAAAAAAAAAAAAAAAARAAAAQwAAAEwAAAAlAAAABwAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4zPgAtPEcAITE7YC4/Sso6TVeCPFBdPSo9
        SGEhMj9kIjRC7iU0Q/8tPUz/IS02qg4WHAcdKDIAAAAAAAAAAAAAAAAAAAAADQAAADIAAABWAAAAQQAA
        ABoAAAAKAAAABwAAAAQAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkKDgA1SVkALT9NFjZI
        VFcwQUyIMEFN0So7R/oiMT21KTpI5iU0Qf8zRVX/KDVB6hokKzkdKDAAAAEGAAAAAAAAAAAAAAAABgAA
        ACIAAABIAAAAXAAAAFgAAABNAAAAQwAAADoAAAA+AAAAKAAAABwAAAARAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAdKzQAER4kAig5RGosPkrdL0FN8zFGUr0mN0LnKjtH/yY1QP4qOkf9Hyw2/xEcI50CDREFCBEVAAAA
        AAAAAAADAAAAMwAAAFMAAABRAAAAVwAAAFsAAABbAAAAWwAAAFoAAABcAAAAUgAAADsAAAAeAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAANEJLADNASDguQEvgL0NPqys+SnwrPEasMUNPzjRFUH4yQUylJjRA/xMe
        J+QOGSAsDxsjAAAAAAAAAAAEAAAAIwAAACoAAAAwAAAAOwAAAEsAAABKAAAATwAAAFMAAABJAAAAKwAA
        AA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPEhQAD1JUBEvQk3BM0lV8TtOWqFFV2IsVm9/FTU7
        PwBZaXMwOUpX3x4tOPsPGiNSER0nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAcAAAAHAAAACgAA
        AA4AAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJjQ/AP///wA5UF09RmFtSWKA
        jAxBYG4Azfj5AKqwtgAAAAAAMkBNbTJFVf8WIiqXAAAAAg4WHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkMDoAJC85IDRHWNohMT3eCRMaIg4ZIQAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQGyEAAAAAASY3RI4qPEv+Eh0lYhck
        LgAKExgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGyo1ABkn
        MzwqPEvxGCYvtwQNDwsMFxwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAADhkiAAYPFgolNEK1IjI+8xAbIkASHyYABgwSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAACg8WAC9CUQAlNEFgKz1L/hUiK5IAAAABDRYdAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcyPQAmMTwcMEFP1h8tONwLFhwiDxohAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlDSwC4//8AOEhVhzJE
        Uf8THyVqFiEpABIgJQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAA1Q00AOUdSNzpNW+4eLTW/DxsgDhYkKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAA8R08ANz9ECDhLWa0qPEj3EiAnSBUjKwALHCEAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABKVGAAMENSADVHVFYvQU/8GSYvmgILDgMTHyYAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMENPAC9BTRcyRFPOJDM/4hIf
        JScVIikAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUmRxABEq
        RwA8TVp/MkNS/xknL3AYJjEAHS00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAADlGUwA8SVUvPE9f6iEwO8EOGB0PFiMqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAGVueABhZmsHQFRlqSo6SPgQGh9hKDMzAholKQAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMADRDTgALOYkAKDlGhiQzP/8YIindGyYsIxsm
        LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMAD5KVQBGUFgELj1Jhys5
        RfsiLzj3HiwyVBQdIgA6V2UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH6T
        pABNWmMATVtlGjdGUc8pNj7/Iy80qj5RVwY1RkwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAACAlJoAAAAAAD5SYG8xQEr9ICku4CEoLCUhKS4AAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARFtrAEdgcRQrOUPFHCcv/xkjKoIZICAIHiYjABMb
        IgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM0FSAFhphgErOkecJDE8/xch
        J/YRGR94H1eNABAbIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARldeAFhp
        bgQqOkWXKTxH/xknLv8UICawIi44WiEqMGwXHyATDhIMAQAOFgDPp28AAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAT2BnAHqHjAIzRVBRLUBL6yEvNv8hLTL7Ii83+SEtNvocJy66MUNNjj1TWhg6T1YAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAaHh8AHy08ACEqMUAhLjfBOExX+zZIU/8lNDv/IzI67iQzPJcdKjLNJzpD9yo7
        Q1wSExsH////AENESgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiJiUAHxwLAh0mLJ4jLzn/JzdA+C07RP8kMDf/GiQp+SIw
        OKshMTiTKTpC7CQxOuUdJy+5Kzc8RCstMAEvOD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        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
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPlRgAElfaS8nOUSdIjE+njZC
        TtUzQk3yKjZA+CApMVwTHSgAJiotAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8fT3AP//
        /wBEYHgDQE5fBEdTXic7S1ZSMT5GtBYbITAYHiQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAD/gA////8AAP+AB////wAA/8AB////AAD/wAD///8AAP+AED///wAA/4AMH///
        AAD/gA8H//8AAP/AB4A//wAA/8AHgAf/AAD/wAMAB/8AAP/gAwAP/wAA/+BD8D//AAD/8eH///8AAP//
        4f///wAA///h////AAD///D///8AAP//8P///wAA///4f///AAD///h///8AAP///H///wAA///8P///
        AAD///w///8AAP///h///wAA///+H///AAD///8f//8AAP///w///wAA////B///AAD///+H//8AAP//
        /wf//wAA////g///AAD////D//8AAP///8H//wAA////wf//AAD////AH/8AAP///8AP/wAA////wAf/
        AAD///+AAf8AAP///4AB/wAA////gAH/AAD///+AAf8AAP///4AB/wAA////AAP/AAD///8AA/8AAP//
        /wAD/wAA////gAP/AAD////AB/8AAP////gP/wAA/////A//AACJUE5HDQoaCgAAAA1JSERSAAABAAAA
        AQAIBgAAAFxyqGYAAIAASURBVHja7N13mCTHeR/+b1Xn7slp897u5YhDBhEJkARzEAlSJiVSNCVTtiXZ
        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
</value>
  </data>
</root>

================================================
FILE: UXM/GameInfo.cs
================================================
using SoulsFormats;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;

namespace UXM
{
    class GameInfo
    {
        public long RequiredGB;
        public BHD5.Game BHD5Game;
        public List<string> Archives;
        public ArchiveDictionary Dictionary;
        public List<string> BackupDirs;
        public List<string> DeleteDirs;
        public List<string> Replacements;

        public GameInfo(string xmlStr, string dictionaryStr)
        {
            XDocument xml = XDocument.Parse(xmlStr);
            RequiredGB = long.Parse(xml.Root.Element("required_gb").Value);
            BHD5Game = (BHD5.Game)Enum.Parse(typeof(BHD5.Game), xml.Root.Element("bhd5_game").Value);
            Archives = xml.Root.Element("archives").Elements().Select(element => element.Value).ToList();
            BackupDirs = xml.Root.Element("backup_dirs").Elements().Select(element => element.Value).ToList();
            DeleteDirs = xml.Root.Element("delete_dirs").Elements().Select(element => element.Value).ToList();
            Replacements = xml.Root.Element("replacements").Elements().Select(element => element.Value).ToList();

            Dictionary = new ArchiveDictionary(dictionaryStr, BHD5Game);
        }

        public static GameInfo GetGameInfo(Util.Game game)
        {
            string prefix = game switch
            {
                Util.Game.DarkSouls2 => "DarkSouls2",
                Util.Game.Scholar => "Scholar",
                Util.Game.DarkSouls3 => "DarkSouls3",
                Util.Game.Sekiro => "Sekiro",
                Util.Game.SekiroBonus => "SekiroBonus",
                Util.Game.EldenRing => "EldenRing",
                Util.Game.ArmoredCore6 => "ArmoredCore6",
                _ => throw new ArgumentException("Invalid game type."),
            };

#if DEBUG
            string gameInfo = File.ReadAllText($@"..\..\..\dist\res\{prefix}GameInfo.xml");
            string dictionary = File.ReadAllText($@"..\..\..\dist\res\{prefix}Dictionary.txt");
#else
            string gameInfo = File.ReadAllText($@"res\{prefix}GameInfo.xml");
            string dictionary = File.ReadAllText($@"res\{prefix}Dictionary.txt");
#endif
            return new GameInfo(gameInfo, dictionary);
        }
    }
}


================================================
FILE: UXM/GameRestorer.cs
================================================
using System;
using System.IO;
using System.Threading;

namespace UXM
{
    static class GameRestorer
    {
        public static string Restore(string exePath, IProgress<(double value, string status)> progress, CancellationToken ct)
        {
            progress.Report((0, "Restoring executable..."));
            string gameDir = Path.GetDirectoryName(exePath);
            string exeName = Path.GetFileName(exePath);

            Util.Game game;
            GameInfo gameInfo;
            try
            {
                game = Util.GetExeVersion(exePath);
                gameInfo = GameInfo.GetGameInfo(game);
            }
            catch (Exception ex)
            {
                return ex.Message;
            }

            if (File.Exists(gameDir + "\\_backup\\" + exeName))
            {
                try
                {
                    File.Delete(exePath);
                    File.Move(gameDir + "\\_backup\\" + exeName, exePath);
                }
                catch (Exception ex)
                {
                    return $"Failed to restore executable.\r\n\r\n{ex}";
                }
            }

            if (ct.IsCancellationRequested)
                return null;

            double totalSteps = gameInfo.BackupDirs.Count + gameInfo.DeleteDirs.Count + 1;

            for (int i = 0; i < gameInfo.BackupDirs.Count; i++)
            {
                string restore = gameInfo.BackupDirs[i];
                progress.Report(((i + 1.0) / totalSteps, $"Restoring directory \"{restore}\" ({i + 1}/{gameInfo.BackupDirs.Count})..."));

                string restoreSource = gameDir + "\\_backup\\" + restore;
                string restoreTarget = gameDir + "\\" + restore;

                if (Directory.Exists(restoreSource))
                {
                    try
                    {
                        if (Directory.Exists(restoreTarget))
                            Directory.Delete(restoreTarget, true);
                        Directory.Move(restoreSource, restoreTarget);
                    }
                    catch (Exception ex)
                    {
                        return $"Failed to restore sounds.\r\n\r\n{ex}";
                    }
                }
            }

            try
            {
                for (int i = 0; i < gameInfo.DeleteDirs.Count; i++)
                {
                    string dir = gameInfo.DeleteDirs[i];

                    progress.Report(((i + 1.0 + gameInfo.BackupDirs.Count) / totalSteps, $"Deleting directory \"{dir}\" ({i + 1}/{gameInfo.DeleteDirs.Count})..."));

                    if (ct.IsCancellationRequested)
                        return null;

                    if (Directory.Exists(gameDir + "\\" + dir))
                        Directory.Delete(gameDir + "\\" + dir, true);
                }
            }
            catch (Exception ex)
            {
                return $"Failed to delete directory.\r\n\r\n{ex}";
            }

            try
            {
                if (Directory.Exists(gameDir + "\\_backup") && Directory.GetFiles(gameDir + "\\_backup").Length == 0)
                    Directory.Delete(gameDir + "\\_backup");
            }
            catch (Exception ex)
            {
                return $"Failed to delete backup directory.\r\n\r\n{ex}";
            }

            progress.Report((1, "Restoration complete!"));
            return null;
        }
    }
}


================================================
FILE: UXM/Program.cs
================================================
using System;
using System.Windows.Forms;

namespace UXM
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Properties.Settings settings = Properties.Settings.Default;
            if (settings.UpgradeRequired)
            {
                settings.Upgrade();
                settings.UpgradeRequired = false;
                settings.Save();
            }

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new FormMain());

            settings.Save();
        }
    }
}


================================================
FILE: UXM/Properties/Resources.Designer.cs
================================================
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace UXM.Properties {
    using System;
    
    
    /// <summary>
    ///   A strongly-typed resource class, for looking up localized strings, etc.
    /// </summary>
    // This class was auto-generated by the StronglyTypedResourceBuilder
    // class via a tool like ResGen or Visual Studio.
    // To add or remove a member, edit your .ResX file then rerun ResGen
    // with the /str option, or rebuild your VS project.
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    internal class Resources {
        
        private static global::System.Resources.ResourceManager resourceMan;
        
        private static global::System.Globalization.CultureInfo resourceCulture;
        
        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        internal Resources() {
        }
        
        /// <summary>
        ///   Returns the cached ResourceManager instance used by this class.
        /// </summary>
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
        internal static global::System.Resources.ResourceManager ResourceManager {
            get {
                if (object.ReferenceEquals(resourceMan, null)) {
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("UXM.Properties.Resources", typeof(Resources).Assembly);
                    resourceMan = temp;
                }
                return resourceMan;
            }
        }
        
        /// <summary>
        ///   Overrides the current thread's CurrentUICulture property for all
        ///   resource lookups using this strongly typed resource class.
        /// </summary>
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
        internal static global::System.Globalization.CultureInfo Culture {
            get {
                return resourceCulture;
            }
            set {
                resourceCulture = value;
            }
        }
    }
}


================================================
FILE: UXM/Properties/Resources.resx
================================================
<?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>
</root>

================================================
FILE: UXM/Properties/Settings.Designer.cs
================================================
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace UXM.Properties {
    
    
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.10.0.0")]
    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
        
        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
        
        public static Settings Default {
            get {
                return defaultInstance;
            }
        }
        
        [global::System.Configuration.UserScopedSettingAttribute()]
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [global::System.Configuration.DefaultSettingValueAttribute("True")]
        public bool UpgradeRequired {
            get {
                return ((bool)(this["UpgradeRequired"]));
            }
            set {
                this["UpgradeRequired"] = value;
            }
        }
      
Download .txt
gitextract_539c5h6b/

├── .gitattributes
├── .gitignore
├── .gitmodules
├── LICENSE
├── README.md
├── UXM/
│   ├── App.config
│   ├── ArchiveDictionary.cs
│   ├── ArchiveKeys.cs
│   ├── ArchiveUnpacker.cs
│   ├── CryptographyUtility.cs
│   ├── ExePatcher.cs
│   ├── FormMain.Designer.cs
│   ├── FormMain.cs
│   ├── FormMain.resx
│   ├── GameInfo.cs
│   ├── GameRestorer.cs
│   ├── Program.cs
│   ├── Properties/
│   │   ├── Resources.Designer.cs
│   │   ├── Resources.resx
│   │   ├── Settings.Designer.cs
│   │   └── Settings.settings
│   ├── UXM.csproj
│   ├── Util.cs
│   └── dist/
│       ├── readme.txt
│       └── res/
│           ├── ArmoredCore6Dictionary.txt
│           ├── ArmoredCore6GameInfo.xml
│           ├── DarkSouls2Dictionary.txt
│           ├── DarkSouls2GameInfo.xml
│           ├── DarkSouls3Dictionary.txt
│           ├── DarkSouls3GameInfo.xml
│           ├── EldenRingDictionary.txt
│           ├── EldenRingGameInfo.xml
│           ├── ScholarDictionary.txt
│           ├── ScholarGameInfo.xml
│           ├── SekiroBonusDictionary.txt
│           ├── SekiroBonusGameInfo.xml
│           ├── SekiroDictionary.txt
│           └── SekiroGameInfo.xml
└── UXM.sln
Download .txt
SYMBOL INDEX (46 symbols across 13 files)

FILE: UXM/ArchiveDictionary.cs
  class ArchiveDictionary (line 8) | internal class ArchiveDictionary : Dictionary<ulong, string>
    method ArchiveDictionary (line 13) | public ArchiveDictionary(string dictionary, BHD5.Game game)
    method Normalize (line 26) | public static string Normalize(string path)
    method FromHash (line 39) | public static ulong FromHash(string path, BHD5.Game game)

FILE: UXM/ArchiveKeys.cs
  class ArchiveKeys (line 5) | static class ArchiveKeys

FILE: UXM/ArchiveUnpacker.cs
  class ArchiveUnpacker (line 13) | static class ArchiveUnpacker
    method Unpack (line 17) | public static string Unpack(string exePath, IProgress<(double value, s...
    method UnpackArchive (line 129) | private static async Task<string> UnpackArchive(string gameDir, string...
    method WriteFileAsync (line 292) | private static async Task<long> WriteFileAsync(string path, byte[] bytes)

FILE: UXM/CryptographyUtility.cs
  class CryptographyUtility (line 12) | internal static class CryptographyUtility
    method DecryptRsa (line 22) | public static MemoryStream DecryptRsa(string filePath, string key)
    method GetKeyOrDefault (line 65) | public static AsymmetricKeyParameter GetKeyOrDefault(string key)

FILE: UXM/ExePatcher.cs
  class ExePatcher (line 10) | class ExePatcher
    method Patch (line 14) | public static string Patch(string exePath, IProgress<(double value, st...
    method replace (line 100) | private static void replace(byte[] bytes, string target, string replac...
    method findBytes (line 112) | private static List<int> findBytes(byte[] bytes, byte[] find)

FILE: UXM/FormMain.Designer.cs
  class FormMain (line 3) | partial class FormMain
    method Dispose (line 14) | protected override void Dispose(bool disposing)
    method InitializeComponent (line 29) | private void InitializeComponent()

FILE: UXM/FormMain.cs
  class FormMain (line 12) | public partial class FormMain : Form
    method FormMain (line 20) | public FormMain()
    method FormMain_Load (line 29) | private void FormMain_Load(object sender, EventArgs e)
    method FormMain_FormClosing (line 43) | private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
    method btnAbort_Click (line 71) | private void btnAbort_Click(object sender, EventArgs e)
    method btnBrowse_Click (line 78) | private void btnBrowse_Click(object sender, EventArgs e)
    method btnExplore_Click (line 85) | private void btnExplore_Click(object sender, EventArgs e)
    method btnPatch_Click (line 94) | private async void btnPatch_Click(object sender, EventArgs e)
    method btnRestore_Click (line 122) | private async void btnRestore_Click(object sender, EventArgs e)
    method btnUnpack_Click (line 155) | private async void btnUnpack_Click(object sender, EventArgs e)
    method ShowError (line 183) | private void ShowError(string message)
    method EnableControls (line 188) | private void EnableControls(bool enable)
    method ReportProgress (line 198) | private void ReportProgress((double value, string status) report)
    method FormMain_Activated (line 214) | private void FormMain_Activated(object sender, EventArgs e)

FILE: UXM/GameInfo.cs
  class GameInfo (line 10) | class GameInfo
    method GameInfo (line 20) | public GameInfo(string xmlStr, string dictionaryStr)
    method GetGameInfo (line 33) | public static GameInfo GetGameInfo(Util.Game game)

FILE: UXM/GameRestorer.cs
  class GameRestorer (line 7) | static class GameRestorer
    method Restore (line 9) | public static string Restore(string exePath, IProgress<(double value, ...

FILE: UXM/Program.cs
  class Program (line 6) | static class Program
    method Main (line 11) | [STAThread]

FILE: UXM/Properties/Resources.Designer.cs
  class Resources (line 22) | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resource...
    method Resources (line 31) | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Mic...

FILE: UXM/Properties/Settings.Designer.cs
  class Settings (line 14) | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]

FILE: UXM/Util.cs
  class Util (line 6) | static class Util
    method GetExeVersion (line 8) | public static Game GetExeVersion(string exePath)
    type Game (line 48) | public enum Game
Condensed preview — 39 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (9,827K chars).
[
  {
    "path": ".gitattributes",
    "chars": 2518,
    "preview": "###############################################################################\n# Set default behavior to automatically "
  },
  {
    "path": ".gitignore",
    "chars": 4305,
    "preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User"
  },
  {
    "path": ".gitmodules",
    "chars": 109,
    "preview": "[submodule \"SoulsFormatsNEXT\"]\n\tpath = SoulsFormatsNEXT\n\turl = https://github.com/soulsmods/SoulsFormatsNEXT\n"
  },
  {
    "path": "LICENSE",
    "chars": 35129,
    "preview": "GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation,"
  },
  {
    "path": "README.md",
    "chars": 2880,
    "preview": "# UXM\nEnables file modding for DS2, SotFS, DS3, and Sekiro by unpacking game archives and patching the executable to loa"
  },
  {
    "path": "UXM/App.config",
    "chars": 1447,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<configuration>\n    <configSections>\n        <sectionGroup name=\"userSettings\" "
  },
  {
    "path": "UXM/ArchiveDictionary.cs",
    "chars": 1343,
    "preview": "using SoulsFormats;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text.RegularExpressions;\n\nnamespa"
  },
  {
    "path": "UXM/ArchiveKeys.cs",
    "chars": 12161,
    "preview": "using System.Collections.Generic;\n\nnamespace UXM\n{\n    static class ArchiveKeys\n    {\n        public static Dictionary<"
  },
  {
    "path": "UXM/ArchiveUnpacker.cs",
    "chars": 13669,
    "preview": "using SoulsFormats;\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Te"
  },
  {
    "path": "UXM/CryptographyUtility.cs",
    "chars": 2819,
    "preview": "using Org.BouncyCastle.Crypto;\nusing Org.BouncyCastle.Crypto.Engines;\nusing Org.BouncyCastle.OpenSsl;\nusing System;\nusi"
  },
  {
    "path": "UXM/ExePatcher.cs",
    "chars": 4500,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Text;\nusing System.Threading;\nusing Syste"
  },
  {
    "path": "UXM/FormMain.Designer.cs",
    "chars": 11017,
    "preview": "namespace UXM\n{\n    partial class FormMain\n    {\n        /// <summary>\n        /// Required designer variable.\n        "
  },
  {
    "path": "UXM/FormMain.cs",
    "chars": 7235,
    "preview": "using Microsoft.WindowsAPICodePack.Taskbar;\nusing System;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Media"
  },
  {
    "path": "UXM/FormMain.resx",
    "chars": 81945,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!--\n    Microsoft ResX Schema \n\n    Version 2.0\n\n    The primary goals"
  },
  {
    "path": "UXM/GameInfo.cs",
    "chars": 2295,
    "preview": "using SoulsFormats;\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Xm"
  },
  {
    "path": "UXM/GameRestorer.cs",
    "chars": 3437,
    "preview": "using System;\nusing System.IO;\nusing System.Threading;\n\nnamespace UXM\n{\n    static class GameRestorer\n    {\n        pub"
  },
  {
    "path": "UXM/Program.cs",
    "chars": 714,
    "preview": "using System;\nusing System.Windows.Forms;\n\nnamespace UXM\n{\n    static class Program\n    {\n        /// <summary>\n       "
  },
  {
    "path": "UXM/Properties/Resources.Designer.cs",
    "chars": 2770,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code w"
  },
  {
    "path": "UXM/Properties/Resources.resx",
    "chars": 5696,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "UXM/Properties/Settings.Designer.cs",
    "chars": 3389,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code w"
  },
  {
    "path": "UXM/Properties/Settings.settings",
    "chars": 1006,
    "preview": "<?xml version='1.0' encoding='utf-8'?>\n<SettingsFile xmlns=\"http://schemas.microsoft.com/VisualStudio/2004/01/settings\""
  },
  {
    "path": "UXM/UXM.csproj",
    "chars": 2858,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <TargetFramework>net8.0-windows</TargetFramework>\n    <OutputTy"
  },
  {
    "path": "UXM/Util.cs",
    "chars": 2030,
    "preview": "using System;\nusing System.IO;\n\nnamespace UXM\n{\n    static class Util\n    {\n        public static Game GetExeVersion(st"
  },
  {
    "path": "UXM/dist/readme.txt",
    "chars": 2875,
    "preview": "\n--| UXM 2.4\n--| By TKGP\n--| https://www.nexusmods.com/sekiro/mods/26\n--| https://github.com/JKAnderson/UXM\n\nEnables fil"
  },
  {
    "path": "UXM/dist/res/ArmoredCore6Dictionary.txt",
    "chars": 1417475,
    "preview": "/1000051991.wem\n/1000794339.wem\n/1001204308.wem\n/1003829556.wem\n/1003903068.wem\n/1004672443.wem\n/1006888205.wem\n/1009235"
  },
  {
    "path": "UXM/dist/res/ArmoredCore6GameInfo.xml",
    "chars": 1073,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<game_info>\n  <required_gb>50</required_gb>\n  <bhd5_game>EldenRing</bhd5_game>\n  "
  },
  {
    "path": "UXM/dist/res/DarkSouls2Dictionary.txt",
    "chars": 602879,
    "preview": "/breakobj/m10_02_00_00.breakobj\n/breakobj/m10_04_00_00.breakobj\n/breakobj/m10_10_00_00.breakobj\n/breakobj/m10_14_00_00.b"
  },
  {
    "path": "UXM/dist/res/DarkSouls2GameInfo.xml",
    "chars": 1139,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<game_info>\n  <required_gb>16</required_gb>\n  <bhd5_game>DarkSouls2</bhd5_game>\n "
  },
  {
    "path": "UXM/dist/res/DarkSouls3Dictionary.txt",
    "chars": 614454,
    "preview": "/action/eventnameid.txt\n/action/script/c0000.hks\n/action/script/c0001.hks\n/action/script/c0002.hks\n/action/script/c0004."
  },
  {
    "path": "UXM/dist/res/DarkSouls3GameInfo.xml",
    "chars": 1304,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<game_info>\n  <required_gb>25</required_gb>\n  <bhd5_game>DarkSouls3</bhd5_game>\n "
  },
  {
    "path": "UXM/dist/res/EldenRingDictionary.txt",
    "chars": 5841885,
    "preview": "/action/eventnameid.txt\n/action/script/c0000.hks\n/action/script/c0000_talk.hks\n/action/script/c0100.hks\n/action/script/c"
  },
  {
    "path": "UXM/dist/res/EldenRingGameInfo.xml",
    "chars": 1334,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<game_info>\n  <required_gb>64</required_gb>\n  <bhd5_game>EldenRing</bhd5_game>\n  "
  },
  {
    "path": "UXM/dist/res/ScholarDictionary.txt",
    "chars": 539704,
    "preview": "/breakobj/m10_02_00_00.breakobj\n/breakobj/m10_04_00_00.breakobj\n/breakobj/m10_10_00_00.breakobj\n/breakobj/m10_14_00_00.b"
  },
  {
    "path": "UXM/dist/res/ScholarGameInfo.xml",
    "chars": 1139,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<game_info>\n  <required_gb>18</required_gb>\n  <bhd5_game>DarkSouls2</bhd5_game>\n "
  },
  {
    "path": "UXM/dist/res/SekiroBonusDictionary.txt",
    "chars": 8211,
    "preview": "/asset/menu/artwork/layout_p00.dds\n/asset/menu/artwork/layout_p01.dds\n/asset/menu/artwork/layout_p02_en.dds\n/asset/menu/"
  },
  {
    "path": "UXM/dist/res/SekiroBonusGameInfo.xml",
    "chars": 564,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<game_info>\n  <required_gb>1</required_gb>\n  <bhd5_game>Sekiro</bhd5_game>\n  <arc"
  },
  {
    "path": "UXM/dist/res/SekiroDictionary.txt",
    "chars": 348633,
    "preview": "/action/eventnameid.txt\n/action/script/c0000.hks\n/action/script/c0000_cmsg.hks\n/action/script/c0000_define.hks\n/action/s"
  },
  {
    "path": "UXM/dist/res/SekiroGameInfo.xml",
    "chars": 1106,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<game_info>\n  <required_gb>12</required_gb>\n  <bhd5_game>DarkSouls3</bhd5_game>\n "
  },
  {
    "path": "UXM.sln",
    "chars": 2266,
    "preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.10.351"
  }
]

About this extraction

This page contains the full source code of the JKAnderson/UXM GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 39 files (9.1 MB), approximately 2.4M tokens, and a symbol index with 46 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!