添加项目文件。

This commit is contained in:
Sancaros 2024-12-19 15:05:55 +08:00
parent 3841126c8a
commit ca28b58547
48 changed files with 4647 additions and 0 deletions

BIN
CPKTOOLS.zip Normal file

Binary file not shown.

BIN
CPKTOOLS/CriPakGUI.exe Normal file

Binary file not shown.

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>

BIN
CPKTOOLS/LibCPK.dll Normal file

Binary file not shown.

BIN
CPKTOOLS/LibCRIComp.dll Normal file

Binary file not shown.

Binary file not shown.

8
CriPakGUI/App.xaml Normal file
View File

@ -0,0 +1,8 @@
<Application x:Class="CriPakGUI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

16
CriPakGUI/App.xaml.cs Normal file
View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
namespace CriPakGUI
{
/// <summary>
/// App.xaml 的交互逻辑
/// </summary>
public partial class App : Application
{
}
}

21
CriPakGUI/CpkPatcher.xaml Normal file
View File

@ -0,0 +1,21 @@
<Window x:Class="CriPakGUI.CpkPatcher"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="补丁 CPK" Height="336" Width="564" ResizeMode="NoResize" Icon="Resources/importAssets.ico">
<Grid>
<TextBox x:Name="textbox_patchDir" HorizontalAlignment="Left" Height="23" Margin="26,35,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="372"/>
<Button x:Name="button_selPatchPath" Content="选择" HorizontalAlignment="Left" Margin="403,35,0,0" VerticalAlignment="Top" Width="37" Height="23" Click="button_selPatchPath_Click"/>
<Label Content="① 选择补丁数据目录" HorizontalAlignment="Left" Margin="26,10,0,0" VerticalAlignment="Top" Width="190"/>
<Label Content="② 选择新的CPK生成路径" HorizontalAlignment="Left" Margin="26,63,0,0" VerticalAlignment="Top" Width="190"/>
<TextBox x:Name="textbox_cpkDir" HorizontalAlignment="Left" Height="23" Margin="26,93,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="372"/>
<Button x:Name="button_selDstCPK" Content="选择" HorizontalAlignment="Left" Margin="403,93,0,0" VerticalAlignment="Top" Width="37" Height="23" Click="button_selDstCPK_Click"/>
<ProgressBar x:Name="progressbar1" HorizontalAlignment="Left" Height="18" Margin="26,195,0,0" VerticalAlignment="Top" Width="414"/>
<Label Content="进度:" HorizontalAlignment="Left" Margin="26,191,0,0" VerticalAlignment="Top" Width="77" Height="27" FontSize="10"/>
<Button x:Name="button_PatchCPK" Content="补丁 CPK" HorizontalAlignment="Left" Margin="461,63,0,0" VerticalAlignment="Top" Width="75" Height="80" Click="button_PatchCPK_Click"/>
<CheckBox x:Name="checkbox_donotcompress" Content="不使用CRILAYLA压缩" HorizontalAlignment="Left" Margin="26,143,0,0" VerticalAlignment="Top"/>
<ScrollViewer x:Name="scrollview0" HorizontalAlignment="Left" Height="50" Margin="26,223,0,0" VerticalAlignment="Top" Width="414" VerticalScrollBarVisibility="Auto">
<TextBlock x:Name="textblock0" TextWrapping="WrapWithOverflow" ScrollViewer.CanContentScroll="True"/>
</ScrollViewer>
</Grid>
</Window>

View File

@ -0,0 +1,334 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.IO;
using System.Windows.Navigation;
using System.Diagnostics;
using Ookii.Dialogs.Wpf;
using System.Threading;
using System.Windows.Threading;
using LibCPK;
namespace CriPakGUI
{
/// <summary>
/// CpkPatcher.xaml 的交互逻辑
/// </summary>
public partial class CpkPatcher : Window
{
public CpkPatcher(double x, double y)
{
InitializeComponent();
this.WindowStartupLocation = WindowStartupLocation.Manual;
this.Top = x;
this.Left = y;
}
private void button_selPatchPath_Click(object sender, RoutedEventArgs e)
{
VistaFolderBrowserDialog saveFilesDialog = new VistaFolderBrowserDialog();
saveFilesDialog.SelectedPath = myPackage.basePath + "/";
if (saveFilesDialog.ShowDialog().Value)
{
Debug.Print(saveFilesDialog.SelectedPath);
textbox_patchDir.Text = saveFilesDialog.SelectedPath;
}
}
private void button_selDstCPK_Click(object sender, RoutedEventArgs e)
{
VistaSaveFileDialog saveDialog = new VistaSaveFileDialog();
saveDialog.InitialDirectory = myPackage.basePath;
saveDialog.RestoreDirectory = true;
saveDialog.Filter = "CPK File*.cpk|*.cpk";
if (saveDialog.ShowDialog() == true)
{
string saveFileName = saveDialog.FileName;
textbox_cpkDir.Text = saveFileName;
}
}
private delegate void textblockDelegate(string text);
private void updateTextblock(string text)
{
textblock0.Text += string.Format("Updating ... {0}\n", text);
scrollview0.ScrollToEnd();
}
private delegate void progressbarDelegate(float no);
private void updateprogressbar(float no)
{
progressbar1.Value = no;
}
public class actionCPK
{
public string cpkDir { get; set; }
public string patchDir { get; set; }
public bool bForceCompress { get; set; }
public Dictionary<string, string> batch_file_list { get; set; }
}
private void button_PatchCPK_Click(object sender, RoutedEventArgs e)
{
string cpkDir = textbox_cpkDir.Text;
string patchDir = textbox_patchDir.Text;
Dictionary<string, string> batch_file_list = new Dictionary<string, string>();
List<string> ls = new List<string>();
if ((myPackage.cpk != null) && (Directory.Exists(patchDir)))
{
GetFilesFromPath(patchDir, ref ls);
Debug.Print(string.Format("GOT {0} Files.", ls.Count));
foreach (string s in ls)
{
string name = s.Remove(0, patchDir.Length + 1);
name = name.Replace("\\" , @"/");
if (!name.Contains(@"/"))
{
name = @"/" + name;
}
batch_file_list.Add(name, s);
}
actionCPK t = new actionCPK();
t.cpkDir = cpkDir;
t.patchDir = patchDir;
if (checkbox_donotcompress.IsChecked == true)
{
t.bForceCompress = false;
}
else
{
t.bForceCompress = true;
}
t.batch_file_list = batch_file_list;
ThreadPool.QueueUserWorkItem(new WaitCallback(PatchCPK), t);
}
else
{
MessageBox.Show("Error, cpkdata or patchdata not found.");
}
}
private void PatchCPK(object t)
{
string msg;
string cpkDir = ((actionCPK)t).cpkDir;
string patchDir = ((actionCPK)t).patchDir;
bool bForceCompress = ((actionCPK)t).bForceCompress;
Dictionary<string, string> batch_file_list = ((actionCPK)t).batch_file_list;
CPK cpk = myPackage.cpk;
BinaryReader oldFile = new BinaryReader(File.OpenRead(myPackage.cpk_name));
string outputName = cpkDir;
BinaryWriter newCPK = new BinaryWriter(File.OpenWrite(outputName));
List<FileEntry> entries = cpk.FileTable.OrderBy(x => x.FileOffset).ToList();
Tools tool = new Tools();
int id;
bool bFileRepeated = Tools.CheckListRedundant(entries);
for (int i = 0; i < entries.Count; i++)
{
this.UI_SetProgess((float)i / (float)entries.Count * 100f);
if (entries[i].FileType != "CONTENT")
{
if (entries[i].FileType == "FILE")
{
// I'm too lazy to figure out how to update the ContextOffset position so this works :)
if ((ulong)newCPK.BaseStream.Position < cpk.ContentOffset)
{
ulong padLength = cpk.ContentOffset - (ulong)newCPK.BaseStream.Position;
for (ulong z = 0; z < padLength; z++)
{
newCPK.Write((byte)0);
}
}
}
id = Convert.ToInt32(entries[i].ID);
string currentName;
if (id > 0 && bFileRepeated)
{
currentName = (((entries[i].DirName != null) ?
entries[i].DirName + "/" : "") + string.Format("[{0}]", id.ToString()) + entries[i].FileName);
}
else
{
currentName = ((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName;
}
if (!currentName.Contains("/"))
{
currentName = "/" + currentName;
}
Debug.Print("Got File:" + currentName.ToString());
if (!batch_file_list.Keys.Contains(currentName.ToString()))
//如果不在表中,复制原始数据
{
oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin);
entries[i].FileOffset = (ulong)newCPK.BaseStream.Position;
if (entries[i].FileName.ToString() == "ETOC_HDR")
{
cpk.EtocOffset = entries[i].FileOffset;
Debug.Print("Fix ETOC_OFFSET to {0:x8}", cpk.EtocOffset);
}
cpk.UpdateFileEntry(entries[i]);
byte[] chunk = oldFile.ReadBytes(Int32.Parse(entries[i].FileSize.ToString()));
newCPK.Write(chunk);
if ((newCPK.BaseStream.Position % 0x800) > 0 && i < entries.Count - 1)
{
long cur_pos = newCPK.BaseStream.Position;
for (int j = 0; j < (0x800 - (cur_pos % 0x800)); j++)
{
newCPK.Write((byte)0);
}
}
}
else
{
string replace_with = batch_file_list[currentName.ToString()];
//Got patch file name
msg = string.Format("Patching: {0}", currentName.ToString());
this.UI_SetTextBlock(msg);
Debug.Print(msg);
byte[] newbie = File.ReadAllBytes(replace_with);
entries[i].FileOffset = (ulong)newCPK.BaseStream.Position;
int o_ext_size = Int32.Parse((entries[i].ExtractSize).ToString());
int o_com_size = Int32.Parse((entries[i].FileSize).ToString());
if ((o_com_size < o_ext_size) && entries[i].FileType == "FILE" && bForceCompress == true)
{
// is compressed
msg = string.Format("Compressing data:{0:x8}", newbie.Length);
this.UI_SetTextBlock(msg);
Console.Write(msg);
byte[] dest_comp = cpk.CompressCRILAYLA(newbie);
entries[i].FileSize = Convert.ChangeType(dest_comp.Length, entries[i].FileSizeType);
entries[i].ExtractSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType);
cpk.UpdateFileEntry(entries[i]);
newCPK.Write(dest_comp);
msg = string.Format(">> {0:x8}\r\n", dest_comp.Length);
this.UI_SetTextBlock(msg);
Console.Write(msg);
}
else
{
msg = string.Format("Storing data:{0:x8}\r\n", newbie.Length);
this.UI_SetTextBlock(msg);
Console.Write(msg);
entries[i].FileSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType);
entries[i].ExtractSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType);
cpk.UpdateFileEntry(entries[i]);
newCPK.Write(newbie);
}
if ((newCPK.BaseStream.Position % 0x800) > 0 && i < entries.Count - 1)
{
long cur_pos = newCPK.BaseStream.Position;
for (int j = 0; j < (0x800 - (cur_pos % 0x800)); j++)
{
newCPK.Write((byte)0);
}
}
}
}
else
{
// Content is special.... just update the position
cpk.UpdateFileEntry(entries[i]);
}
}
cpk.WriteCPK(newCPK);
msg = string.Format("Writing TOC....");
this.UI_SetTextBlock(msg);
Console.WriteLine(msg);
cpk.WriteITOC(newCPK);
cpk.WriteTOC(newCPK);
cpk.WriteETOC(newCPK, cpk.EtocOffset);
cpk.WriteGTOC(newCPK);
newCPK.Close();
oldFile.Close();
msg = string.Format("Saving CPK to {0}....", outputName);
this.UI_SetTextBlock(msg);
Console.WriteLine(msg);
MessageBox.Show("CPK Patched.");
this.UI_SetProgess(0f);
}
public void UI_SetProgess(float value)
{
this.Dispatcher.Invoke(new progressbarDelegate(updateprogressbar), new object[] { (float)value });
}
public void UI_SetTextBlock(string msg)
{
this.Dispatcher.Invoke(new textblockDelegate(updateTextblock), new object[] { msg });
}
private void GetFilesFromPath(string directoryname , ref List<string> ls)
{
FileInfo[] fi = new DirectoryInfo(directoryname).GetFiles();
DirectoryInfo[] di = new DirectoryInfo(directoryname).GetDirectories();
if (fi.Length != 0)
{
foreach (FileInfo v in fi)
{
ls.Add(v.FullName);
}
}
if (di.Length != 0)
{
foreach (DirectoryInfo v in di)
{
GetFilesFromPath(v.FullName , ref ls);
}
}
}
}
}

