diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..80e2cdb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,225 @@
+# The following command works for downloading when using Git for Windows:
+# curl -LOf http://gist.githubusercontent.com/kmorcinek/2710267/raw/.gitignore
+#
+# Download this file using PowerShell v3 under Windows with the following comand:
+# Invoke-WebRequest https://gist.githubusercontent.com/kmorcinek/2710267/raw/ -OutFile .gitignore
+#
+# or wget:
+# wget --no-check-certificate http://gist.githubusercontent.com/kmorcinek/2710267/raw/.gitignore
+
+# User-specific files
+*.suo
+*.user
+*.sln.docstates
+
+# Build results
+[Dd]ebug/
+[Rr]elease/
+x64/
+[Bb]in/
+[Oo]bj/
+# build folder is nowadays used for build scripts and should not be ignored
+#build/
+
+# 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
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+*_i.c
+*_p.c
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.log
+*.scc
+
+# OS generated files #
+.DS_Store*
+Icon?
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+*.ncrunch*
+.*crunch*.local.xml
+
+# 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
+*.Publish.xml
+
+# Windows Azure Build Output
+csx
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Others
+*.Cache
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.[Pp]ublish.xml
+*.pfx
+*.publishsettings
+modulesbin/
+tempbin/
+
+# EPiServer Site file (VPP)
+AppData/
+
+# 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
+
+# vim
+*.txt~
+*.swp
+*.swo
+
+# Temp files when opening LibreOffice on ubuntu
+.~lock.*
+
+# svn
+.svn
+
+# CVS - Source Control
+**/CVS/
+
+# Remainings from resolving conflicts in Source Control
+*.orig
+
+# SQL Server files
+**/App_Data/*.mdf
+**/App_Data/*.ldf
+**/App_Data/*.sdf
+
+
+#LightSwitch generated files
+GeneratedArtifacts/
+_Pvt_Extensions/
+ModelManifest.xml
+
+# =========================
+# Windows detritus
+# =========================
+
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Mac desktop service store files
+.DS_Store
+
+# SASS Compiler cache
+.sass-cache
+
+# Visual Studio 2014 CTP
+**/*.sln.ide
+
+# Visual Studio temp something
+.vs/
+
+# dotnet stuff
+project.lock.json
+
+# VS 2015+
+*.vc.vc.opendb
+*.vc.db
+
+# Rider
+.idea/
+
+# Visual Studio Code
+.vscode/
+
+# Output folder used by Webpack or other FE stuff
+**/node_modules/*
+**/wwwroot/*
+
+# SpecFlow specific
+*.feature.cs
+*.feature.xlsx.*
+*.Specs_*.html
+
+#####
+# End of core ignore list, below put you custom 'per project' settings (patterns or path)
+#####
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..803933f
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 Lê Hiếu
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/NieR-Text-Tool.sln b/NieR-Text-Tool.sln
new file mode 100644
index 0000000..f841750
--- /dev/null
+++ b/NieR-Text-Tool.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31402.337
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NieR-Text-Tool", "NieR-Text-Tool\NieR-Text-Tool.csproj", "{6EDB4357-2F91-48EE-8A54-0998F025C8C1}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6EDB4357-2F91-48EE-8A54-0998F025C8C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6EDB4357-2F91-48EE-8A54-0998F025C8C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6EDB4357-2F91-48EE-8A54-0998F025C8C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6EDB4357-2F91-48EE-8A54-0998F025C8C1}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {3E022B72-1C99-4507-83D6-CCB5420A9CA4}
+ EndGlobalSection
+EndGlobal
diff --git a/NieR-Text-Tool/App.config b/NieR-Text-Tool/App.config
new file mode 100644
index 0000000..56efbc7
--- /dev/null
+++ b/NieR-Text-Tool/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NieR-Text-Tool/CSV.cs b/NieR-Text-Tool/CSV.cs
new file mode 100644
index 0000000..550b7d8
--- /dev/null
+++ b/NieR-Text-Tool/CSV.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.IO;
+using Microsoft.VisualBasic.FileIO;
+
+namespace NieR_Text_Tool
+{
+ public static class CSV
+ {
+ public static string ToCSV(byte[] input)
+ {
+ string str = Encoding.UTF8.GetString(input);
+ string[] lines = str.Split(new string[] { "\r\n" }, StringSplitOptions.None);
+ List strings = new List();
+ for (int i = 0; i < lines.Length; i++)
+ {
+ string[] line = lines[i].Replace("\n", "").Split(new string[] { "\t" }, StringSplitOptions.None).Select(entry => $"\"{entry.Replace("\"", "\"\"")}\"").ToArray();
+ strings.Add(string.Join(",", line));
+ }
+ string result = string.Join("\r\n", strings.ToArray());
+ Dictionary gameCode = GameCode.GetGameCode();
+ foreach (KeyValuePair entry in gameCode)
+ {
+ result = result.Replace(Encoding.UTF8.GetString(entry.Value), entry.Key);
+ }
+ return result;
+ }
+
+ public static byte[] ToGameFormat(string input)
+ {
+ List strings = new List();
+ using (TextFieldParser parser = new TextFieldParser(input))
+ {
+ parser.TextFieldType = FieldType.Delimited;
+ parser.SetDelimiters(",");
+ parser.TrimWhiteSpace = false;
+ while (!parser.EndOfData)
+ {
+ string[] fields = parser.ReadFields();
+ strings.Add(string.Join("\t", fields));
+ }
+ }
+ string result = string.Join("\r\n", strings.ToArray());
+ result = result.Replace("", "\n");
+ Dictionary gameCode = GameCode.GetGameCode();
+ foreach (KeyValuePair entry in gameCode)
+ {
+ result = result.Replace(entry.Key, Encoding.UTF8.GetString(entry.Value));
+ }
+ return Encoding.UTF8.GetBytes(result);
+ }
+ }
+}
diff --git a/NieR-Text-Tool/GameCode.cs b/NieR-Text-Tool/GameCode.cs
new file mode 100644
index 0000000..073d233
--- /dev/null
+++ b/NieR-Text-Tool/GameCode.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace NieR_Text_Tool
+{
+ public class GameCode
+ {
+ private static Dictionary _Instance;
+ private static Dictionary Instance()
+ {
+ Dictionary gameCode = new Dictionary();
+ gameCode.Add("{01C280}", new byte[] { 0x1, 0xC2, 0x80 });
+ gameCode.Add("{01C299}", new byte[] { 0x1, 0xC2, 0x99 });
+ gameCode.Add("{01C29C}", new byte[] { 0x1, 0xC2, 0x9C });
+ gameCode.Add("{01C297}", new byte[] { 0x1, 0xC2, 0x97 });
+ gameCode.Add("{01C298}", new byte[] { 0x1, 0xC2, 0x98 });
+ gameCode.Add("{01C286}", new byte[] { 0x1, 0xC2, 0x86 });
+ gameCode.Add("{017E}", new byte[] { 0x1, 0x7E });
+ gameCode.Add("{01C285}", new byte[] { 0x1, 0xC2, 0x85 });
+ gameCode.Add("{01C2B6}", new byte[] { 0x1, 0xC2, 0xB6 });
+ gameCode.Add("{01C2B5}", new byte[] { 0x1, 0xC2, 0xB5 });
+ gameCode.Add("{01C28A}", new byte[] { 0x1, 0xC2, 0x8A });
+ gameCode.Add("{017F}", new byte[] { 0x1, 0x7F });
+ gameCode.Add("{017D}", new byte[] { 0x1, 0x7D });
+ gameCode.Add("{0166}", new byte[] { 0x1, 0x66 });
+ gameCode.Add("{0167}", new byte[] { 0x1, 0x67 });
+ gameCode.Add("{0168}", new byte[] { 0x1, 0x68 });
+ gameCode.Add("{016A}", new byte[] { 0x1, 0x6A });
+ gameCode.Add("{0169}", new byte[] { 0x1, 0x69 });
+ gameCode.Add("{016B}", new byte[] { 0x1, 0x6B });
+ gameCode.Add("{0164}", new byte[] { 0x1, 0x64 });
+ gameCode.Add("{0165}", new byte[] { 0x1, 0x65 });
+ gameCode.Add("{016C}", new byte[] { 0x1, 0x6C });
+ gameCode.Add("{016D}", new byte[] { 0x1, 0x6D });
+ gameCode.Add("{01C283}", new byte[] { 0x1, 0xC2, 0x83 });
+ gameCode.Add("{01C284}", new byte[] { 0x1, 0xC2, 0x84 });
+ gameCode.Add("{01C287}", new byte[] { 0x1, 0xC2, 0x87 });
+ gameCode.Add("{01C288}", new byte[] { 0x1, 0xC2, 0x88 });
+ gameCode.Add("{01C289}", new byte[] { 0x1, 0xC2, 0x89 });
+ gameCode.Add("{01C28B}", new byte[] { 0x1, 0xC2, 0x8B });
+ gameCode.Add("{01C282}", new byte[] { 0x1, 0xC2, 0x82 });
+ gameCode.Add("{01C281}", new byte[] { 0x1, 0xC2, 0x81 });
+ gameCode.Add("{01C2A3}", new byte[] { 0x1, 0xC2, 0xA3 });
+ gameCode.Add("{01C290}", new byte[] { 0x1, 0xC2, 0x90 });
+ gameCode.Add("{01C291}", new byte[] { 0x1, 0xC2, 0x91 });
+ gameCode.Add("{01C292}", new byte[] { 0x1, 0xC2, 0x92 });
+ gameCode.Add("{01C293}", new byte[] { 0x1, 0xC2, 0x93 });
+ gameCode.Add("{01C2A4}", new byte[] { 0x1, 0xC2, 0xA4 });
+ gameCode.Add("{01C28C}", new byte[] { 0x1, 0xC2, 0x8C });
+ gameCode.Add("{01C28D}", new byte[] { 0x1, 0xC2, 0x8D });
+ gameCode.Add("{01C28E}", new byte[] { 0x1, 0xC2, 0x8E });
+ gameCode.Add("{01C28F}", new byte[] { 0x1, 0xC2, 0x8F });
+ gameCode.Add("{01C2A8}", new byte[] { 0x1, 0xC2, 0xA8 });
+ return gameCode;
+
+ }
+ public static Dictionary GetGameCode()
+ {
+ if (_Instance == null)
+ {
+ _Instance = Instance();
+ }
+ return _Instance;
+ }
+ }
+}
diff --git a/NieR-Text-Tool/NieR-Text-Tool.csproj b/NieR-Text-Tool/NieR-Text-Tool.csproj
new file mode 100644
index 0000000..eb64dc8
--- /dev/null
+++ b/NieR-Text-Tool/NieR-Text-Tool.csproj
@@ -0,0 +1,58 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {6EDB4357-2F91-48EE-8A54-0998F025C8C1}
+ Exe
+ NieR_Text_Tool
+ NieR-Text-Tool
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NieR-Text-Tool/PACK.cs b/NieR-Text-Tool/PACK.cs
new file mode 100644
index 0000000..72896d8
--- /dev/null
+++ b/NieR-Text-Tool/PACK.cs
@@ -0,0 +1,167 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.IO;
+
+namespace NieR_Text_Tool
+{
+ public static class PACK
+ {
+ #region Structure
+ public struct PackHeader
+ {
+ public int Magic;
+ public int Version;
+ public int PackSize;
+ public int UnkDataOffset;
+ public int Unk;
+ public int NameCount;
+ public int NameTableOffset;
+ public int Table1FileCount;
+ public int Table1Offset;
+ public int Table1RealOffset;
+ public int Table2FileCount;
+ public int Table2Offset;
+ public int Table2RealOffset;
+ }
+ public struct PackEntry
+ {
+ public int NameHash;
+ public int NameOffset;
+ public int RealNameOffset;
+ public int DataLength;
+ public int DataOffset;
+ public int RealDataOffset;
+ public int Unk;
+ public string FileName;
+ public byte[] FileData;
+ }
+ #endregion
+ public static PackHeader ReadHeader(ref BinaryReader reader)
+ {
+ reader.BaseStream.Seek(0, SeekOrigin.Begin);
+ PackHeader header = new PackHeader();
+ header.Magic = reader.ReadInt32();
+ if (header.Magic != 0x4B434150) throw new Exception("Unsupported file type.");
+ header.Version = reader.ReadInt32();
+ header.PackSize = reader.ReadInt32();
+ header.UnkDataOffset = reader.ReadInt32();
+ header.Unk = reader.ReadInt32();
+ header.NameCount = reader.ReadInt32();
+ header.NameTableOffset = reader.ReadInt32();
+ header.Table1FileCount = reader.ReadInt32();
+ header.Table1Offset = reader.ReadInt32();
+ header.Table1RealOffset = (int)(reader.BaseStream.Position - 4) + header.Table1Offset;
+ header.Table2FileCount = reader.ReadInt32();
+ header.Table2Offset = reader.ReadInt32();
+ header.Table2RealOffset = (int)(reader.BaseStream.Position - 4) + header.Table2Offset;
+ return header;
+ }
+ public static string ReadString(ref BinaryReader reader)
+ {
+ StringBuilder str = new StringBuilder();
+ byte[] ch = reader.ReadBytes(1);
+ while (ch[0] != 0 && reader.BaseStream.Position < reader.BaseStream.Length)
+ {
+ str.Append(Encoding.ASCII.GetString(ch));
+ ch = reader.ReadBytes(1);
+ }
+ return str.ToString();
+ }
+ public static PackEntry[] ReadEntries(ref BinaryReader reader, PackHeader header)
+ {
+ List result = new List();
+ reader.BaseStream.Position = header.Table2RealOffset;
+ for (int i = 0; i < header.Table2FileCount; i++)
+ {
+ PackEntry entry = new PackEntry();
+ entry.NameHash = reader.ReadInt32();
+ entry.NameOffset = reader.ReadInt32();
+ entry.RealNameOffset = (int)(reader.BaseStream.Position - 4) + entry.NameOffset;
+ entry.DataLength = reader.ReadInt32();
+ entry.DataOffset = reader.ReadInt32();
+ entry.RealDataOffset = (int)(reader.BaseStream.Position - 4) + entry.DataOffset;
+ entry.Unk = reader.ReadInt32();
+ long temp = reader.BaseStream.Position;
+ reader.BaseStream.Position = entry.RealNameOffset;
+ entry.FileName = ReadString(ref reader);
+ reader.BaseStream.Position = entry.RealDataOffset;
+ entry.FileData = reader.ReadBytes(entry.DataLength);
+ reader.BaseStream.Position = temp;
+ result.Add(entry);
+ }
+ return result.ToArray();
+ }
+ private static byte[] Padding(int len)
+ {
+ byte[] padding = new byte[len];
+ for (int i = 0; i < len; i++)
+ {
+ if (i < 8) padding[i] = 0x26;
+ else padding[i] = 0x40;
+ }
+ return padding;
+ }
+ public static void Unpack(string file, string des)
+ {
+ BinaryReader reader = new BinaryReader(File.OpenRead(file));
+ PackHeader header = ReadHeader(ref reader);
+ PackEntry[] files = ReadEntries(ref reader, header);
+ foreach (PackEntry entry in files)
+ {
+ string filePath = Path.Combine(des, $"{entry.FileName}.csv");
+ string data = CSV.ToCSV(entry.FileData);
+ if (!Directory.Exists(des)) Directory.CreateDirectory(des);
+ File.WriteAllText(filePath, data, Encoding.UTF8);
+ Console.WriteLine($">> {Path.GetFileName(filePath)}");
+ }
+ reader.Close();
+ }
+ public static void Repack(string file, string dir, string outFile)
+ {
+ MemoryStream input = new MemoryStream(File.ReadAllBytes(file));
+ BinaryReader reader = new BinaryReader(input);
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ PackHeader header = ReadHeader(ref reader);
+ PackEntry[] entries = ReadEntries(ref reader, header);
+ reader.BaseStream.Seek(0, SeekOrigin.Begin);
+ writer.Write(reader.ReadBytes(header.Table2RealOffset));
+ long tocPos = writer.BaseStream.Position;
+ writer.Write(new byte[0x14 * header.Table2FileCount]);
+ for (int i = 0; i < entries.Length; i++)
+ {
+ string filePath = Path.Combine(dir, $"{entries[i].FileName}.csv");
+ if (File.Exists(filePath))
+ {
+ entries[i].FileData = CSV.ToGameFormat(filePath);
+ entries[i].DataLength = entries[i].FileData.Length;
+ Console.WriteLine($"<< {Path.GetFileName(filePath)}");
+ }
+ entries[i].RealDataOffset = (int)writer.BaseStream.Position;
+ writer.Write(entries[i].FileData);
+ entries[i].RealNameOffset = (int)writer.BaseStream.Position;
+ writer.Write(Encoding.ASCII.GetBytes(entries[i].FileName));
+ writer.Write(new byte());
+ long temp = writer.BaseStream.Position;
+ writer.BaseStream.Position = tocPos + (0x14 * i);
+ writer.Write(entries[i].NameHash);
+ writer.Write(entries[i].RealNameOffset - (int)writer.BaseStream.Position);
+ writer.Write(entries[i].DataLength);
+ writer.Write(entries[i].RealDataOffset - (int)writer.BaseStream.Position);
+ writer.Write(entries[i].Unk);
+ writer.BaseStream.Position = temp;
+ }
+ writer.BaseStream.Seek(8, SeekOrigin.Begin);
+ writer.Write((int)writer.BaseStream.Length);
+ writer.Write((int)writer.BaseStream.Length);
+ File.WriteAllBytes(outFile, stream.ToArray());
+ reader.Close();
+ writer.Close();
+ input.Close();
+ stream.Close();
+ }
+ }
+}
diff --git a/NieR-Text-Tool/Program.cs b/NieR-Text-Tool/Program.cs
new file mode 100644
index 0000000..a77bd74
--- /dev/null
+++ b/NieR-Text-Tool/Program.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.IO;
+
+namespace NieR_Text_Tool
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.Title = "NieR Replicant Text Tool by LeHieu - VietHoaGame";
+ if (args.Length > 0)
+ {
+ switch (args[0])
+ {
+ case "-e":
+ if (args.Length >= 3)
+ {
+ PACK.Unpack(args[1], args[2]);
+ }
+ else
+ {
+ Console.WriteLine("-> Type \"-e [Input File] [Extract Folder]\" to extract the files.");
+ }
+ break;
+ case "-i":
+ if (args.Length >= 4)
+ {
+ PACK.Repack(args[1], args[2], args[3]);
+ Console.WriteLine($"\n>> {args[3]}");
+ }
+ else
+ {
+ Console.WriteLine("-> Type \"-i [Input File] [Extracted Folder] [Output File]\" to re-import the files.");
+ }
+ break;
+ default:
+ Help();
+ break;
+ }
+ }
+ else
+ {
+ Help();
+ }
+ }
+ static void Help()
+ {
+ Console.WriteLine("Usage:\n-> Type \"-e [Input File] [Extract Folder]\" to extract the files.\n-> Type \"-i [Input File] [Extracted Folder] [Output File]\" to re-import the files.");
+ }
+ }
+}
diff --git a/NieR-Text-Tool/Properties/AssemblyInfo.cs b/NieR-Text-Tool/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..f94441e
--- /dev/null
+++ b/NieR-Text-Tool/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("NieR-Text-Tool")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("NieR-Text-Tool")]
+[assembly: AssemblyCopyright("Copyright © 2021")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("6edb4357-2f91-48ee-8a54-0998f025c8c1")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/NieR-Text-Tool/TXT.cs b/NieR-Text-Tool/TXT.cs
new file mode 100644
index 0000000..b4a3a1d
--- /dev/null
+++ b/NieR-Text-Tool/TXT.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.IO;
+
+namespace NieR_Text_Tool
+{
+ public static class TXT
+ {
+ public static string ToTXT(byte[] bytes)
+ {
+ string str = Encoding.UTF8.GetString(bytes);
+ string[] lines = str.Split(new string[] { "\r\n" }, StringSplitOptions.None);
+ for (int i = 0; i < lines.Length; i++)
+ {
+ lines[i] = lines[i].Replace("\n", "").Replace("\t", "");
+ }
+ str = string.Join("\r\n", lines);
+ Dictionary gameCode = GameCode.GetGameCode();
+ foreach (KeyValuePair entry in gameCode)
+ {
+ str = str.Replace(Encoding.UTF8.GetString(entry.Value), entry.Key);
+ }
+ return str;
+ }
+ public static byte[] ToGameFormat(string input)
+ {
+ string str = input.Replace("", "\n").Replace("", "\t");
+ Dictionary gameCode = GameCode.GetGameCode();
+ foreach (KeyValuePair entry in gameCode)
+ {
+ str = str.Replace(entry.Key, Encoding.UTF8.GetString(entry.Value));
+ }
+ return Encoding.UTF8.GetBytes(str);
+ }
+ }
+}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4c0c3c0
--- /dev/null
+++ b/README.md
@@ -0,0 +1,8 @@
+# NieR Replicant ver1.22 Text Tool
+
+Requires [emil.exe](https://github.com/yretenai/kaine/releases) to extract game assets.
+Text files can be found at: *\snow\text*.
+
+## Usage:
+* Type "-e [Input Text File] [Extract Folder]" to extract the file.
+* Type "-i [Input Text File] [Extracted Folder] [Output File]" to re-import the file.
\ No newline at end of file