181
CriPakGUI/CriPakGUI.csproj Normal file
View File

@ -0,0 +1,181 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B1456552-CB63-49BF-99C0-5A4669532F61}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CriPakGUI</RootNamespace>
<AssemblyName>CriPakGUI</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<TargetFrameworkProfile />
<PublishUrl>发布\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>Resources\1.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<StartupObject>CriPakGUI.App</StartupObject>
</PropertyGroup>
<ItemGroup>
<Reference Include="Ookii.Dialogs.Wpf">
<HintPath>Resources\Ookii.Dialogs.Wpf.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="WindowAboutGUI.xaml.cs">
<DependentUpon>WindowAboutGUI.xaml</DependentUpon>
</Compile>
<Page Include="CpkPatcher.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="CpkPatcher.xaml.cs">
<DependentUpon>CpkPatcher.xaml</DependentUpon>
</Compile>
<Compile Include="cpkwrapper.cs" />
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="WindowAboutGUI.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="app.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\1.ico" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\Icon1.ico" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LibCPK\LibCPK.csproj">
<Project>{ba3a00e4-4f51-4ab4-a8fb-f4b64a874449}</Project>
<Name>LibCPK</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.5">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.5 %28x86 和 x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\importAssets.ico" />
<Resource Include="Resources\openFile.ico" />
<Resource Include="Resources\saveFiles.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

99
CriPakGUI/MainWindow.xaml Normal file
View File

@ -0,0 +1,99 @@
<Window x:Class="CriPakGUI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CPK文件工具 Ver0.1 Sancaros" Height="360" Width="640" ResizeMode="CanResizeWithGrip" SizeToContent="WidthAndHeight" MinWidth="640" MinHeight="358" Icon="Resources/1.ico" MaxHeight="640">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0*"/>
<ColumnDefinition Width="0*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StatusBar Grid.ColumnSpan="3" Height="25" VerticalAlignment="Bottom">
<StatusBarItem Content="已载入CPK:"/>
<StatusBarItem x:Name="status_cpkname" Content=" "/>
<StatusBarItem x:Name="status_progress" Content=" " Width="40"/>
<StatusBarItem x:Name="status_tips" Content=" " Height="25" VerticalAlignment="Top"/>
<ProgressBar x:Name="progressbar0" Height="15" Width="287"/>
<StatusBarItem x:Name="status_cpkmsg" Content="0 文件已注入." HorizontalContentAlignment="Right"/>
</StatusBar>
<Menu Grid.ColumnSpan="3" Height="25" VerticalAlignment="Top">
<MenuItem Header="_文件">
<MenuItem x:Name="menu_openfile" Header="打开 CPK" Click="menu_openfile_Click" >
<MenuItem.Icon>
<Image Width="18" Height="18" Source="Resources/openFile.ico"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="menu_importAssets" Header="补丁 CPK..." Click="menu_importAssets_Click" >
<MenuItem.Icon>
<Image Width="18" Height="18" Source="Resources/importAssets.ico"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="menu_savefiles" Header="释放 CPK..." Click="menu_savefiles_Click" >
<MenuItem.Icon>
<Image Width="18" Height="18" Source="Resources/saveFiles.ico"/>
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="_工具">
<MenuItem Header="生成 filelist.csv" Click="menu_makeCSV_Click"/>
</MenuItem>
<MenuItem Header="_编码">
<ComboBox Name="comboBox_encodings" SelectedIndex="0" SelectionChanged="comboBox_encodings_SelectionChanged">
<ComboBoxItem>
<TextBlock Foreground="Blue">UTF-8</TextBlock>
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Foreground="Red">SHIFT-JIS</TextBlock>
</ComboBoxItem>
</ComboBox>
</MenuItem>
<Separator Margin="0"/>
<Separator Margin="0"/>
<Separator Margin="0"/>
<Separator Margin="0"/>
<Separator Margin="0"/>
<Separator Margin="0"/>
<Separator Margin="0"/>
<Separator Margin="0"/>
<Separator Margin="0"/>
<Separator Margin="0"/>
<Separator Margin="0"/>
<Separator Margin="0"/>
<Separator Margin="0"/>
<Separator Margin="0"/>
<Separator Margin="0"/>
<Separator Margin="0"/>
<MenuItem Header="关于" HorizontalContentAlignment="Right" HorizontalAlignment="Right" FlowDirection="RightToLeft" Width="50">
<MenuItem x:Name="menu_aboutgui" Header="关于 CriPak GUI" Click="menu_aboutgui_Click" />
</MenuItem>
</Menu>
<DataGrid x:Name="datagrid_cpk" CanUserAddRows="False" Margin="0,62,0,30" Grid.Column="2" VerticalScrollBarVisibility="Visible" IsReadOnly="True" FrozenColumnCount="7" AutoGenerateColumns="False" CanUserResizeColumns="False" CanUserReorderColumns="False" CanUserSortColumns="False" AlternationCount="2" RowHeight="17" AreRowDetailsFrozen="True" CanUserResizeRows="False" MaxHeight="500" HorizontalContentAlignment="Stretch" IsTextSearchEnabled="True" RowBackground="#FFF1F7F4">
<DataGrid.Columns>
<DataGridTextColumn x:Name="colume_number" Header="序号" MinWidth="40" Binding="{Binding id}"/>
<DataGridTextColumn x:Name="colume_filename" Header="文件名" MinWidth="200" Binding="{Binding FileName}"/>
<DataGridTextColumn x:Name="colume_offset" Header="偏移值" MinWidth="100" Binding="{Binding FileOffset , StringFormat=\{0:X8\}}"/>
<DataGridTextColumn x:Name="colume_size" Header="数据大小" MinWidth="80" Binding="{Binding FileSize}"/>
<DataGridTextColumn x:Name="colume_extractsize" Header="原始大小" MinWidth="80" Binding="{Binding ExtractSize}"/>
<DataGridTextColumn x:Name="culume_type" Header="数据类型" MinWidth="40" Binding="{Binding FileType}"/>
<DataGridTextColumn x:Name="colume_pt" Header="%" MinWidth="40" Binding="{Binding Pt}"/>
</DataGrid.Columns>
<DataGrid.ContextMenu>
<ContextMenu Name="dgmenu1" StaysOpen="true" PreviewMouseRightButtonDown="dgmenu1_Cilck">
<MenuItem Name="dgitem1" Header="_解压该类目" Click="dgitem1_Click"/>
<MenuItem Name="dgitem2" Header="_注入类目" Click="dgitem2_Click"/>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
<Grid Grid.ColumnSpan="3" Height="37" Margin="0,25,0,0" VerticalAlignment="Top" Background="{DynamicResource {x:Static SystemColors.MenuBarBrushKey}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="39*"/>
<ColumnDefinition Width="601*"/>
</Grid.ColumnDefinitions>
<Button x:Name="button_importassets" Content="补丁 CPK" HorizontalAlignment="Left" Margin="103,0,0,0" VerticalAlignment="Center" Width="86" IsEnabled="False" Click="button_importassets_Click" Grid.Column="1"/>
<Button x:Name="button_extract" Content="释放文件" HorizontalAlignment="Left" Margin="37,0,0,0" VerticalAlignment="Center" Width="86" IsEnabled="False" Click="button_extract_Click" Grid.ColumnSpan="2"/>
</Grid>
</Grid>
</Window>

View File

@ -0,0 +1,355 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Diagnostics;
using System.Windows.Shapes;
using System.IO;
using Ookii.Dialogs.Wpf;
using System.Threading;
using System.Windows.Threading;
using LibCPK;
namespace CriPakGUI
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
SetBasicPrefs();
}
private void SetBasicPrefs()
{
menu_savefiles.IsEnabled = false;
menu_importAssets.IsEnabled = false;
progressbar0.Maximum = 100;
myPackage.basePath = @"C:/";
}
private void menu_openfile_Click(object sender, RoutedEventArgs e)
{
Debug.WriteLine("载入 cpk");
string fName;
string baseName;
VistaOpenFileDialog openFileDialog = new VistaOpenFileDialog();
openFileDialog.InitialDirectory = "";
openFileDialog.Filter = "Criware CPK|*.cpk";
openFileDialog.RestoreDirectory = true;
openFileDialog.FilterIndex = 1;
if (openFileDialog.ShowDialog().Value)
{
fName = openFileDialog.FileName;
baseName = System.IO.Path.GetFileName(fName);
status_cpkname.Content = baseName;
beginLoadCPK(fName);
button_extract.IsEnabled = true;
button_importassets.IsEnabled = true;
}
}
private void beginLoadCPK(string fName)
{
ThreadPool.QueueUserWorkItem(o =>
{
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.SystemIdle,
new Action(() =>
{
cpkwrapper cpk = new cpkwrapper(fName);
status_cpkmsg.Content = string.Format("{0} 文件已注入.", cpk.nums);
datagrid_cpk.ItemsSource = cpk.table;
menu_importAssets.IsEnabled = true;
menu_savefiles.IsEnabled = true;
myPackage.basePath = System.IO.Path.GetDirectoryName(fName);
myPackage.baseName = System.IO.Path.GetFileName(fName);
myPackage.fileName = fName;
} )
);
});
}
private void menu_importAssets_Click(object sender, RoutedEventArgs e)
{
CpkPatcher patcherWindow = new CpkPatcher(this.Top, this.Left);
patcherWindow.ShowDialog();
}
private delegate void progressbarDelegate(float no);
private delegate void datagridDelegate(bool value);
private void updateDatagrid(bool value)
{
datagrid_cpk.IsEnabled = value;
button_extract.IsEnabled = value;
button_importassets.IsEnabled = value;
}
private void updateprogressbar(float no)
{
progressbar0.Value = no;
}
private void menu_savefiles_Click(object sender, RoutedEventArgs e)
{
VistaFolderBrowserDialog saveFilesDialog = new VistaFolderBrowserDialog();
saveFilesDialog.SelectedPath = myPackage.basePath;
if (saveFilesDialog.ShowDialog().Value)
{
Debug.Print(saveFilesDialog.SelectedPath + "/" + myPackage.baseName + "_unpacked");
ThreadPool.QueueUserWorkItem(new WaitCallback(beginExtractCPK), saveFilesDialog.SelectedPath);
}
}
private void beginExtractCPK(object foutDir)
{
string outDir;
outDir = (string)(foutDir + "/" + myPackage.baseName + "_unpacked");
if (myPackage.cpk != null)
{
if (!Directory.Exists(outDir))
{
Directory.CreateDirectory(outDir);
}
BinaryReader oldFile = new BinaryReader(File.OpenRead(myPackage.cpk_name));
List<FileEntry> entries = null;
entries = myPackage.cpk.FileTable.Where(x => x.FileType == "FILE").ToList();
if (entries.Count == 0)
{
MessageBox.Show("释放文件出错,类目为空.");
oldFile.Close();
return;
}
int i = 0;
int id;
string currentName;
bool bFileRepeated = Tools.CheckListRedundant(entries);
this.Dispatcher.Invoke(new datagridDelegate(updateDatagrid), new object[] { (bool)false });
while (i < entries.Count)
{
this.Dispatcher.Invoke(new progressbarDelegate(updateprogressbar), new object[] { (float)i / (float)entries.Count * 100f });//异步委托
if (!String.IsNullOrEmpty((string)entries[i].DirName))
{
Directory.CreateDirectory(outDir + "/" + entries[i].DirName.ToString());
}
id = Convert.ToInt32(entries[i].ID);
if (id > 0 && bFileRepeated)
{
currentName = (((entries[i].DirName != null) ?
entries[i].DirName + "/" : "") + string.Format("[{0}]", id.ToString()) + entries[i].FileName);
currentName = currentName.TrimStart('/');
}
else
{
currentName = ((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName;
currentName = currentName.TrimStart('/');
}
oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin);
string isComp = Encoding.ASCII.GetString(oldFile.ReadBytes(8));
oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin);
byte[] chunk = oldFile.ReadBytes(Int32.Parse(entries[i].FileSize.ToString()));
if (isComp == "CRILAYLA")
{
int size = Int32.Parse((entries[i].ExtractSize ?? entries[i].FileSize).ToString());
if (size != 0)
{
chunk = myPackage.cpk.DecompressLegacyCRI(chunk, size);
}
}
Debug.WriteLine(" 文件名 :{0}\n 文件偏移值:{1:x8} 释放大小:{2:x8} 块大小:{3:x8} {4}",
entries[i].FileName.ToString(),
(long)entries[i].FileOffset,
entries[i].ExtractSize,
entries[i].FileSize,
((float)i / (float)entries.Count) * 100f);
string dstpath = outDir + "/" + currentName;
dstpath = Tools.GetSafePath(dstpath);
string dstdir = System.IO.Path.GetDirectoryName(dstpath);
if (!Directory.Exists(dstdir))
{
Directory.CreateDirectory(dstdir);
}
File.WriteAllBytes(dstpath, chunk);
i += 1;
}
oldFile.Close();
this.Dispatcher.Invoke(new progressbarDelegate(updateprogressbar), new object[] { 100f });
this.Dispatcher.Invoke(new datagridDelegate(updateDatagrid), new object[] { (bool)true });
MessageBox.Show("释放完成.");
}
}
private void button_extract_Click(object sender, RoutedEventArgs e)
{
VistaFolderBrowserDialog saveFilesDialog = new VistaFolderBrowserDialog();
saveFilesDialog.SelectedPath = myPackage.basePath + "/";
if (saveFilesDialog.ShowDialog().Value)
{
Debug.Print(saveFilesDialog.SelectedPath + "/" + myPackage.baseName + "_unpacked");
ThreadPool.QueueUserWorkItem(new WaitCallback(beginExtractCPK), saveFilesDialog.SelectedPath);
}
}
private void button_importassets_Click(object sender, RoutedEventArgs e)
{
CpkPatcher patcherWindow = new CpkPatcher(this.Top, this.Left);
patcherWindow.ShowDialog();
}
private void menu_aboutgui_Click(object sender, RoutedEventArgs e)
{
WindowAboutGUI aboutwindow = new WindowAboutGUI(this.Top, this.Left);
aboutwindow.ShowDialog();
}
private void dgmenu1_Cilck(object sender, MouseButtonEventArgs e)
{
Point p = e.GetPosition(this.datagrid_cpk);
HitTestResult htr = VisualTreeHelper.HitTest(this.datagrid_cpk, p);
TextBlock o = htr.VisualHit as TextBlock;
if (o != null)
{
DataGridRow dgr = VisualTreeHelper.GetParent(o) as DataGridRow;
dgr.Focus();
dgr.IsSelected = true;
}
}
private void dgitem1_Click(object sender, RoutedEventArgs e)
{
CPKTable t = this.datagrid_cpk.SelectedItem as CPKTable;
if (t != null)
{
if (t.FileSize > 0 && t.FileType == "FILE")
{
VistaSaveFileDialog saveFilesDialog = new VistaSaveFileDialog();
saveFilesDialog.InitialDirectory = myPackage.basePath ;
saveFilesDialog.FileName = myPackage.basePath + "/" + t._localName;
if (saveFilesDialog.ShowDialog().Value)
{
byte[] chunk = ExtractItem(t);
File.WriteAllBytes(saveFilesDialog.FileName, chunk);
MessageBox.Show(String.Format("解压至 :{0}", saveFilesDialog.FileName));
}
}
}
}
private void dgitem2_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("当前不支持该功能");
}
private byte[] ExtractItem(CPKTable t)
{
CPKTable entries = t as CPKTable;
BinaryReader oldFile = new BinaryReader(File.OpenRead(myPackage.cpk_name));
oldFile.BaseStream.Seek((long)entries.FileOffset, SeekOrigin.Begin);
string isComp = Encoding.ASCII.GetString(oldFile.ReadBytes(8));
oldFile.BaseStream.Seek((long)entries.FileOffset, SeekOrigin.Begin);
byte[] chunk = oldFile.ReadBytes(Int32.Parse(entries.FileSize.ToString()));
if (isComp == "CRILAYLA")
{
int size;
if (entries.ExtractSize == 0)
{
size = entries.FileSize;
}
else
{
size = entries.ExtractSize;
}
if (size != 0)
{
chunk = myPackage.cpk.DecompressLegacyCRI(chunk, size);
}
}
oldFile.Close();
return chunk;
}
private void menu_makeCSV_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("当前不支持该功能");
}
private void comboBox_encodings_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
int cur = comboBox_encodings.SelectedIndex;
Encoding current_codepage;
switch (cur)
{
case 0:
current_codepage = Encoding.GetEncoding(65001);
break;
case 1:
current_codepage = Encoding.GetEncoding(932);
break;
default:
current_codepage = Encoding.GetEncoding(65001);
break;
}
if (current_codepage != myPackage.encoding)
{
myPackage.encoding = current_codepage;
if (myPackage.fileName != null)
{
beginLoadCPK(myPackage.fileName);
}
}
}
}
}

View File

@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// 有关程序集的常规信息通过以下
// 特性集控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("CriPakGUI")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CriPakGUI")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 使此程序集中的类型
// 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
// 则将该类型上的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
//若要开始生成可本地化的应用程序,请在
//<PropertyGroup> 中的 .csproj 文件中
//设置 <UICulture>CultureYouAreCodingWith</UICulture>。 例如,如果您在源文件中
//使用的是美国英语,请将 <UICulture> 设置为 en-US。 然后取消
//对以下 NeutralResourceLanguage 特性的注释。 更新
//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //主题特定资源词典所处位置
//(在页面或应用程序资源词典中
// 未找到某个资源的情况下使用)
ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
//(在页面、应用程序或任何主题特定资源词典中
// 未找到某个资源的情况下使用)
)]
// 程序集的版本信息由下面四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
// 方法是按如下所示使用“*”:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

133
CriPakGUI/Properties/Resources.Designer.cs generated Normal file
View File

@ -0,0 +1,133 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace CriPakGUI.Properties {
using System;
/// <summary>
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// </summary>
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.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>
/// 返回此类使用的缓存的 ResourceManager 实例。
/// </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("CriPakGUI.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 重写当前线程的 CurrentUICulture 属性,对
/// 使用此强类型资源类的所有资源查找执行重写。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。
/// </summary>
internal static System.Drawing.Icon _1 {
get {
object obj = ResourceManager.GetObject("_1", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
/// <summary>
/// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。
/// </summary>
internal static System.Drawing.Icon importAssets {
get {
object obj = ResourceManager.GetObject("importAssets", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
/// <summary>
/// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。
/// </summary>
internal static System.Drawing.Icon importAssets1 {
get {
object obj = ResourceManager.GetObject("importAssets1", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
/// <summary>
/// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。
/// </summary>
internal static System.Drawing.Icon openFile {
get {
object obj = ResourceManager.GetObject("openFile", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
/// <summary>
/// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。
/// </summary>
internal static System.Drawing.Icon openFile1 {
get {
object obj = ResourceManager.GetObject("openFile1", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
/// <summary>
/// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。
/// </summary>
internal static System.Drawing.Icon saveFiles {
get {
object obj = ResourceManager.GetObject("saveFiles", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
/// <summary>
/// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。
/// </summary>
internal static System.Drawing.Icon saveFiles1 {
get {
object obj = ResourceManager.GetObject("saveFiles1", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
}
}

View File

@ -0,0 +1,142 @@
<?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>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="importAssets" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\importAssets.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="importAssets1" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\importAssets.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="openFile" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\openFile.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="openFile1" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\openFile.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="saveFiles" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\saveFiles.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="saveFiles1" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\saveFiles.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_1" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\1.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace CriPakGUI.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.12.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;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

BIN
CriPakGUI/Resources/1.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -0,0 +1,12 @@
<Window x:Class="CriPakGUI.WindowAboutGUI"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="关于 GUI" Height="300" Width="395" WindowStyle="ToolWindow" ResizeMode="NoResize" Icon="Resources/1.ico">
<Grid>
<ScrollViewer HorizontalAlignment="Left" Height="210" Margin="10,10,0,0" VerticalAlignment="Top" Width="369">
<TextBlock x:Name="textblock0" TextWrapping="WrapWithOverflow" Background="WhiteSmoke" IsHyphenationEnabled="True"/>
</ScrollViewer>
<Button x:Name="button_Close" Content="关闭" HorizontalAlignment="Left" Margin="152,243,0,0" VerticalAlignment="Top" Width="75" Click="button_Close_Click"/>
</Grid>
</Window>

View File

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace CriPakGUI
{
/// <summary>
/// WindowAboutGUI.xaml 的交互逻辑
/// </summary>
public partial class WindowAboutGUI : Window
{
public WindowAboutGUI(double x, double y)
{
InitializeComponent();
this.WindowStartupLocation = WindowStartupLocation.Manual;
this.Top = x;
this.Left = y;
SetWindowPrefs();
}
private void SetWindowPrefs()
{
textblock0.Text = @"CriPakTools-GUI
Github repository:
https://github.com/wmltogether/CriPakTools
This tool is based on codes by
Falo (http://forum.xentax.com/viewtopic.php?f=10&t=10646),
Nanashi3(http://forums.fuwanovel.org/index.php?/topic/1785-request-for-psp-hackers/page-4),
esperknight (https://github.com/esperknight/CriPakTools),
and uyjulian(https://github.com/uyjulian/CriPakTools)
I forked these repos , added batch reimport \ compression code \ basic GUI and fixed TOC issues .
Thanks for KenTse 's CRILAYLA compression method.
What's new in this modding version:
Added Encodings for CPK Reader
Added Batch Mode
Added compression option
Fixed GTOC & ETOC
Fixed CPK header
now it support almost all games using Criware cpk with itoc ,gtoc and etoc chunks.
";
}
private void button_Close_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
}

3
CriPakGUI/app.config Normal file
View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>

113
CriPakGUI/cpkwrapper.cs Normal file
View File

@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LibCPK;
using System.IO;
namespace CriPakGUI
{
public enum packageEncodings
{
UTF_8 = 65001,
SHIFT_JIS = 932,
}
public static class myPackage
{
public static CPK cpk { get; set; }
public static string basePath { get; set; }
public static string cpk_name { get; set; }
public static string baseName { get; set; }
public static string fileName { get; set; }
public static Encoding encoding = Encoding.GetEncoding(65001);
}
public class CPKTable
{
public int id { get; set; }
public string FileName { get; set; }
public string _localName { get; set; }
//public string DirName;
public UInt64 FileOffset { get; set; }
public int FileSize { get; set; }
public int ExtractSize { get; set; }
public string FileType { get; set; }
public float Pt { get; set; }
}
public class cpkwrapper
{
public int nums = 0;
public List<CPKTable> table;
public cpkwrapper(string inFile)
{
string cpk_name = inFile;
table = new List<CPKTable>();
myPackage.cpk = new CPK(new Tools());
myPackage.cpk.ReadCPK(cpk_name, myPackage.encoding);
myPackage.cpk_name = cpk_name;
BinaryReader oldFile = new BinaryReader(File.OpenRead(cpk_name));
List<FileEntry> entries = myPackage.cpk.FileTable.OrderBy(x => x.FileOffset).ToList();
int i = 0;
bool bFileRepeated = Tools.CheckListRedundant(entries);
while (i < entries.Count)
{
/*
Console.WriteLine("FILE ID:{0},File Name:{1},File Type:{5},FileOffset:{2:x8},Extract Size:{3:x8},Chunk Size:{4:x8}", entries[i].ID,
(((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName),
entries[i].FileOffset,
entries[i].ExtractSize,
entries[i].FileSize,
entries[i].FileType);
*/
if (entries[i].FileType != null)
{
nums += 1;
CPKTable t = new CPKTable();
if (entries[i].ID == null)
{
t.id = -1;
}
else
{
t.id = Convert.ToInt32(entries[i].ID);
}
if (t.id >= 0 && bFileRepeated)
{
t.FileName = (((entries[i].DirName != null) ?
entries[i].DirName + "/" : "") + string.Format("[{0}]",t.id.ToString()) + entries[i].FileName);
}
else
{
t.FileName = (((entries[i].DirName != null) ?
entries[i].DirName + "/" : "") + entries[i].FileName);
}
t._localName = entries[i].FileName.ToString();
t.FileOffset = Convert.ToUInt64(entries[i].FileOffset);
t.FileSize = Convert.ToInt32(entries[i].FileSize);
t.ExtractSize = Convert.ToInt32(entries[i].ExtractSize);
t.FileType = entries[i].FileType;
if (entries[i].FileType == "FILE")
{
t.Pt = (float)Math.Round((float)t.FileSize / (float)t.ExtractSize, 2) * 100f;
}
else
{
t.Pt = (float)1f * 100f;
}
table.Add(t);
}
i += 1;
}
oldFile.Close();
}
}
}

77
CriPakTools.sln Normal file
View File

@ -0,0 +1,77 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.16
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CriPakTools", "CriPakTools\CriPakTools.csproj", "{05EC5B1D-DF4F-48D6-A17F-C8AB5FD4A015}"
ProjectSection(ProjectDependencies) = postProject
{BA3A00E4-4F51-4AB4-A8FB-F4B64A874449} = {BA3A00E4-4F51-4AB4-A8FB-F4B64A874449}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CriPakGUI", "CriPakGUI\CriPakGUI.csproj", "{B1456552-CB63-49BF-99C0-5A4669532F61}"
ProjectSection(ProjectDependencies) = postProject
{BA3A00E4-4F51-4AB4-A8FB-F4B64A874449} = {BA3A00E4-4F51-4AB4-A8FB-F4B64A874449}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibCPK", "LibCPK\LibCPK.csproj", "{BA3A00E4-4F51-4AB4-A8FB-F4B64A874449}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibCRIComp", "LibCRIComp\LibCRIComp.vcxproj", "{E5829A5B-E121-41AA-A84B-E7B4C8DBDF30}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{05EC5B1D-DF4F-48D6-A17F-C8AB5FD4A015}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{05EC5B1D-DF4F-48D6-A17F-C8AB5FD4A015}.Debug|Any CPU.Build.0 = Debug|Any CPU
{05EC5B1D-DF4F-48D6-A17F-C8AB5FD4A015}.Debug|x64.ActiveCfg = Debug|x64
{05EC5B1D-DF4F-48D6-A17F-C8AB5FD4A015}.Debug|x64.Build.0 = Debug|x64
{05EC5B1D-DF4F-48D6-A17F-C8AB5FD4A015}.Debug|x86.ActiveCfg = Debug|x86
{05EC5B1D-DF4F-48D6-A17F-C8AB5FD4A015}.Debug|x86.Build.0 = Debug|x86
{05EC5B1D-DF4F-48D6-A17F-C8AB5FD4A015}.Release|Any CPU.ActiveCfg = Release|Any CPU
{05EC5B1D-DF4F-48D6-A17F-C8AB5FD4A015}.Release|Any CPU.Build.0 = Release|Any CPU
{05EC5B1D-DF4F-48D6-A17F-C8AB5FD4A015}.Release|x64.ActiveCfg = Release|x64
{05EC5B1D-DF4F-48D6-A17F-C8AB5FD4A015}.Release|x64.Build.0 = Release|x64
{05EC5B1D-DF4F-48D6-A17F-C8AB5FD4A015}.Release|x86.ActiveCfg = Release|x86
{05EC5B1D-DF4F-48D6-A17F-C8AB5FD4A015}.Release|x86.Build.0 = Release|x86
{B1456552-CB63-49BF-99C0-5A4669532F61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B1456552-CB63-49BF-99C0-5A4669532F61}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B1456552-CB63-49BF-99C0-5A4669532F61}.Debug|x64.ActiveCfg = Debug|Any CPU
{B1456552-CB63-49BF-99C0-5A4669532F61}.Debug|x86.ActiveCfg = Debug|Any CPU
{B1456552-CB63-49BF-99C0-5A4669532F61}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B1456552-CB63-49BF-99C0-5A4669532F61}.Release|Any CPU.Build.0 = Release|Any CPU
{B1456552-CB63-49BF-99C0-5A4669532F61}.Release|x64.ActiveCfg = Release|Any CPU
{B1456552-CB63-49BF-99C0-5A4669532F61}.Release|x64.Build.0 = Release|Any CPU
{B1456552-CB63-49BF-99C0-5A4669532F61}.Release|x86.ActiveCfg = Release|Any CPU
{BA3A00E4-4F51-4AB4-A8FB-F4B64A874449}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BA3A00E4-4F51-4AB4-A8FB-F4B64A874449}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BA3A00E4-4F51-4AB4-A8FB-F4B64A874449}.Debug|x64.ActiveCfg = Debug|Any CPU
{BA3A00E4-4F51-4AB4-A8FB-F4B64A874449}.Debug|x86.ActiveCfg = Debug|Any CPU
{BA3A00E4-4F51-4AB4-A8FB-F4B64A874449}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BA3A00E4-4F51-4AB4-A8FB-F4B64A874449}.Release|Any CPU.Build.0 = Release|Any CPU
{BA3A00E4-4F51-4AB4-A8FB-F4B64A874449}.Release|x64.ActiveCfg = Release|Any CPU
{BA3A00E4-4F51-4AB4-A8FB-F4B64A874449}.Release|x64.Build.0 = Release|Any CPU
{BA3A00E4-4F51-4AB4-A8FB-F4B64A874449}.Release|x86.ActiveCfg = Release|Any CPU
{E5829A5B-E121-41AA-A84B-E7B4C8DBDF30}.Debug|Any CPU.ActiveCfg = Debug|Win32
{E5829A5B-E121-41AA-A84B-E7B4C8DBDF30}.Debug|x64.ActiveCfg = Debug|x64
{E5829A5B-E121-41AA-A84B-E7B4C8DBDF30}.Debug|x64.Build.0 = Debug|x64
{E5829A5B-E121-41AA-A84B-E7B4C8DBDF30}.Debug|x86.ActiveCfg = Debug|Win32
{E5829A5B-E121-41AA-A84B-E7B4C8DBDF30}.Debug|x86.Build.0 = Debug|Win32
{E5829A5B-E121-41AA-A84B-E7B4C8DBDF30}.Release|Any CPU.ActiveCfg = Release|Win32
{E5829A5B-E121-41AA-A84B-E7B4C8DBDF30}.Release|x64.ActiveCfg = Release|x64
{E5829A5B-E121-41AA-A84B-E7B4C8DBDF30}.Release|x64.Build.0 = Release|x64
{E5829A5B-E121-41AA-A84B-E7B4C8DBDF30}.Release|x86.ActiveCfg = Release|Win32
{E5829A5B-E121-41AA-A84B-E7B4C8DBDF30}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {770B89CA-7183-4E2F-A24E-0E1920153831}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{05EC5B1D-DF4F-48D6-A17F-C8AB5FD4A015}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>LibCPK</RootNamespace>
<AssemblyName>CriPakTools</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
<PublishUrl>发布\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
<OutputPath>bin\Debug\</OutputPath>
<Optimize>true</Optimize>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<WarningLevel>3</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\Release\</OutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Prefer32Bit>false</Prefer32Bit>
<Optimize>true</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Debug\</OutputPath>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Release\</OutputPath>
<Prefer32Bit>false</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4 Client Profile %28x86 和 x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.4.5">
<Visible>False</Visible>
<ProductName>Windows Installer 4.5</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LibCPK\LibCPK.csproj">
<Project>{ba3a00e4-4f51-4ab4-a8fb-f4b64a874449}</Project>
<Name>LibCPK</Name>
</ProjectReference>
<ProjectReference Include="..\LibCRIComp\LibCRIComp.vcxproj">
<Project>{e5829a5b-e121-41aa-a84b-e7b4c8dbdf30}</Project>
<Name>LibCRIComp</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

486
CriPakTools/Program.cs Normal file
View File

@ -0,0 +1,486 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using LibCPK;
namespace CriPakTools
{
public class SystemEncoding
{
public static Encoding Codecs = Encoding.UTF8;
}
class Program
{
[DllImport("user32.dll", EntryPoint = "MessageBox")]
public static extern int MsgBox(IntPtr hwnd, string text, string caption, uint type);
public static void ShowMsgBox(string msg)
{
MsgBox(IntPtr.Zero, msg, "CriPakTools", 1);
}
static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("error: no args\n");
Console.WriteLine("====================");
Console.WriteLine("This tool has been redesigned, please use CriPakGUI.exe ");
Console.WriteLine("====================");
Console.WriteLine("This tool is based on the codes by Falo , Nanashi3 ,esperknight and uyjulian");
Console.WriteLine("I forked and added batch reimport and compress code .");
Console.WriteLine("Thanks for KenTse 's CRILAYLA compression method");
Console.WriteLine(" by: wmltogether@gmail.com");
Console.WriteLine("CriPakTool Usage:");
Console.WriteLine(" -e - set encodings (utf8, utf16, cp932)");
Console.WriteLine(" -l - Displays all contained chunks.");
Console.WriteLine(" -x - Extracts all files.");
Console.WriteLine(" -r REPLACE_ME REPLACE_WITH - Replaces REPLACE_ME with REPLACE_WITH.");
Console.WriteLine(" -o OUT_FILE - Set output file.");
Console.WriteLine(" -d OUT_DIR - Set output directory.");
Console.WriteLine(" -i IN_FILE - Set input file.");
Console.WriteLine(" -c - use CRILAYLA compression");
Console.WriteLine(" -y - use legacy (c)CRI decompression");
Console.WriteLine(" -b BATCH_REPLACE_LIST_TXT - Batch Replace file recorded in filelist.txt .");
Console.WriteLine(" -h HELP");
Program.ShowMsgBox("Error: \n Please run this program from console!");
return;
}
bool doExtract = false;
bool doReplace = false;
bool doDisplay = false;
bool bUseCompress = false;
bool doBatchReplace = false; //添加批量替换功能
bool bUseLegacyCompress = false; //添加旧式解压参数
string outDir = ".";
string inFile = "";
string outFile = "";
string replaceMe = "";
string replaceWith = "";
string batch_text_name = "";
for (int i = 0; i < args.Length; i++)
{
string option = args[i];
if (option[0] == '-')
{
switch (option[1])
{
case 'e':
{
var encodingdata = args[i + 1];
if (encodingdata.ToLower().Equals("utf8") || encodingdata.ToLower().Equals("utf-8"))
{
SystemEncoding.Codecs = Encoding.UTF8;
}
else if (encodingdata.ToLower().Equals("cp932") || encodingdata.ToLower().Equals("sjis") || encodingdata.ToLower().Equals("shift-jis"))
{
SystemEncoding.Codecs = Encoding.GetEncoding(932);
}
else if (encodingdata.ToLower().Equals("utf-16") || encodingdata.ToLower().Equals("unicode") || encodingdata.ToLower().Equals("utf16"))
{
SystemEncoding.Codecs = Encoding.Unicode;
}
break;
}
case 'x': doExtract = true; break;
case 'c': bUseCompress = true; break;
case 'r': doReplace = true; replaceMe = args[i + 1]; replaceWith = args[i + 2]; break;
case 'l': doDisplay = true; break;
case 'd': outDir = args[i + 1]; break;
case 'i': inFile = args[i + 1]; break;
case 'o': outFile = args[i + 1]; break;
case 'b': doBatchReplace = true; batch_text_name = args[i + 1]; break;
case 'y': bUseLegacyCompress = true; break;
case 'h':
Console.WriteLine("CriPakTool Usage:");
Console.WriteLine(" -l - Displays all contained chunks.");
Console.WriteLine(" -x - Extracts all files.");
Console.WriteLine(" -c - use CRILAYLA compression");
Console.WriteLine(" -r REPLACE_ME REPLACE_WITH - Replaces REPLACE_ME with REPLACE_WITH.");
Console.WriteLine(" -o OUT_FILE - Set output file.");
Console.WriteLine(" -d OUT_DIR - Set output directory.");
Console.WriteLine(" -i IN_FILE - Set input file.");
Console.WriteLine(" -b BATCH_REPLACE_LIST_TXT - Batch Replace file recorded in filelist.txt .");
Console.WriteLine(" -h HELP");
Console.WriteLine(" [Extract files from cpk]");
Console.WriteLine(" CriPakTool.exe -x -i xxx.cpk -d xxx.cpk_unpacked");
Console.WriteLine(" [Display files from cpk]");
Console.WriteLine(" CriPakTool.exe -l -i xxx.cpk");
Console.WriteLine(" [Batch Replace files into cpk]");
Console.WriteLine(" CriPakTool.exe -b filelist.txt -c -i xxx.cpk -o xxx_patched.cpk");
Console.WriteLine(" //e.g. FILELIST.TXT");
Console.WriteLine(" original_file_name(in cpk),patch_file_name(in folder)");
Console.WriteLine(" /HD_font_a.ftx,patch/BOOT.cpk_unpacked/HD_font_a.ftx");
Console.WriteLine(" OTHER/ICON0.PNG,patch/BOOT.cpk_unpacked/OTHER/ICON0.PNG");
Console.WriteLine("...");
return;
default:
Console.WriteLine("CriPakTool Usage:");
Console.WriteLine(" -l - Displays all contained chunks.");
Console.WriteLine(" -x - Extracts all files.");
Console.WriteLine(" -c - use CRILAYLA compression");
Console.WriteLine(" -r REPLACE_ME REPLACE_WITH - Replaces REPLACE_ME with REPLACE_WITH.");
Console.WriteLine(" -o OUT_FILE - Set output file.");
Console.WriteLine(" -d OUT_DIR - Set output directory.");
Console.WriteLine(" -i IN_FILE - Set input file.");
Console.WriteLine(" -b BATCH_REPLACE_LIST_TXT - Batch Replace file recorded in filelist.txt .");
break;
}
}
}
if (inFile == "")
{
Console.WriteLine("ERROR :You must give -i argv");
return;
}
if (!File.Exists(inFile))
{
Console.WriteLine("ERROR :INPUT FILE NOT EXISTS");
return;
}
if (!(doExtract || doReplace || doDisplay || doBatchReplace))
{ //Lazy sanity checking for now
Console.WriteLine("no? \n");
return;
}
string cpk_name = inFile;
CPK cpk = new CPK(new Tools());
cpk.ReadCPK(cpk_name, SystemEncoding.Codecs);
BinaryReader oldFile = new BinaryReader(File.OpenRead(cpk_name));
if (doDisplay)
{
List<FileEntry> entries = cpk.FileTable.OrderBy(x => x.FileOffset).ToList();
for (int i = 0; i < entries.Count; i++)
{
Console.WriteLine("FILE ID:{0},File Name:{1},File Type:{5},FileOffset:{2:x8},Extract Size:{3:x8},Chunk Size:{4:x8}", entries[i].ID,
(((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName) ,
entries[i].FileOffset,
entries[i].ExtractSize,
entries[i].FileSize,
entries[i].FileType);
}
}
else if (doExtract)
{
if (!Directory.Exists(outDir))
{
Directory.CreateDirectory(outDir);
}
List<FileEntry> entries = null;
entries = cpk.FileTable.Where(x => x.FileType == "FILE").ToList();
if (entries.Count == 0)
{
Console.WriteLine("err while extracting.");
}
for (int i = 0; i < entries.Count; i++)
{
if (!String.IsNullOrEmpty((string)entries[i].DirName))
{
Directory.CreateDirectory(outDir + "/" + entries[i].DirName.ToString());
}
oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin);
string isComp = Encoding.ASCII.GetString(oldFile.ReadBytes(8));
oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin);
byte[] chunk = oldFile.ReadBytes(Int32.Parse(entries[i].FileSize.ToString()));
Console.WriteLine("FileName :{0}\n FileOffset:{1:x8} ExtractSize:{2:x8} ChunkSize:{3:x8}",
entries[i].FileName.ToString(),
(long)entries[i].FileOffset,
entries[i].ExtractSize,
entries[i].FileSize);
if (isComp == "CRILAYLA")
{
Console.WriteLine("Got CRILAYLA !");
int size = Int32.Parse((entries[i].ExtractSize ?? entries[i].FileSize).ToString());
if (size != 0)
if (bUseLegacyCompress == false)
{
chunk = cpk.DecompressCRILAYLA(chunk, size);
}
else
{
chunk = cpk.DecompressLegacyCRI(chunk, size);
}
}
string dstpath = outDir + "/" + ((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName.ToString();
dstpath = Tools.GetSafePath(dstpath);
string dstdir = Path.GetDirectoryName(dstpath);
if (!Directory.Exists(dstdir))
{
Directory.CreateDirectory(dstdir);
}
File.WriteAllBytes(dstpath, chunk);
}
}
else if (doBatchReplace)
{
//批量处理功能 读取filelist.txt内文件将相应文件批量导入到cpk
FileInfo fi = new FileInfo(cpk_name);
string outputName = outFile;
BinaryWriter newCPK = new BinaryWriter(File.OpenWrite(outputName));
List<FileEntry> entries = cpk.FileTable.OrderBy(x => x.FileOffset).ToList();
Tools tool = new Tools();
Dictionary<string, string> batch_file_list = tool.ReadBatchScript(batch_text_name);
for (int i = 0; i < entries.Count; i++)
{
if (entries[i].FileType != "CONTENT")
{
if (entries[i].FileType == "FILE")
{
// I'm too lazy to figure out how to update the ContextOffset position so this works :)
if ((ulong)newCPK.BaseStream.Position < cpk.ContentOffset)
{
ulong padLength = cpk.ContentOffset - (ulong)newCPK.BaseStream.Position;
for (ulong z = 0; z < padLength; z++)
{
newCPK.Write((byte)0);
}
}
}
string currentName = ((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName;
if (!currentName.Contains("/"))
{
currentName = "/" + currentName;
}
if (!batch_file_list.Keys.Contains(currentName.ToString()))
//如果不在表中,复制原始数据
{
oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin);
entries[i].FileOffset = (ulong)newCPK.BaseStream.Position;
if (entries[i].FileName.ToString() == "ETOC_HDR")
{
cpk.EtocOffset = entries[i].FileOffset;
Console.WriteLine("Fix ETOC_OFFSET to {0:x8}", cpk.EtocOffset);
}
cpk.UpdateFileEntry(entries[i]);
byte[] chunk = oldFile.ReadBytes(Int32.Parse(entries[i].FileSize.ToString()));
newCPK.Write(chunk);
if ((newCPK.BaseStream.Position % 0x800) > 0 && i < entries.Count - 1)
{
long cur_pos = newCPK.BaseStream.Position;
for (int j = 0; j < (0x800 - (cur_pos % 0x800)); j++)
{
newCPK.Write((byte)0);
}
}
}
else
{
string replace_with = batch_file_list[currentName.ToString()];
//Got patch file name
Console.WriteLine("Patching: {0}", currentName.ToString());
byte[] newbie = File.ReadAllBytes(replace_with);
entries[i].FileOffset = (ulong)newCPK.BaseStream.Position;
int o_ext_size = Int32.Parse((entries[i].ExtractSize).ToString());
int o_com_size = Int32.Parse((entries[i].FileSize).ToString());
if ((o_com_size < o_ext_size) && entries[i].FileType == "FILE" && bUseCompress == true)
{
// is compressed
Console.Write("Compressing data:{0:x8}", newbie.Length);
byte[] dest_comp = cpk.CompressCRILAYLA(newbie);
entries[i].FileSize = Convert.ChangeType(dest_comp.Length, entries[i].FileSizeType);
entries[i].ExtractSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType);
cpk.UpdateFileEntry(entries[i]);
newCPK.Write(dest_comp);
Console.Write(">> {0:x8}\r\n", dest_comp.Length);
}
else
{
Console.Write("Storing data:{0:x8}\r\n", newbie.Length);
entries[i].FileSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType);
entries[i].ExtractSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType);
cpk.UpdateFileEntry(entries[i]);
newCPK.Write(newbie);
}
if ((newCPK.BaseStream.Position % 0x800) > 0 && i < entries.Count - 1)
{
long cur_pos = newCPK.BaseStream.Position;
for (int j = 0; j < (0x800 - (cur_pos % 0x800)); j++)
{
newCPK.Write((byte)0);
}
}
}
}
else
{
// Content is special.... just update the position
cpk.UpdateFileEntry(entries[i]);
}
}
cpk.WriteCPK(newCPK);
cpk.WriteITOC(newCPK);
cpk.WriteTOC(newCPK);
cpk.WriteETOC(newCPK, cpk.EtocOffset);
cpk.WriteGTOC(newCPK);
newCPK.Close();
oldFile.Close();
}
else
{
string ins_name = replaceMe;
string replace_with = replaceWith;
FileInfo fi = new FileInfo(cpk_name);
string outputName = outFile;
BinaryWriter newCPK = new BinaryWriter(File.OpenWrite(outputName));
List<FileEntry> entries = cpk.FileTable.OrderBy(x => x.FileOffset).ToList();
for (int i = 0; i < entries.Count; i++)
{
if (entries[i].FileType != "CONTENT")
{
if (entries[i].FileType == "FILE")
{
// I'm too lazy to figure out how to update the ContextOffset position so this works :)
if ((ulong)newCPK.BaseStream.Position < cpk.ContentOffset)
{
ulong padLength = cpk.ContentOffset - (ulong)newCPK.BaseStream.Position;
for (ulong z = 0; z < padLength; z++)
{
newCPK.Write((byte)0);
}
}
}
if (entries[i].FileName.ToString() != ins_name)
{
oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin);
Console.WriteLine("{0},{1}", entries[i].FileName, entries[i].FileType);
entries[i].FileOffset = (ulong)newCPK.BaseStream.Position;
cpk.UpdateFileEntry(entries[i]);
byte[] chunk = oldFile.ReadBytes(Int32.Parse(entries[i].FileSize.ToString()));
newCPK.Write(chunk);
if ((newCPK.BaseStream.Position % 0x800) > 0 && i < entries.Count - 1)
{
long cur_pos = newCPK.BaseStream.Position;
for (int j = 0; j < (0x800 - (cur_pos % 0x800)); j++)
{
newCPK.Write((byte)0);
}
}
}
else
{
//Got patch file name
Console.WriteLine("{0} Patched.", entries[i].FileName.ToString());
byte[] newbie = File.ReadAllBytes(replace_with);
entries[i].FileOffset = (ulong)newCPK.BaseStream.Position;
int o_ext_size = Int32.Parse((entries[i].ExtractSize).ToString());
int o_com_size = Int32.Parse((entries[i].FileSize).ToString());
if ((o_com_size < o_ext_size) && entries[i].FileType == "FILE" && bUseCompress == true)
{
// is compressed
byte[] dest_comp = cpk.CompressCRILAYLA(newbie);
entries[i].FileSize = Convert.ChangeType(dest_comp.Length, entries[i].FileSizeType);
entries[i].ExtractSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType);
cpk.UpdateFileEntry(entries[i]);
newCPK.Write(dest_comp);
Console.WriteLine("Compressing {0:x8} >> {1:x8}", newbie.Length, dest_comp.Length);
}
else
{
entries[i].FileSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType);
entries[i].ExtractSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType);
cpk.UpdateFileEntry(entries[i]);
newCPK.Write(newbie);
}
if ((newCPK.BaseStream.Position % 0x800) > 0 && i < entries.Count - 1)
{
long cur_pos = newCPK.BaseStream.Position;
for (int j = 0; j < (0x800 - (cur_pos % 0x800)); j++)
{
newCPK.Write((byte)0);
}
}
}
}
else
{
Console.WriteLine("{0},{1}", entries[i].FileName, entries[i].FileType);
// Content is special.... just update the position
cpk.UpdateFileEntry(entries[i]);
}
}
cpk.WriteCPK(newCPK);
cpk.WriteITOC(newCPK);
cpk.WriteTOC(newCPK);
cpk.WriteETOC(newCPK , cpk.EtocOffset);
cpk.WriteGTOC(newCPK);
newCPK.Close();
oldFile.Close();
}
}
}
}

3
CriPakTools/app.config Normal file
View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>

1492
LibCPK/CPK.cs Normal file

File diff suppressed because it is too large Load Diff

188
LibCPK/Endian.cs Normal file
View File

@ -0,0 +1,188 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace LibCPK
{
public class EndianReader : BinaryReader
{
private bool isLittleEndian;
private byte[] buffer = new byte[8];
public EndianReader(Stream input, Encoding encoding, bool isLittleEndian)
: base(input, encoding)
{
this.isLittleEndian = isLittleEndian;
}
public EndianReader(Stream input, bool isLittleEndian)
: this(input, Encoding.UTF8, isLittleEndian)
{
}
public bool IsLittleEndian
{
get { return isLittleEndian; }
set { isLittleEndian = value; }
}
public override double ReadDouble()
{
if (isLittleEndian)
return base.ReadDouble();
FillMyBuffer(8);
return BitConverter.ToDouble(buffer.Take(8).Reverse().ToArray(), 0);
}
public override short ReadInt16()
{
if (isLittleEndian)
return base.ReadInt16();
FillMyBuffer(2);
return BitConverter.ToInt16(buffer.Take(2).Reverse().ToArray(), 0);
}
public override int ReadInt32()
{
if (isLittleEndian)
return base.ReadInt32();
FillMyBuffer(4);
return BitConverter.ToInt32(buffer.Take(4).Reverse().ToArray(), 0);
}
public override long ReadInt64()
{
if (isLittleEndian)
return base.ReadInt64();
FillMyBuffer(8);
return BitConverter.ToInt64(buffer.Take(8).Reverse().ToArray(), 0);
}
public override float ReadSingle()
{
if (isLittleEndian)
return base.ReadSingle();
FillMyBuffer(4);
return BitConverter.ToSingle(buffer.Take(4).Reverse().ToArray(), 0);
}
public override ushort ReadUInt16()
{
if (isLittleEndian)
return base.ReadUInt16();
FillMyBuffer(2);
return BitConverter.ToUInt16(buffer.Take(2).Reverse().ToArray(), 0);
}
public override uint ReadUInt32()
{
if (isLittleEndian)
return base.ReadUInt32();
FillMyBuffer(4);
return BitConverter.ToUInt32(buffer.Take(4).Reverse().ToArray(), 0);
}
public override ulong ReadUInt64()
{
if (isLittleEndian)
return base.ReadUInt64();
FillMyBuffer(8);
return BitConverter.ToUInt64(buffer.Take(8).Reverse().ToArray(), 0);
}
private void FillMyBuffer(int numBytes)
{
int offset = 0;
int num2 = 0;
if (numBytes == 1)
{
num2 = BaseStream.ReadByte();
if (num2 == -1)
{
throw new EndOfStreamException("Attempted to read past the end of the stream.");
}
buffer[0] = (byte)num2;
}
else
{
do
{
num2 = BaseStream.Read(buffer, offset, numBytes - offset);
if (num2 == 0)
{
throw new EndOfStreamException("Attempted to read past the end of the stream.");
}
offset += num2;
}
while (offset < numBytes);
}
}
}
public class EndianWriter : BinaryWriter
{
private bool isLittleEndian;
public EndianWriter(Stream input, Encoding encoding, bool isLittleEndian)
: base(input, encoding)
{
this.isLittleEndian = isLittleEndian;
}
public EndianWriter(Stream input, bool isLittleEndian)
: this(input, Encoding.UTF8, isLittleEndian)
{
}
public bool IsLittleEndian
{
get { return isLittleEndian; }
set { isLittleEndian = value; }
}
public void Write<T>(T value)
{
dynamic input = value;
byte[] someBytes = BitConverter.GetBytes(input);
if (!isLittleEndian)
someBytes = someBytes.Reverse().ToArray();
base.Write(someBytes);
}
public void Write(FileEntry entry)
{
if (entry.ExtractSizeType == typeof(Byte))
{
Write((Byte)entry.ExtractSize);
}
else if (entry.ExtractSizeType == typeof(UInt16))
{
Write((UInt16)entry.ExtractSize);
}
else if (entry.ExtractSizeType == typeof(UInt32))
{
Write((UInt32)entry.ExtractSize);
}
else if (entry.ExtractSizeType == typeof(UInt64))
{
Write((UInt64)entry.ExtractSize);
}
else if (entry.ExtractSizeType == typeof(Single))
{
Write((Single)entry.ExtractSize);
}
else
{
throw new Exception("Not supported type!");
}
}
}
}

68
LibCPK/LibCPK.csproj Normal file
View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{BA3A00E4-4F51-4AB4-A8FB-F4B64A874449}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>LibCPK</RootNamespace>
<AssemblyName>LibCPK</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>3</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CPK.cs" />
<Compile Include="Endian.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Tools.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LibCRIComp\LibCRIComp.vcxproj">
<Project>{e5829a5b-e121-41aa-a84b-e7b4c8dbdf30}</Project>
<Name>LibCRIComp</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的常规信息通过以下
// 特性集控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("LibCPK")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LibCPK")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 使此程序集中的类型
// 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
// 则将该类型上的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("9423973b-97c7-4805-9f00-539d7b9f7a95")]
// 程序集的版本信息由下面四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
// 方法是按如下所示使用“*”:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

156
LibCPK/Tools.cs Normal file
View File

@ -0,0 +1,156 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
namespace LibCPK
{
public class Tools
{
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int memcmp(byte[] b1, byte[] b2, long count);
public Tools()
{
}
public static bool CheckListRedundant(List<FileEntry> input)
{
bool result = false;
List<string> tmp = new List<string>();
for (int i = 0; i < input.Count; i++)
{
string name = ((input[i].DirName != null) ?
input[i].DirName + "/" : "") + input[i].FileName;
if (!tmp.Contains(name))
{
tmp.Add(name);
}
else
{
result = true;
return result;
}
}
return result;
}
public Dictionary<string, string> ReadBatchScript(string batch_script_name)
{
//---------------------
// TXT内部
// original_file_name(in cpk),patch_file_name(in folder)
// /HD_font_a.ftx,patch/BOOT.cpk_unpacked/HD_font_a.ftx
// OTHER/ICON0.PNG,patch/BOOT.cpk_unpacked/OTHER/ICON0.PNG
Dictionary<string, string> flist = new Dictionary<string, string>();
StreamReader sr = new StreamReader(batch_script_name, Encoding.Default);
String line;
while ((line = sr.ReadLine()) != null)
{
if (line.IndexOf(",") > -1)
//只读取格式正确的行
{
line = line.Replace("\n", "");
line = line.Replace("\r", "");
string[] currentValue = line.Split(',');
flist.Add(currentValue[0], currentValue[1]);
}
}
sr.Close();
return flist;
}
public string ReadCString(BinaryReader br, int MaxLength = -1, long lOffset = -1, Encoding enc = null)
{
int Max;
if (MaxLength == -1)
Max = 255;
else
Max = MaxLength;
long fTemp = br.BaseStream.Position;
byte bTemp = 0;
int i = 0;
string result = "";
if (lOffset > -1)
{
br.BaseStream.Seek(lOffset, SeekOrigin.Begin);
}
do
{
bTemp = br.ReadByte();
if (bTemp == 0)
break;
i += 1;
} while (i < Max);
if (MaxLength == -1)
Max = i + 1;
else
Max = MaxLength;
if (lOffset > -1)
{
br.BaseStream.Seek(lOffset, SeekOrigin.Begin);
if (enc == null)
result = Encoding.UTF8.GetString(br.ReadBytes(i));
else
result = enc.GetString(br.ReadBytes(i));
br.BaseStream.Seek(fTemp, SeekOrigin.Begin);
}
else
{
br.BaseStream.Seek(fTemp, SeekOrigin.Begin);
if (enc == null)
result = Encoding.ASCII.GetString(br.ReadBytes(i));
else
result = enc.GetString(br.ReadBytes(i));
br.BaseStream.Seek(fTemp + Max, SeekOrigin.Begin);
}
return result;
}
public void DeleteFileIfExists(string sPath)
{
if (File.Exists(sPath))
File.Delete(sPath);
}
public string GetPath(string input)
{
return Path.GetDirectoryName(input) + "\\" + Path.GetFileNameWithoutExtension(input);
}
public byte[] GetData(BinaryReader br, long offset, int size)
{
byte[] result = null;
long backup = br.BaseStream.Position;
br.BaseStream.Seek(offset, SeekOrigin.Begin);
result = br.ReadBytes(size);
br.BaseStream.Seek(backup, SeekOrigin.Begin);
return result;
}
public static string GetSafePath(string filename)
{
return string.Join("_", filename.Split(Path.GetInvalidFileNameChars()));
}
}
}

View File

@ -0,0 +1,38 @@
#include "stdafx.h"
using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;
//
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
//
[assembly:AssemblyTitleAttribute(L"LibCRIComp")];
[assembly:AssemblyDescriptionAttribute(L"")];
[assembly:AssemblyConfigurationAttribute(L"")];
[assembly:AssemblyCompanyAttribute(L"")];
[assembly:AssemblyProductAttribute(L"LibCRIComp")];
[assembly:AssemblyCopyrightAttribute(L"Copyright (c) 2017")];
[assembly:AssemblyTrademarkAttribute(L"")];
[assembly:AssemblyCultureAttribute(L"")];
//
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
// 您可以指定所有值,也可以使用“修订号”和“生成号”的默认值,
// 方法是按如下所示使用“*”: :
[assembly:AssemblyVersionAttribute("1.0.*")];
[assembly:ComVisible(false)];
[assembly:CLSCompliantAttribute(true)];

105
LibCRIComp/LibCRIComp.cpp Normal file
View File

@ -0,0 +1,105 @@
// ÕâÊÇÖ÷ DLL Îļþ¡£
#include <windows.h>
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "LibCRIComp.h"
namespace LibCRIComp
{
/*
CRIcompress method by KenTse
*/
int CriCompression::CRIcompress(unsigned char *dest, int *destLen, unsigned char *src, int srcLen)
{
int n = srcLen - 1, m = *destLen - 0x1, T = 0, d = 0, p, q, i, j, k;
unsigned char *odest = dest;
for (; n >= 0x100;)
{
j = n + 3 + 0x2000;
if (j>srcLen) j = srcLen;
for (i = n + 3, p = 0; i<j; i++)
{
for (k = 0; k <= n - 0x100; k++)
{
if (*(src + n - k) != *(src + i - k)) break;
}
if (k>p)
{
q = i - n - 3; p = k;
}
}
if (p<3)
{
d = (d << 9) | (*(src + n--)); T += 9;
}
else
{
d = (((d << 1) | 1) << 13) | q; T += 14; n -= p;
if (p<6)
{
d = (d << 2) | (p - 3); T += 2;
}
else if (p<13)
{
d = (((d << 2) | 3) << 3) | (p - 6); T += 5;
}
else if (p<44)
{
d = (((d << 5) | 0x1f) << 5) | (p - 13); T += 10;
}
else
{
d = ((d << 10) | 0x3ff); T += 10; p -= 44;
for (;;)
{
for (; T >= 8;)
{
*(dest + m--) = (d >> (T - 8)) & 0xff; T -= 8; d = d&((1 << T) - 1);
}
if (p<255) break;
d = (d << 8) | 0xff; T += 8; p = p - 0xff;
}
d = (d << 8) | p; T += 8;
}
}
for (; T >= 8;)
{
*(dest + m--) = (d >> (T - 8)) & 0xff; T -= 8; d = d&((1 << T) - 1);
}
}
if (T != 0)
{
*(dest + m--) = d << (8 - T);
}
*(dest + m--) = 0; *(dest + m) = 0;
for (;;)
{
if (((*destLen - m) & 3) == 0) break;
*(dest + m--) = 0;
}
*destLen = *destLen - m; dest += m;
int l[] = { 0x4c495243,0x414c5941,srcLen - 0x100,*destLen };
for (j = 0; j<4; j++)
{
for (i = 0; i<4; i++)
{
*(odest + i + j * 4) = l[j] & 0xff; l[j] >>= 8;
}
}
for (j = 0, odest += 0x10; j<*destLen; j++)
{
*(odest++) = *(dest + j);
}
for (j = 0; j<0x100; j++)
{
*(odest++) = *(src + j);
}
*destLen += 0x110;
return *destLen;
}
}

13
LibCRIComp/LibCRIComp.h Normal file
View File

@ -0,0 +1,13 @@
// LibCRIComp.h
#pragma once
using namespace System;
namespace LibCRIComp {
public ref class CriCompression
{
public:static int CRIcompress(unsigned char *dest, int *destLen, unsigned char *src, int srcLen);
};
}

View File

@ -0,0 +1,162 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{E5829A5B-E121-41AA-A84B-E7B4C8DBDF30}</ProjectGuid>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<Keyword>ManagedCProj</Keyword>
<RootNamespace>LibCRIComp</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalDependencies />
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalDependencies />
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalDependencies />
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalDependencies />
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="LibCRIComp.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="Stdafx.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AssemblyInfo.cpp" />
<ClCompile Include="LibCRIComp.cpp" />
<ClCompile Include="Stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="app.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="app.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="LibCRIComp.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="Stdafx.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="LibCRIComp.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="AssemblyInfo.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Stdafx.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="app.rc">
<Filter>资源文件</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="app.ico">
<Filter>资源文件</Filter>
</Image>
</ItemGroup>
</Project>

5
LibCRIComp/Stdafx.cpp Normal file
View File

@ -0,0 +1,5 @@
// stdafx.cpp : 只包括标准包含文件的源文件
// LibCRIComp.pch 将作为预编译头
// stdafx.obj 将包含预编译类型信息
#include "stdafx.h"

7
LibCRIComp/Stdafx.h Normal file
View File

@ -0,0 +1,7 @@
// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
#pragma once

BIN
LibCRIComp/app.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
LibCRIComp/app.rc Normal file

Binary file not shown.

3
LibCRIComp/resource.h Normal file
View File

@ -0,0 +1,3 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by app.rc

44
README.md Normal file
View File

@ -0,0 +1,44 @@
CriPakTools-mod
基于 uyjulian/CriPakTools 的派生版本
该工具基于 Falo、Nanashi3、esperknight 和 uyjulian 的代码开发。
我对其进行了派生,并添加了批量重新导入和压缩功能。
感谢 KenTse 提供的 CRILAYLA 压缩方法。
添加批处理模式
添加压缩选项
修复 GTOC 和 ETOC
修复 CPK 头信息
仍需完成的事项:
添加图形用户界面 (GUI)
===========
该工具用于提取/更新 CRIWARE 的 CPK 存档格式内容(也称为 CRI FileMajik
此工具基于 Falo 在 Xentax 论坛上发布的代码http://forum.xentax.com/viewtopic.php?f=10&t=10646该代码经过 Nanashi3 修改http://forums.fuwanovel.org/index.php?/topic/1785-request-for-psp-hackers/page-4然后再次由 esperknight 修改https://github.com/esperknight/CriPakTools
我清理了命令行标志,并使其能够提取 0 字节的 CRILAYLA 压缩文件。
如果发生任何问题,请提交 issue。
要查看选项,请使用 CriPackTools -h。
编译
切换到 CriPakTools.sln 文件所在的目录,如果你使用 Mono请运行 xbuild。编译后文件应位于 CriPakTools/bin/CriPackTools.exe。
如果没有 Mono可以直接在 Visual Studio 2013 中打开 CriPakTools.sln 文件并进行构建。
TODO
添加更多的错误检查
清理代码
添加创建存档的选项