mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-23 11:24:14 +08:00
Initial commit.
This commit is contained in:
commit
e208029dd3
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
bin
|
||||
obj
|
||||
tags
|
||||
*.exe
|
||||
*.suo
|
||||
*;*
|
100
AboutBox.xaml
Normal file
100
AboutBox.xaml
Normal file
@ -0,0 +1,100 @@
|
||||
<!-- Game Resource browser
|
||||
|
||||
Copyright (C) 2014 by morkt
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
-->
|
||||
<w:ModalWindow x:Class="GARbro.GUI.AboutBox"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:GARbro.GUI"
|
||||
xmlns:w="clr-namespace:Rnd.Windows"
|
||||
xmlns:s="clr-namespace:GARbro.GUI.Strings"
|
||||
Title="{x:Static s:guiStrings.TextAboutTitle}" Height="306" Width="475" ResizeMode="NoResize"
|
||||
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
|
||||
ShowInTaskbar="False" WindowStartupLocation="CenterOwner">
|
||||
<Window.Resources>
|
||||
<local:BooleanToVisibiltyConverter x:Key="guiBoolToVisibilityConverter" />
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="43*" />
|
||||
<ColumnDefinition Width="74*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Grid.Column="0" Grid.Row="0" Grid.RowSpan="4" Margin="10,10,10,67.304"
|
||||
DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:AboutBox}}}">
|
||||
<Label Content="{Binding Path=AssemblyTitle, Mode=OneWay}" />
|
||||
<Label Content="{Binding Path=VersionString, Mode=OneWay}" />
|
||||
<Label Content="{Binding Path=AssemblyCopyright, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
<Button Grid.Row="3" VerticalAlignment="Bottom" HorizontalAlignment="Left" IsDefault="true"
|
||||
Content="{x:Static s:guiStrings.ButtonOK}" Margin="10,0,0,10" Width="70" Click="Button_Click" IsCancel="True" Height="21"/>
|
||||
<Grid Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" Margin="10,8,10,6">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Text="{x:Static s:guiStrings.TextAboutSupportedArchives}" Grid.Row="0" Margin="0" />
|
||||
<Border Grid.Row="1" BorderThickness="1" BorderBrush="Black" VerticalAlignment="Stretch" Margin="0" SnapsToDevicePixels="True">
|
||||
<ScrollViewer Grid.Row="1" Margin="0" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled"
|
||||
Background="{DynamicResource {x:Static SystemColors.ControlLightLightBrushKey}}"
|
||||
BorderThickness="1" BorderBrush="Black">
|
||||
<ItemsControl Name="ArchiveFormats">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding Tag}" Margin="3,0,5,0" />
|
||||
<TextBlock Text="{Binding Description}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Grid>
|
||||
<Grid Grid.Column="1" Grid.Row="2" Grid.RowSpan="2" Margin="10,2,10,10">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" Text="{x:Static s:guiStrings.TextAboutSupportedImages}" Margin="0" />
|
||||
<Border Grid.Row="1" BorderThickness="1" BorderBrush="Black" VerticalAlignment="Stretch" Margin="0" SnapsToDevicePixels="True">
|
||||
<ScrollViewer VerticalAlignment="Stretch" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Margin="0" Background="{DynamicResource {x:Static SystemColors.ControlLightLightBrushKey}}" BorderThickness="1" BorderBrush="Black">
|
||||
<ItemsControl Name="ImageFormats">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding Tag}" Margin="3,0,5,0" />
|
||||
<TextBlock Text="{x:Static s:guiStrings.TextAboutBuiltin}" Margin="0,0,5,0" Visibility="{Binding IsBuiltin, Converter={StaticResource guiBoolToVisibilityConverter}}"/>
|
||||
<TextBlock Text="{Binding Description}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</w:ModalWindow>
|
213
AboutBox.xaml.cs
Normal file
213
AboutBox.xaml.cs
Normal file
@ -0,0 +1,213 @@
|
||||
/// Game Resource browser
|
||||
//
|
||||
// Copyright (C) 2014 by morkt
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using GARbro.GUI.Properties;
|
||||
using GARbro.GUI.Strings;
|
||||
|
||||
namespace GARbro.GUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for AboutBox.xaml
|
||||
/// </summary>
|
||||
public partial class AboutBox : Rnd.Windows.ModalWindow
|
||||
{
|
||||
public AboutBox()
|
||||
{
|
||||
InitializeComponent();
|
||||
ArchiveFormats.ItemsSource = GameRes.FormatCatalog.Instance.ArcFormats;
|
||||
ImageFormats.ItemsSource = GameRes.FormatCatalog.Instance.ImageFormats;
|
||||
}
|
||||
|
||||
private void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
#region Assembly Attribute Accessors
|
||||
|
||||
public string AssemblyTitle
|
||||
{
|
||||
get
|
||||
{
|
||||
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
|
||||
if (attributes.Length > 0)
|
||||
{
|
||||
AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
|
||||
if (titleAttribute.Title != "")
|
||||
{
|
||||
return titleAttribute.Title;
|
||||
}
|
||||
}
|
||||
return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
|
||||
}
|
||||
}
|
||||
|
||||
public string VersionString
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Format (guiStrings.MsgVersion, AssemblyVersion);
|
||||
}
|
||||
}
|
||||
|
||||
public string AssemblyVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public string AssemblyDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
|
||||
if (attributes.Length == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return ((AssemblyDescriptionAttribute)attributes[0]).Description;
|
||||
}
|
||||
}
|
||||
|
||||
public string AssemblyProduct
|
||||
{
|
||||
get
|
||||
{
|
||||
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
|
||||
if (attributes.Length == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return ((AssemblyProductAttribute)attributes[0]).Product;
|
||||
}
|
||||
}
|
||||
|
||||
public string AssemblyCopyright
|
||||
{
|
||||
get
|
||||
{
|
||||
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
|
||||
if (attributes.Length == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
|
||||
}
|
||||
}
|
||||
|
||||
public string AssemblyCompany
|
||||
{
|
||||
get
|
||||
{
|
||||
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
|
||||
if (attributes.Length == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return ((AssemblyCompanyAttribute)attributes[0]).Company;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class BooleanToVisibiltyConverter : IValueConverter
|
||||
{
|
||||
/// <summary>Convert a boolean value to a Visibility value</summary>
|
||||
public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
bool isVisible = (bool)value;
|
||||
|
||||
// If visibility is inverted by the converter parameter, then invert our value
|
||||
if (IsVisibilityInverted (parameter))
|
||||
isVisible = !isVisible;
|
||||
|
||||
return (isVisible ? Visibility.Visible : Visibility.Collapsed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine the visibility mode based on a converter parameter. This parameter is
|
||||
/// of type Visibility, and specifies what visibility value to return when the boolean
|
||||
/// value is true.
|
||||
/// </summary>
|
||||
private static Visibility GetVisibilityMode(object parameter)
|
||||
{
|
||||
// Default to Visible
|
||||
Visibility mode = Visibility.Visible;
|
||||
|
||||
// If a parameter is specified, then we'll try to understand it as a Visibility value
|
||||
if (parameter != null)
|
||||
{
|
||||
// If it's already a Visibility value, then just use it
|
||||
if (parameter is Visibility)
|
||||
{
|
||||
mode = (Visibility)parameter;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Let's try to parse the parameter as a Visibility value, throwing an exception when the parsing fails
|
||||
try
|
||||
{
|
||||
mode = (Visibility)Enum.Parse(typeof(Visibility), parameter.ToString(), true);
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
throw new FormatException("Invalid Visibility specified as the ConverterParameter. Use Visible or Collapsed.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the detected mode
|
||||
return mode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether or not visibility is inverted based on a converter parameter.
|
||||
/// When the parameter is specified as Collapsed, that means that when the boolean value
|
||||
/// is true, we should return Collapsed, which is inverted.
|
||||
/// </summary>
|
||||
private static bool IsVisibilityInverted(object parameter)
|
||||
{
|
||||
return (GetVisibilityMode(parameter) == Visibility.Collapsed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Support 2-way databinding of the VisibilityConverter, converting Visibility to a boolean
|
||||
/// </summary>
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
bool isVisible = ((Visibility)value == Visibility.Visible);
|
||||
|
||||
// If visibility is inverted by the converter parameter, then invert our value
|
||||
if (IsVisibilityInverted(parameter))
|
||||
isVisible = !isVisible;
|
||||
|
||||
return isVisible;
|
||||
}
|
||||
}
|
||||
}
|
73
App.config
Normal file
73
App.config
Normal file
@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<section name="GARbro.GUI.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<system.diagnostics>
|
||||
<trace autoflush="true">
|
||||
<listeners>
|
||||
<add type="System.Diagnostics.TextWriterTraceListener" name="TextWriter" initializeData="trace.log"/>
|
||||
</listeners>
|
||||
</trace>
|
||||
</system.diagnostics>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/>
|
||||
</startup>
|
||||
<userSettings>
|
||||
<GARbro.GUI.Properties.Settings>
|
||||
<setting name="UpgradeRequired" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="winTop" serializeAs="String">
|
||||
<value>NaN</value>
|
||||
</setting>
|
||||
<setting name="winLeft" serializeAs="String">
|
||||
<value>NaN</value>
|
||||
</setting>
|
||||
<setting name="winWidth" serializeAs="String">
|
||||
<value>1024</value>
|
||||
</setting>
|
||||
<setting name="winHeight" serializeAs="String">
|
||||
<value>560</value>
|
||||
</setting>
|
||||
<setting name="winState" serializeAs="String">
|
||||
<value>Normal</value>
|
||||
</setting>
|
||||
<setting name="lvNameColumnWidth" serializeAs="String">
|
||||
<value>265</value>
|
||||
</setting>
|
||||
<setting name="lvTypeColumnWidth" serializeAs="String">
|
||||
<value>75</value>
|
||||
</setting>
|
||||
<setting name="lvSizeColumnWidth" serializeAs="String">
|
||||
<value>75</value>
|
||||
</setting>
|
||||
<setting name="lvSortColumn" serializeAs="String">
|
||||
<value>Name</value>
|
||||
</setting>
|
||||
<setting name="lvSortDirection" serializeAs="String">
|
||||
<value>Ascending</value>
|
||||
</setting>
|
||||
<setting name="lvPanelWidth" serializeAs="String">
|
||||
<value>448</value>
|
||||
</setting>
|
||||
<setting name="appExtractImages" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="appExtractText" serializeAs="String">
|
||||
<value>True</value>
|
||||
</setting>
|
||||
<setting name="appImageFormat" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="appTextEncoding" serializeAs="String">
|
||||
<value>UTF-8</value>
|
||||
</setting>
|
||||
<setting name="appLastDirectory" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
</GARbro.GUI.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
9
App.xaml
Normal file
9
App.xaml
Normal file
@ -0,0 +1,9 @@
|
||||
<Application x:Class="GARbro.GUI.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
StartupUri="MainWindow.xaml" Startup="ApplicationStartup"
|
||||
ShutdownMode="OnMainWindowClose" Exit="ApplicationExit">
|
||||
<Application.Resources>
|
||||
<BitmapImage x:Key="IconSearch" UriSource="pack://application:,,,/Images/search4files.ico" />
|
||||
</Application.Resources>
|
||||
</Application>
|
174
App.xaml.cs
Normal file
174
App.xaml.cs
Normal file
@ -0,0 +1,174 @@
|
||||
// Game Resource Browser
|
||||
//
|
||||
// Copyright (C) 2014 by morkt
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Configuration;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using System.Reflection;
|
||||
using System.Diagnostics;
|
||||
using GARbro.GUI.Strings;
|
||||
using GARbro.GUI.Properties;
|
||||
using GameRes;
|
||||
|
||||
namespace GARbro.GUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
const StringComparison StringIgnoreCase = StringComparison.OrdinalIgnoreCase;
|
||||
|
||||
public static string Name { get { return "GARbro"; } }
|
||||
|
||||
public string InitPath { get; private set; }
|
||||
public string CurrentPath { get; private set; }
|
||||
public ArcFile CurrentArchive { get; private set; }
|
||||
|
||||
void ApplicationStartup (object sender, StartupEventArgs e)
|
||||
{
|
||||
Trace.WriteLine ("ApplicationStartup --------------------------------", "GARbro.GUI.App");
|
||||
if (0 != e.Args.Length)
|
||||
{
|
||||
InitPath = Path.GetFullPath (e.Args[0]);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty (Settings.Default.appLastDirectory))
|
||||
{
|
||||
try
|
||||
{
|
||||
string last_dir = Settings.Default.appLastDirectory;
|
||||
Directory.SetCurrentDirectory (last_dir);
|
||||
InitPath = last_dir;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty (InitPath))
|
||||
InitPath = Directory.GetCurrentDirectory();
|
||||
|
||||
CurrentPath = "";
|
||||
}
|
||||
|
||||
void ApplicationExit (object sender, ExitEventArgs e)
|
||||
{
|
||||
Settings.Default.appLastDirectory = Directory.GetCurrentDirectory();
|
||||
Settings.Default.Save();
|
||||
}
|
||||
|
||||
public ICollection<Entry> GetDirectoryList (string path)
|
||||
{
|
||||
var info = new DirectoryInfo (path);
|
||||
var list = new List<Entry>();
|
||||
foreach (var subdir in info.EnumerateDirectories())
|
||||
{
|
||||
if (0 != (subdir.Attributes & (FileAttributes.Hidden | FileAttributes.System)))
|
||||
continue;
|
||||
list.Add (new SubDirEntry (subdir.Name));
|
||||
}
|
||||
foreach (var file in info.EnumerateFiles())
|
||||
{
|
||||
if (0 != (file.Attributes & (FileAttributes.Hidden | FileAttributes.System)))
|
||||
continue;
|
||||
var entry = FormatCatalog.Instance.CreateEntry (file.Name);
|
||||
entry.Size = (uint)Math.Min (file.Length, uint.MaxValue);
|
||||
list.Add (entry);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public ArcFile GetArchive (string path)
|
||||
{
|
||||
if (path.Equals (CurrentPath, StringIgnoreCase))
|
||||
return CurrentArchive;
|
||||
FormatCatalog.Instance.LastError = null;
|
||||
var arc = ArcFile.TryOpen (path);
|
||||
if (null == arc)
|
||||
{
|
||||
if (null != FormatCatalog.Instance.LastError)
|
||||
throw FormatCatalog.Instance.LastError;
|
||||
throw new UnknownFormatException();
|
||||
}
|
||||
if (null != CurrentArchive)
|
||||
CurrentArchive.Dispose();
|
||||
CurrentPath = path;
|
||||
CurrentArchive = arc;
|
||||
return CurrentArchive;
|
||||
}
|
||||
|
||||
public void ResetCache ()
|
||||
{
|
||||
if (null != CurrentArchive)
|
||||
CurrentArchive.Dispose();
|
||||
CurrentArchive = null;
|
||||
CurrentPath = "";
|
||||
}
|
||||
|
||||
// Update UI on demand.
|
||||
|
||||
private static DispatcherOperationCallback exitFrameCallback =
|
||||
new DispatcherOperationCallback(ExitFrame);
|
||||
|
||||
/// <summary>
|
||||
/// Processes all UI messages currently in the message queue.
|
||||
/// </summary>
|
||||
public static void DoEvents()
|
||||
{
|
||||
// Create new nested message pump.
|
||||
DispatcherFrame nestedFrame = new DispatcherFrame();
|
||||
|
||||
// Dispatch a callback to the current message queue, when getting called,
|
||||
// this callback will end the nested message loop.
|
||||
// note that the priority of this callback should be lower than the that of UI event messages.
|
||||
DispatcherOperation exitOperation = Dispatcher.CurrentDispatcher.BeginInvoke(
|
||||
DispatcherPriority.Background, exitFrameCallback, nestedFrame);
|
||||
|
||||
// pump the nested message loop, the nested message loop will
|
||||
// immediately process the messages left inside the message queue.
|
||||
Dispatcher.PushFrame(nestedFrame);
|
||||
|
||||
// If the "exitFrame" callback doesn't get finished, Abort it.
|
||||
if (exitOperation.Status != DispatcherOperationStatus.Completed)
|
||||
exitOperation.Abort();
|
||||
}
|
||||
|
||||
static Object ExitFrame(Object state)
|
||||
{
|
||||
DispatcherFrame frame = state as DispatcherFrame;
|
||||
|
||||
// Exit the nested message loop.
|
||||
frame.Continue = false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class UnknownFormatException : Exception
|
||||
{
|
||||
public UnknownFormatException () : base (guiStrings.MsgUnknownFormat) { }
|
||||
public UnknownFormatException (string path)
|
||||
: base (string.Format ("{1}: {0}", guiStrings.MsgUnknownFormat, path))
|
||||
{ }
|
||||
}
|
||||
}
|
284
ArcFormats/ArcAMI.cs
Normal file
284
ArcFormats/ArcAMI.cs
Normal file
@ -0,0 +1,284 @@
|
||||
//! \file ArcAMI.cs
|
||||
//! \date Thu Jul 03 09:40:40 2014
|
||||
//! \brief Muv-Luv Amaterasu Translation archive.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using ZLibNet;
|
||||
|
||||
namespace GameRes.Formats
|
||||
{
|
||||
public class AmiEntry : PackedEntry
|
||||
{
|
||||
private Lazy<Tuple<string,string>> m_item;
|
||||
public override string Name
|
||||
{
|
||||
get { return m_item.Value.Item1; }
|
||||
set { m_item = new Lazy<Tuple<string, string>>(() => new Tuple<string, string>(value, Type)); }
|
||||
}
|
||||
public override string Type
|
||||
{
|
||||
get { return m_item.Value.Item2; }
|
||||
set { m_item = new Lazy<Tuple<string, string>>(() => new Tuple<string, string>(Name, value)); }
|
||||
}
|
||||
|
||||
public AmiEntry (Func<Tuple<string, string>> factory)
|
||||
{
|
||||
m_item = new Lazy<Tuple<string, string>> (factory);
|
||||
}
|
||||
}
|
||||
|
||||
[Export(typeof(ArchiveFormat))]
|
||||
public class AmiOpener : ArchiveFormat
|
||||
{
|
||||
public override string Tag { get { return "AMI"; } }
|
||||
public override string Description { get { return "Amaterasu Translations Muv-Luv archive"; } }
|
||||
public override uint Signature { get { return 0x00494d41; } }
|
||||
|
||||
public AmiOpener ()
|
||||
{
|
||||
Extensions = new string[] { "ami", "amr" };
|
||||
}
|
||||
|
||||
public override ArcFile TryOpen (ArcView file)
|
||||
{
|
||||
int count = file.View.ReadInt32 (4);
|
||||
if (count <= 0)
|
||||
return null;
|
||||
uint base_offset = file.View.ReadUInt32 (8);
|
||||
long max_offset = file.MaxOffset;
|
||||
if (base_offset >= max_offset)
|
||||
return null;
|
||||
|
||||
uint cur_offset = 16;
|
||||
var dir = new List<Entry> (count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
if (cur_offset+16 > base_offset)
|
||||
return null;
|
||||
uint id = file.View.ReadUInt32 (cur_offset);
|
||||
uint offset = file.View.ReadUInt32 (cur_offset+4);
|
||||
uint size = file.View.ReadUInt32 (cur_offset+8);
|
||||
uint packed_size = file.View.ReadUInt32 (cur_offset+12);
|
||||
|
||||
var entry = new AmiEntry (() => {
|
||||
uint signature = file.View.ReadUInt32 (offset);
|
||||
string ext, type;
|
||||
if (0x00524353 == signature) {
|
||||
ext = "scr"; type = "script";
|
||||
} else if (0 != packed_size) {
|
||||
ext = "grp"; type = "image";
|
||||
} else {
|
||||
ext = "dat"; type = "";
|
||||
}
|
||||
string name = string.Format ("{0:x8}.{1}", id, ext);
|
||||
return new Tuple<string,string> (name, type);
|
||||
});
|
||||
|
||||
entry.Offset = offset;
|
||||
entry.UnpackedSize = size;
|
||||
entry.IsPacked = 0 != packed_size;
|
||||
entry.Size = entry.IsPacked ? packed_size : size;
|
||||
if (!entry.CheckPlacement (max_offset))
|
||||
return null;
|
||||
dir.Add (entry);
|
||||
cur_offset += 16;
|
||||
}
|
||||
return new ArcFile (file, this, dir);
|
||||
}
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
{
|
||||
var input = arc.File.CreateStream (entry.Offset, entry.Size);
|
||||
var packed_entry = entry as AmiEntry;
|
||||
if (null == packed_entry || !packed_entry.IsPacked)
|
||||
return input;
|
||||
else
|
||||
return new ZLibStream (input, CompressionMode.Decompress);
|
||||
}
|
||||
}
|
||||
|
||||
[Export(typeof(ImageFormat))]
|
||||
public class GrpFormat : ImageFormat
|
||||
{
|
||||
public override string Tag { get { return "GRP"; } }
|
||||
public override string Description { get { return "âge proprietary image format"; } }
|
||||
public override uint Signature { get { return 0x00505247; } }
|
||||
|
||||
public override ImageMetaData ReadMetaData (Stream stream)
|
||||
{
|
||||
using (var file = new BinaryReader (stream, Encoding.ASCII, true))
|
||||
{
|
||||
if (file.ReadUInt32() != Signature)
|
||||
return null;
|
||||
var meta = new ImageMetaData();
|
||||
meta.OffsetX = file.ReadInt16();
|
||||
meta.OffsetY = file.ReadInt16();
|
||||
meta.Width = file.ReadUInt16();
|
||||
meta.Height = file.ReadUInt16();
|
||||
meta.BPP = 32;
|
||||
stream.Position = 0;
|
||||
return meta;
|
||||
}
|
||||
}
|
||||
|
||||
public override ImageData Read (Stream file, ImageMetaData info)
|
||||
{
|
||||
int width = (int)info.Width;
|
||||
int height = (int)info.Height;
|
||||
int stride = width*4;
|
||||
byte[] pixels = new byte[stride*height];
|
||||
file.Position = 12;
|
||||
for (int row = height-1; row >= 0; --row)
|
||||
{
|
||||
if (stride != file.Read (pixels, row*stride, stride))
|
||||
throw new InvalidFormatException();
|
||||
}
|
||||
var bitmap = BitmapSource.Create (width, height, 96, 96,
|
||||
PixelFormats.Bgra32, null, pixels, stride);
|
||||
bitmap.Freeze();
|
||||
|
||||
return new ImageData (bitmap, info);
|
||||
}
|
||||
|
||||
public override void Write (Stream stream, ImageData image)
|
||||
{
|
||||
using (var file = new BinaryWriter (stream, Encoding.ASCII, true))
|
||||
{
|
||||
file.Write (Signature);
|
||||
file.Write ((short)image.OffsetX);
|
||||
file.Write ((short)image.OffsetY);
|
||||
file.Write ((ushort)image.Width);
|
||||
file.Write ((ushort)image.Height);
|
||||
|
||||
var bitmap = image.Bitmap;
|
||||
if (bitmap.Format != PixelFormats.Bgra32)
|
||||
{
|
||||
var converted_bitmap = new FormatConvertedBitmap();
|
||||
converted_bitmap.BeginInit();
|
||||
converted_bitmap.Source = image.Bitmap;
|
||||
converted_bitmap.DestinationFormat = PixelFormats.Bgra32;
|
||||
converted_bitmap.EndInit();
|
||||
bitmap = converted_bitmap;
|
||||
}
|
||||
int stride = (int)image.Width * 4;
|
||||
byte[] row_data = new byte[stride];
|
||||
Int32Rect rect = new Int32Rect (0, (int)image.Height, (int)image.Width, 1);
|
||||
for (uint row = 0; row < image.Height; ++row)
|
||||
{
|
||||
--rect.Y;
|
||||
bitmap.CopyPixels (rect, row_data, stride, 0);
|
||||
file.Write (row_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class AmiScriptData : ScriptData
|
||||
{
|
||||
public uint Id;
|
||||
public uint Type;
|
||||
}
|
||||
|
||||
[Export(typeof(ScriptFormat))]
|
||||
public class ScrFormat : ScriptFormat
|
||||
{
|
||||
public override string Tag { get { return "SCR"; } }
|
||||
public override string Description { get { return "Amaterasu Translations Muv-Luv script file"; } }
|
||||
public override uint Signature { get { return 0x00524353; } }
|
||||
|
||||
public override ScriptData Read (string name, Stream stream)
|
||||
{
|
||||
if (Signature != FormatCatalog.ReadSignature (stream))
|
||||
return null;
|
||||
uint script_id = Convert.ToUInt32 (name, 16);
|
||||
uint max_offset = (uint)Math.Min (stream.Length, 0xffffffff);
|
||||
|
||||
using (var file = new BinaryReader (stream, Encodings.cp932, true))
|
||||
{
|
||||
uint script_type = file.ReadUInt32();
|
||||
var script = new AmiScriptData {
|
||||
Id = script_id,
|
||||
Type = script_type
|
||||
};
|
||||
uint count = file.ReadUInt32();
|
||||
for (uint i = 0; i < count; ++i)
|
||||
{
|
||||
uint offset = file.ReadUInt32();
|
||||
if (offset >= max_offset)
|
||||
throw new InvalidFormatException ("Invalid offset in script data file");
|
||||
int size = file.ReadInt32();
|
||||
uint id = file.ReadUInt32();
|
||||
var header_pos = file.BaseStream.Position;
|
||||
file.BaseStream.Position = offset;
|
||||
byte[] line = file.ReadBytes (size);
|
||||
if (line.Length != size)
|
||||
throw new InvalidFormatException ("Premature end of file");
|
||||
string text = Encodings.cp932.GetString (line);
|
||||
|
||||
script.TextLines.Add (new ScriptLine { Id = id, Text = text });
|
||||
file.BaseStream.Position = header_pos;
|
||||
}
|
||||
return script;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetName (ScriptData script_data)
|
||||
{
|
||||
var script = script_data as AmiScriptData;
|
||||
if (null != script)
|
||||
return script.Id.ToString ("x8");
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
struct IndexEntry
|
||||
{
|
||||
public uint offset, size, id;
|
||||
}
|
||||
|
||||
public override void Write (Stream stream, ScriptData script_data)
|
||||
{
|
||||
var script = script_data as AmiScriptData;
|
||||
if (null == script)
|
||||
throw new ArgumentException ("Illegal ScriptData", "script_data");
|
||||
using (var file = new BinaryWriter (stream, Encodings.cp932, true))
|
||||
{
|
||||
file.Write (Signature);
|
||||
file.Write (script.Type);
|
||||
uint count = (uint)script.TextLines.Count;
|
||||
file.Write (count);
|
||||
var index_pos = file.BaseStream.Position;
|
||||
file.Seek ((int)count*12, SeekOrigin.Current);
|
||||
var index = new IndexEntry[count];
|
||||
int i = 0;
|
||||
foreach (var line in script.TextLines)
|
||||
{
|
||||
var text = Encodings.cp932.GetBytes (line.Text);
|
||||
index[i].offset = (uint)file.BaseStream.Position;
|
||||
index[i].size = (uint)text.Length;
|
||||
index[i].id = line.Id;
|
||||
file.Write (text);
|
||||
file.Write ((byte)0);
|
||||
++i;
|
||||
}
|
||||
var end_pos = file.BaseStream.Position;
|
||||
file.BaseStream.Position = index_pos;
|
||||
foreach (var entry in index)
|
||||
{
|
||||
file.Write (entry.offset);
|
||||
file.Write (entry.size);
|
||||
file.Write (entry.id);
|
||||
}
|
||||
file.BaseStream.Position = end_pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
149
ArcFormats/ArcFormats.csproj
Normal file
149
ArcFormats/ArcFormats.csproj
Normal file
@ -0,0 +1,149 @@
|
||||
<?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>{A8865685-27CC-427B-AC38-E48D2AD05DF4}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>GameRes.Formats</RootNamespace>
|
||||
<AssemblyName>ArcFormats</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<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' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\bin\Release\</OutputPath>
|
||||
<DefineConstants>
|
||||
</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xaml" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="zlibnet, Version=1.3.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\zlibnet\zlibnet.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ArcAMI.cs" />
|
||||
<Compile Include="ArcINT.cs" />
|
||||
<Compile Include="ArcNPA.cs" />
|
||||
<Compile Include="ArcXFL.cs" />
|
||||
<Compile Include="ArcXP3.cs" />
|
||||
<Compile Include="ArcYPF.cs" />
|
||||
<Compile Include="Blowfish.cs" />
|
||||
<Compile Include="ImageHG3.cs" />
|
||||
<Compile Include="ImageTLG.cs" />
|
||||
<Compile Include="ImageWCG.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Settings.cs" />
|
||||
<Compile Include="Strings\arcStrings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>arcStrings.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="WidgetINT.xaml.cs">
|
||||
<DependentUpon>WidgetINT.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="WidgetNPA.xaml.cs">
|
||||
<DependentUpon>WidgetNPA.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="WidgetXP3.xaml.cs">
|
||||
<DependentUpon>WidgetXP3.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="WidgetYPF.xaml.cs">
|
||||
<DependentUpon>WidgetYPF.xaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\GameRes\GameRes.csproj">
|
||||
<Project>{453c087f-e416-4ae9-8c03-d8760da0574b}</Project>
|
||||
<Name>GameRes</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="..\zlib\zlib32.dll">
|
||||
<Link>zlib32.dll</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="..\zlib\zlib64.dll">
|
||||
<Link>zlib64.dll</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>PublicSettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="WidgetINT.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="WidgetNPA.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="WidgetXP3.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="WidgetYPF.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Strings\arcStrings.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>arcStrings.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Strings\arcStrings.ru-RU.resx" />
|
||||
</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>
|
288
ArcFormats/ArcINT.cs
Normal file
288
ArcFormats/ArcINT.cs
Normal file
@ -0,0 +1,288 @@
|
||||
//! \file ArcINT.cs
|
||||
//! \date Fri Jul 11 09:32:36 2014
|
||||
//! \brief Frontwing games archive.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Simias.Encryption;
|
||||
using System.Runtime.InteropServices;
|
||||
using GameRes.Formats.Strings;
|
||||
using GameRes.Formats.Properties;
|
||||
|
||||
namespace GameRes.Formats
|
||||
{
|
||||
public class FrontwingArchive : ArcFile
|
||||
{
|
||||
public readonly Blowfish Encryption;
|
||||
|
||||
public FrontwingArchive (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir, Blowfish cipher)
|
||||
: base (arc, impl, dir)
|
||||
{
|
||||
Encryption = cipher;
|
||||
}
|
||||
}
|
||||
|
||||
public class IntEncryptionInfo
|
||||
{
|
||||
public uint? Key { get; set; }
|
||||
public string Scheme { get; set; }
|
||||
public string Password { get; set; }
|
||||
|
||||
public IntEncryptionInfo () { }
|
||||
}
|
||||
|
||||
[Export(typeof(ArchiveFormat))]
|
||||
public class IntOpener : ArchiveFormat
|
||||
{
|
||||
public override string Tag { get { return "INT"; } }
|
||||
public override string Description { get { return "FrontWing game resource archive"; } }
|
||||
public override uint Signature { get { return 0x0046494b; } }
|
||||
|
||||
public override ArcFile TryOpen (ArcView file)
|
||||
{
|
||||
uint entry_count = file.View.ReadUInt32 (4);
|
||||
if (0 == entry_count || 0 != ((entry_count - 1) >> 0x14))
|
||||
{
|
||||
Trace.WriteLine (string.Format ("Invalid entry count ({0})", entry_count));
|
||||
return null;
|
||||
}
|
||||
if (file.View.AsciiEqual (8, "__key__.dat\x00"))
|
||||
{
|
||||
uint? key = QueryEncryptionInfo();
|
||||
if (null == key)
|
||||
throw new UnknownEncryptionScheme();
|
||||
return OpenEncrypted (file, entry_count, key.Value);
|
||||
}
|
||||
|
||||
long current_offset = 8;
|
||||
var dir = new List<Entry>();
|
||||
for (uint i = 0; i < entry_count; ++i)
|
||||
{
|
||||
string name = file.View.ReadString (current_offset, 0x40);
|
||||
var entry = FormatCatalog.Instance.CreateEntry (name);
|
||||
entry.Offset = file.View.ReadUInt32 (current_offset+0x40);
|
||||
entry.Size = file.View.ReadUInt32 (current_offset+0x44);
|
||||
if (!entry.CheckPlacement (file.MaxOffset))
|
||||
return null;
|
||||
dir.Add (entry);
|
||||
current_offset += 0x48;
|
||||
}
|
||||
return new ArcFile (file, this, dir);
|
||||
}
|
||||
|
||||
private ArcFile OpenEncrypted (ArcView file, uint entry_count, uint main_key)
|
||||
{
|
||||
if (1 == entry_count)
|
||||
return null; // empty archive
|
||||
long current_offset = 8;
|
||||
var twister = new Twister();
|
||||
|
||||
// [@@L1] = 32-bit key
|
||||
// [@@L1+4] = 0 if key is available, -1 otherwise
|
||||
uint key_data = file.View.ReadUInt32 (current_offset+0x44);
|
||||
uint twist_key = twister.Twist (key_data);
|
||||
// [@@L0] = 32-bit twist key
|
||||
byte[] blowfish_key = BitConverter.GetBytes (twist_key);
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
Array.Reverse (blowfish_key);
|
||||
|
||||
var blowfish = new Blowfish (blowfish_key);
|
||||
var dir = new List<Entry>();
|
||||
byte[] name_info = new byte[0x40];
|
||||
for (uint i = 1; i < entry_count; ++i)
|
||||
{
|
||||
current_offset += 0x48;
|
||||
file.View.Read (current_offset, name_info, 0, 0x40);
|
||||
uint eax = file.View.ReadUInt32 (current_offset+0x40);
|
||||
uint edx = file.View.ReadUInt32 (current_offset+0x44);
|
||||
eax += i;
|
||||
blowfish.Decipher (ref eax, ref edx);
|
||||
uint key = twister.Twist (main_key + i);
|
||||
string name = DecipherName (name_info, key);
|
||||
|
||||
var entry = FormatCatalog.Instance.CreateEntry (name);
|
||||
entry.Offset = eax;
|
||||
entry.Size = edx;
|
||||
if (!entry.CheckPlacement (file.MaxOffset))
|
||||
return null;
|
||||
dir.Add (entry);
|
||||
}
|
||||
return new FrontwingArchive (file, this, dir, blowfish);
|
||||
}
|
||||
|
||||
private Stream OpenEncryptedEntry (FrontwingArchive arc, Entry entry)
|
||||
{
|
||||
using (var view = arc.File.CreateViewAccessor (entry.Offset, entry.Size))
|
||||
{
|
||||
byte[] data = new byte[entry.Size];
|
||||
// below is supposedly faster version of
|
||||
//arc.File.View.Read (entry.Offset, data, 0, entry.Size);
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = view.GetPointer (entry.Offset);
|
||||
try {
|
||||
Marshal.Copy (new IntPtr(ptr), data, 0, data.Length);
|
||||
} finally {
|
||||
view.SafeMemoryMappedViewHandle.ReleasePointer();
|
||||
}
|
||||
}
|
||||
arc.Encryption.Decipher (data, data.Length/8*8);
|
||||
return new MemoryStream (data, false);
|
||||
}
|
||||
}
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
{
|
||||
if (arc is FrontwingArchive)
|
||||
return OpenEncryptedEntry (arc as FrontwingArchive, entry);
|
||||
else
|
||||
return base.OpenEntry (arc, entry);
|
||||
}
|
||||
|
||||
public string DecipherName (byte[] name, uint key)
|
||||
{
|
||||
key += (key >> 8) + (key >> 16) + (key >> 24);
|
||||
key &= 0xff;
|
||||
key %= 0x34;
|
||||
int count = 0;
|
||||
for (int i = 0; i < name.Length; ++i)
|
||||
{
|
||||
byte al = name[i];
|
||||
if (0 == al)
|
||||
break;
|
||||
byte bl = (byte)key;
|
||||
++count;
|
||||
uint edx = al;
|
||||
al |= 0x20;
|
||||
al -= 0x61;
|
||||
if (al < 0x1a)
|
||||
{
|
||||
if (0 != (edx & 0x20))
|
||||
al += 0x1a;
|
||||
al = (byte)~al;
|
||||
al += 0x34;
|
||||
if (al >= bl)
|
||||
al -= bl;
|
||||
else
|
||||
al = (byte)(al - bl + 0x34);
|
||||
if (al >= 0x1a)
|
||||
al += 6;
|
||||
al += 0x41;
|
||||
name[i] = al;
|
||||
}
|
||||
++key;
|
||||
if (0x34 == key)
|
||||
key = 0;
|
||||
}
|
||||
return Encodings.cp932.GetString (name, 0, count);
|
||||
}
|
||||
|
||||
class Twister
|
||||
{
|
||||
const uint TwisterLength = 0x270;
|
||||
uint[] m_twister = new uint[TwisterLength];
|
||||
uint m_twister_pos = 0;
|
||||
|
||||
public uint Twist (uint key)
|
||||
{
|
||||
Init (key);
|
||||
return Next();
|
||||
}
|
||||
|
||||
public void Init (uint key)
|
||||
{
|
||||
uint edx = key;
|
||||
for (int i = 0; i < TwisterLength; ++i)
|
||||
{
|
||||
uint ecx = edx * 0x10dcd + 1;
|
||||
m_twister[i] = (edx & 0xffff0000) | (ecx >> 16);
|
||||
edx *= 0x1C587629;
|
||||
edx += 0x10dce;
|
||||
}
|
||||
m_twister_pos = 0;
|
||||
}
|
||||
|
||||
public uint Next ()
|
||||
{
|
||||
uint ecx = m_twister[m_twister_pos];
|
||||
uint edx = m_twister_pos + 1;
|
||||
if (TwisterLength == edx)
|
||||
edx = 0;
|
||||
uint edi = m_twister[edx];
|
||||
edi = ((edi ^ ecx) & 0x7FFFFFFF) ^ ecx;
|
||||
bool carry = 0 != (edi & 1);
|
||||
edi >>= 1;
|
||||
if (carry)
|
||||
edi ^= 0x9908B0DF;
|
||||
ecx = m_twister_pos + 0x18d;
|
||||
if (ecx >= TwisterLength)
|
||||
ecx -= TwisterLength;
|
||||
edi ^= m_twister[ecx];
|
||||
m_twister[m_twister_pos] = edi;
|
||||
m_twister_pos = edx;
|
||||
uint eax = edi ^ (edi >> 11);
|
||||
eax = ((eax & 0xFF3A58AD) << 7) ^ eax;
|
||||
eax = ((eax & 0xFFFFDF8C) << 15) ^ eax;
|
||||
eax = (eax >> 18) ^ eax;
|
||||
return eax;
|
||||
}
|
||||
}
|
||||
|
||||
public static uint EncodePassPhrase (string password)
|
||||
{
|
||||
byte[] pass_bytes = Encodings.cp932.GetBytes (password);
|
||||
uint key = 0xffffffff;
|
||||
foreach (var c in pass_bytes)
|
||||
{
|
||||
uint val = (uint)c << 24;
|
||||
key ^= val;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
bool carry = 0 != (key & 0x80000000);
|
||||
key <<= 1;
|
||||
if (carry)
|
||||
key ^= 0x4C11DB7;
|
||||
}
|
||||
key = ~key;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
public struct KeyData
|
||||
{
|
||||
public uint Key;
|
||||
public string Passphrase;
|
||||
}
|
||||
|
||||
public static readonly Dictionary<string, KeyData> KnownSchemes = new Dictionary<string, KeyData> {
|
||||
{ "Grisaia no Kajitsu", new KeyData { Key=0x1DAD9120, Passphrase="FW-6JD55162" }},
|
||||
{ "Shukufuku no Campanella", new KeyData { Key=0x4260E643, Passphrase="CAMPANELLA" }},
|
||||
{ "Makai Tenshi Djibril -Episode 4-", new KeyData { Key=0xA5A166AA, Passphrase="FW_MAKAI-TENSHI_DJIBRIL4" }},
|
||||
{ "Sengoku Tenshi Djibril (trial)", new KeyData { Key=0xef870610, Passphrase="FW-8O9B6WDS" }},
|
||||
};
|
||||
|
||||
IntEncryptionInfo m_info = Settings.Default.INTEncryption ?? new IntEncryptionInfo();
|
||||
|
||||
uint? QueryEncryptionInfo ()
|
||||
{
|
||||
var widget = new GUI.WidgetINT (m_info);
|
||||
var args = new ParametersRequestEventArgs
|
||||
{
|
||||
Notice = arcStrings.INTNotice,
|
||||
InputWidget = widget,
|
||||
};
|
||||
FormatCatalog.Instance.InvokeParametersRequest (this, args);
|
||||
if (!args.InputResult)
|
||||
throw new OperationCanceledException();
|
||||
|
||||
Settings.Default.INTEncryption = widget.Info;
|
||||
return widget.GetKey();
|
||||
}
|
||||
}
|
||||
}
|
376
ArcFormats/ArcNPA.cs
Normal file
376
ArcFormats/ArcNPA.cs
Normal file
@ -0,0 +1,376 @@
|
||||
//! \file ArcNPA.cs
|
||||
//! \date Fri Jul 18 04:07:42 2014
|
||||
//! \brief NPA archive format implementation.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using ZLibNet;
|
||||
using GameRes.Formats.Strings;
|
||||
using GameRes.Formats.Properties;
|
||||
|
||||
namespace GameRes.Formats
|
||||
{
|
||||
public class NpaEntry : PackedEntry
|
||||
{
|
||||
public byte[] RawName;
|
||||
}
|
||||
|
||||
public class NpaArchive : ArcFile
|
||||
{
|
||||
public NpaTitleId GameId { get; private set; }
|
||||
public int Key { get; private set; }
|
||||
public byte[] KeyTable { get { return m_key_table.Value; } }
|
||||
|
||||
private Lazy<byte[]> m_key_table;
|
||||
|
||||
public NpaArchive (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir,
|
||||
NpaTitleId game_id, int key)
|
||||
: base (arc, impl, dir)
|
||||
{
|
||||
GameId = game_id;
|
||||
Key = key;
|
||||
m_key_table = new Lazy<byte[]> (() => NpaOpener.GenerateKeyTable (game_id));
|
||||
}
|
||||
}
|
||||
|
||||
public enum NpaTitleId
|
||||
{
|
||||
CHAOSHEAD = 0, CHAOSHEADTR1, CHAOSHEADTR2, MURAMASATR, MURAMASA, SUMAGA, DJANGO, DJANGOTR,
|
||||
LAMENTO, LAMENTOTR, SWEETPOOL, SUMAGASP, DEMONBANE, MURAMASAAD, AXANAEL, KIKOKUGAI, SONICOMITR2,
|
||||
SUMAGA3P, SONICOMI, LOSTX, LOSTXTRAILER, DRAMATICALMURDER, TOTONO, PHENOMENO, NEKODA,
|
||||
NotEncrypted
|
||||
}
|
||||
|
||||
[Export(typeof(ArchiveFormat))]
|
||||
public class NpaOpener : ArchiveFormat
|
||||
{
|
||||
public override string Tag { get { return "NPA"; } }
|
||||
public override string Description { get { return "Nitro+ resource archive"; } }
|
||||
public override uint Signature { get { return 0x0141504e; } } // NPA\x01
|
||||
|
||||
/// <summary>Known encryption schemes.</summary>
|
||||
public static readonly string[] KnownSchemes = new string[] {
|
||||
"Chaos;Head", "Chaos;Head Trial 1", "Chaos;Head Trial 2", "Muramasa Trial", "Muramasa",
|
||||
"Sumaga", "Zoku Satsuriku no Django", "Zoku Satsuriku no Django Trial", "Lamento",
|
||||
"Lamento Trial", "Sweet Pool", "Sumaga Special", "Demonbane", "MuramasaAD", "Axanael",
|
||||
"Kikokugai", "Sonicomi Trial 2", "Sumaga 3% Trial", "Sonicomi Version 1.0",
|
||||
"Guilty Crown Lost Xmas", "Guilty Crown Lost Xmas Trailer", "DRAMAtical Murder",
|
||||
"Kimi to Kanojo to Kanojo no Koi", "Phenomeno", "Nekoda -Nyanda-",
|
||||
arcStrings.ArcNoEncryption,
|
||||
};
|
||||
|
||||
/// <summary>Game id of the last opened archive.</summary>
|
||||
NpaTitleId m_game_id = Settings.Default.NPAScheme;
|
||||
|
||||
public override ArcFile TryOpen (ArcView file)
|
||||
{
|
||||
int key1 = file.View.ReadInt32 (7);
|
||||
int key2 = file.View.ReadInt32 (11);
|
||||
bool compressed = 0 != file.View.ReadByte (15);
|
||||
bool encrypted = 0 != file.View.ReadByte (16);
|
||||
int total_count = file.View.ReadInt32 (17);
|
||||
int folder_count = file.View.ReadInt32 (21);
|
||||
int file_count = file.View.ReadInt32 (25);
|
||||
if (total_count < folder_count + file_count)
|
||||
return null;
|
||||
uint dir_size = file.View.ReadUInt32 (37);
|
||||
if (dir_size >= file.MaxOffset)
|
||||
return null;
|
||||
|
||||
var game_id = NpaTitleId.NotEncrypted;
|
||||
if (encrypted)
|
||||
game_id = QueryGameEncryption();
|
||||
|
||||
int key;
|
||||
if (encrypted && (game_id == NpaTitleId.LAMENTO || game_id == NpaTitleId.LAMENTOTR))
|
||||
key = key1 + key2;
|
||||
else
|
||||
key = key1 * key2;
|
||||
|
||||
long cur_offset = 41;
|
||||
var dir = new List<Entry> (file_count);
|
||||
for (int i = 0; i < total_count; ++i)
|
||||
{
|
||||
int name_size = file.View.ReadInt32 (cur_offset);
|
||||
int type = file.View.ReadByte (cur_offset+4+name_size);
|
||||
if (1 != type)
|
||||
{
|
||||
var raw_name = new byte[name_size];
|
||||
file.View.Read (cur_offset+4, raw_name, 0, (uint)name_size);
|
||||
for (int x = 0; x < name_size; ++x)
|
||||
raw_name[x] += DecryptName (x, i, key);
|
||||
var info_offset = cur_offset + 5 + name_size;
|
||||
|
||||
uint id = file.View.ReadUInt32 (info_offset);
|
||||
uint offset = file.View.ReadUInt32 (info_offset+4);
|
||||
uint size = file.View.ReadUInt32 (info_offset+8);
|
||||
uint unpacked_size = file.View.ReadUInt32 (info_offset+12);
|
||||
|
||||
var entry = new NpaEntry {
|
||||
Name = Encodings.cp932.GetString (raw_name),
|
||||
Offset = dir_size+offset+41,
|
||||
Size = size,
|
||||
UnpackedSize = unpacked_size,
|
||||
IsPacked = compressed,
|
||||
RawName = raw_name,
|
||||
};
|
||||
entry.Type = FormatCatalog.Instance.GetTypeFromName (entry.Name);
|
||||
dir.Add (entry);
|
||||
}
|
||||
cur_offset += 4 + name_size + 17;
|
||||
}
|
||||
if (game_id != NpaTitleId.NotEncrypted)
|
||||
return new NpaArchive (file, this, dir, game_id, key);
|
||||
else
|
||||
return new ArcFile (file, this, dir);
|
||||
}
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
{
|
||||
if (arc is NpaArchive && entry is NpaEntry)
|
||||
return OpenEncryptedEntry (arc as NpaArchive, entry as NpaEntry);
|
||||
|
||||
var input = arc.File.CreateStream (entry.Offset, entry.Size);
|
||||
return UnpackEntry (input, entry);
|
||||
}
|
||||
|
||||
private Stream UnpackEntry (Stream input, Entry entry)
|
||||
{
|
||||
if (entry.Type != "image")
|
||||
{
|
||||
var npa_entry = entry as PackedEntry;
|
||||
if (null != npa_entry && npa_entry.IsPacked)
|
||||
return new ZLibStream (input, CompressionMode.Decompress);
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
private Stream OpenEncryptedEntry (NpaArchive arc, NpaEntry entry)
|
||||
{
|
||||
int key = GetKeyFromEntry (entry, arc.GameId, arc.Key);
|
||||
int encrypted_length = 0x1000;
|
||||
|
||||
if (arc.GameId != NpaTitleId.LAMENTO && arc.GameId != NpaTitleId.LAMENTOTR)
|
||||
encrypted_length += entry.RawName.Length;
|
||||
|
||||
using (var view = arc.File.CreateViewAccessor (entry.Offset, entry.Size))
|
||||
{
|
||||
byte[] buffer = new byte[entry.Size];
|
||||
unsafe
|
||||
{
|
||||
byte* src = view.GetPointer (entry.Offset);
|
||||
try
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < entry.Size && x < encrypted_length; x++)
|
||||
{
|
||||
if (arc.GameId == NpaTitleId.LAMENTO || arc.GameId == NpaTitleId.LAMENTOTR)
|
||||
{
|
||||
buffer[x] = (byte)(arc.KeyTable[src[x]] - key);
|
||||
}
|
||||
else if (arc.GameId == NpaTitleId.TOTONO)
|
||||
{
|
||||
byte r = src[x];
|
||||
r = arc.KeyTable[r];
|
||||
r = arc.KeyTable[r];
|
||||
r = arc.KeyTable[r];
|
||||
r = (byte)~r;
|
||||
buffer[x] = (byte)((sbyte)r - key - x);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[x] = (byte)(arc.KeyTable[src[x]] - key - x);
|
||||
}
|
||||
}
|
||||
if (x != entry.Size)
|
||||
Marshal.Copy ((IntPtr)(src+x), buffer, x, (int)(entry.Size-x));
|
||||
} finally {
|
||||
view.SafeMemoryMappedViewHandle.ReleasePointer();
|
||||
}
|
||||
}
|
||||
return UnpackEntry (new MemoryStream (buffer, false), entry);
|
||||
}
|
||||
}
|
||||
|
||||
byte DecryptName (int index, int curfile, int arc_key)
|
||||
{
|
||||
int key = 0xFC*index;
|
||||
|
||||
key -= arc_key >> 0x18;
|
||||
key -= arc_key >> 0x10;
|
||||
key -= arc_key >> 0x08;
|
||||
key -= arc_key & 0xff;
|
||||
|
||||
key -= curfile >> 0x18;
|
||||
key -= curfile >> 0x10;
|
||||
key -= curfile >> 0x08;
|
||||
key -= curfile;
|
||||
|
||||
return (byte)(key & 0xff);
|
||||
}
|
||||
|
||||
byte GetKeyFromEntry (NpaEntry entry, NpaTitleId game_id, int key2)
|
||||
{
|
||||
int key1;
|
||||
switch (game_id)
|
||||
{
|
||||
case NpaTitleId.AXANAEL:
|
||||
case NpaTitleId.KIKOKUGAI:
|
||||
case NpaTitleId.SONICOMITR2:
|
||||
case NpaTitleId.SONICOMI:
|
||||
case NpaTitleId.LOSTX:
|
||||
case NpaTitleId.DRAMATICALMURDER:
|
||||
key1 = 0x20101118;
|
||||
break;
|
||||
case NpaTitleId.TOTONO:
|
||||
key1 = 0x12345678;
|
||||
break;
|
||||
default:
|
||||
key1 = unchecked((int)0x87654321);
|
||||
break;
|
||||
}
|
||||
var name = entry.RawName;
|
||||
int i;
|
||||
for (i = 0; i < name.Length; ++i)
|
||||
key1 -= name[i];
|
||||
|
||||
int key = key1 * i;
|
||||
|
||||
if (game_id != NpaTitleId.LAMENTO && game_id != NpaTitleId.LAMENTOTR) // if the game is not Lamento
|
||||
{
|
||||
key += key2;
|
||||
key *= (int)entry.UnpackedSize;
|
||||
}
|
||||
return (byte)(key & 0xff);
|
||||
}
|
||||
|
||||
public static byte[] GenerateKeyTable (NpaTitleId title_id)
|
||||
{
|
||||
if ((int)title_id >= OrderTable.Length)
|
||||
throw new ArgumentOutOfRangeException ("title_id", "Invalid title id specified");
|
||||
|
||||
byte[] order = OrderTable[(int)title_id];
|
||||
var table = new byte[256];
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
int edx = i << 4;
|
||||
int dl = (edx + order[i & 0x0f]) & 0xff;
|
||||
int dh = (edx + (order[i>>4] << 8)) & 0xff00;
|
||||
edx = (dh | dl) >> 4;
|
||||
var eax = BaseTable[i];
|
||||
table[eax] = (byte)(edx & 0xff);
|
||||
}
|
||||
for (int i = 16; i+1 < order.Length; i+=2)
|
||||
{
|
||||
int ecx = order[i];
|
||||
int edx = order[i+1];
|
||||
byte tmp = table[ecx];
|
||||
table[ecx] = table[edx];
|
||||
table[edx] = tmp;
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
NpaTitleId QueryGameEncryption ()
|
||||
{
|
||||
var widget = new GUI.WidgetNPA (KnownSchemes[(int)m_game_id]);
|
||||
var args = new ParametersRequestEventArgs
|
||||
{
|
||||
Notice = arcStrings.ArcEncryptedNotice,
|
||||
InputWidget = widget,
|
||||
};
|
||||
FormatCatalog.Instance.InvokeParametersRequest (this, args);
|
||||
if (!args.InputResult)
|
||||
throw new OperationCanceledException();
|
||||
|
||||
NpaTitleId scheme = GetTitleId (widget.GetScheme());
|
||||
Settings.Default.NPAScheme = scheme;
|
||||
return scheme;
|
||||
}
|
||||
|
||||
public static NpaTitleId GetTitleId (string title)
|
||||
{
|
||||
var index = Array.IndexOf (KnownSchemes, title);
|
||||
if (index != -1)
|
||||
return (NpaTitleId)index;
|
||||
else
|
||||
return NpaTitleId.NotEncrypted;
|
||||
}
|
||||
|
||||
static readonly byte[] BaseTable = {
|
||||
0x6F,0x05,0x6A,0xBF,0xA1,0xC7,0x8E,0xFB,0xD4,0x2F,0x80,0x58,0x4A,0x17,0x3B,0xB1,
|
||||
0x89,0xEC,0xA0,0x9F,0xD3,0xFC,0xC2,0x04,0x68,0x03,0xF3,0x25,0xBE,0x24,0xF1,0xBD,
|
||||
0xB8,0x41,0xC9,0x27,0x0E,0xA3,0xD8,0x7F,0x5B,0x8F,0x16,0x49,0xAA,0xB2,0x18,0xA7,
|
||||
0x33,0xE4,0xDB,0x48,0xCA,0xDE,0xAE,0xCD,0x13,0x1F,0x15,0x2E,0x39,0xF5,0x1E,0xDD,
|
||||
0x0F,0x88,0x4C,0x98,0x36,0xB4,0x3F,0x09,0x83,0xFD,0x32,0xBA,0x14,0x30,0x7A,0x63,
|
||||
0xB9,0x56,0x95,0x61,0xCC,0x8B,0xEF,0xDA,0xE5,0x2C,0xDC,0x12,0x1A,0x67,0x23,0x50,
|
||||
0xD1,0xC3,0x7E,0x6D,0xB6,0x90,0x3C,0xB3,0x0B,0xE2,0x91,0x70,0xA8,0xDF,0x44,0xC4,
|
||||
0xF4,0x01,0x5C,0x10,0x06,0xE7,0x54,0x40,0x43,0x72,0x38,0xBC,0xE3,0x07,0xFA,0x34,
|
||||
0x02,0xA4,0xF7,0x74,0xA9,0x4D,0x42,0xA5,0x85,0x35,0x79,0xD2,0x76,0x97,0x45,0x4F,
|
||||
0x08,0x5A,0xB0,0xEE,0x51,0x73,0x69,0x9E,0x94,0x47,0x77,0x29,0xD9,0x64,0x11,0xEB,
|
||||
0x37,0xAC,0x20,0x62,0x9A,0x6B,0x9C,0x75,0x22,0x87,0xAB,0x78,0x53,0xC8,0x5D,0xAD,
|
||||
0x2A,0xF2,0xCB,0xB7,0x0D,0xED,0x86,0x55,0xFF,0x19,0x57,0xD7,0xD5,0x60,0xC6,0x3D,
|
||||
0xEA,0xC1,0x6C,0xE1,0xC0,0x65,0x84,0xC5,0xE0,0x3E,0x7D,0x28,0x66,0xAF,0x1C,0x9B,
|
||||
0xCF,0x81,0x4E,0x26,0x59,0x2B,0x5F,0x7B,0xE8,0x8D,0x52,0x7C,0xF8,0x82,0x0C,0xF9,
|
||||
0x8C,0xE9,0xB5,0xE6,0x31,0x93,0x46,0x5E,0x1D,0x1B,0x4B,0x71,0xD6,0x92,0x3A,0xA6,
|
||||
0x2D,0x00,0x9D,0xBB,0x6E,0xF0,0x99,0xCE,0x21,0x0A,0xD0,0xF6,0xFE,0xA2,0x8A,0x96,
|
||||
};
|
||||
|
||||
static readonly byte[][] OrderTable = {
|
||||
// CHAOSHEAD
|
||||
new byte[] { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
// CHAOSHEADTR1
|
||||
new byte[] { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1e,0x4e,0x66,0xb6 },
|
||||
// CHAOSHEADTR2
|
||||
new byte[] { 0x05,0x05,0x05,0x05,0x05,0x0b,0x0b,0x0b,0x0b,0x0b,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||
// MURAMASATR
|
||||
new byte[] { 0x3c,0xe0,0x2e,0x2f,0x20,0x2e,0x2f,0x20,0x8e,0x80,0x80,0xf2,0xf2,0xf2,0xfa,0xfc },
|
||||
// MURAMASA
|
||||
new byte[] { 0x35,0x70,0x2e,0x66,0x67,0x65,0x66,0x67,0x85,0x89,0x89,0x3b,0x3b,0x8b,0x81,0x85 },
|
||||
// SUMAGA
|
||||
new byte[] { 0x3c,0xe0,0x2e,0x2f,0x2f,0x2f,0x2f,0x20,0x8e,0x8f,0x8f,0xf2,0xf2,0xf2,0xfc,0xfc },
|
||||
// DJANGO
|
||||
new byte[] { 0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0x1e,0x4e,0x66,0xb6 },
|
||||
// DJANGOTR
|
||||
new byte[] { 0xed,0xee,0xee,0xef,0xed,0xee,0xee,0xee,0xfe,0xde,0xee,0xef,0xed,0xee,0xfe,0xdf,0x1e,0x4e,0x66,0xb6 },
|
||||
// LAMENTO
|
||||
new byte[] { 0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0x1e,0x4e,0x66,0xb6 },
|
||||
// LAMENTOTR
|
||||
new byte[] { 0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0x1e,0x4e,0x66,0xb6 },
|
||||
// SWEETPOOL
|
||||
new byte[] { 0x38,0x9c,0x2a,0x8b,0x8b,0x8b,0x8b,0x8c,0x8a,0x8b,0x8b,0xae,0xae,0xae,0xa8,0xa8 },
|
||||
// SUMAGASP
|
||||
new byte[] { 0xab,0x6f,0x9d,0x9e,0x9f,0x9d,0x9e,0xaf,0x8d,0xff,0xff,0x71,0x71,0x71,0x79,0x7b },
|
||||
// DEMONBANE
|
||||
new byte[] { 0x96,0xb9,0x47,0x48,0x99,0x97,0x9c,0xaa,0x88,0xca,0xea,0x73,0x73,0x7b,0xc9,0xc6 },
|
||||
// MURAMASAAD
|
||||
new byte[] { 0x00,0x04,0x04,0x68,0x68,0x68,0x68,0x68,0x6f,0x6f,0x9f,0x96,0x96,0x96,0x96,0x9b },
|
||||
// AXANAEL
|
||||
new byte[] { 0x08,0x0c,0x0c,0xc0,0xf0,0xf0,0xf0,0xf0,0xf7,0xf7,0xf7,0xfe,0xfe,0xfe,0xfe,0xf3 },
|
||||
// KIKOKUGAI
|
||||
new byte[] { 0x0f,0x07,0x07,0x90,0xf7,0xf7,0xf7,0xf7,0xf2,0x47,0x47,0x49,0xc9,0xc9,0xc9,0xc3 },
|
||||
// SONICOMITR2
|
||||
new byte[] { 0x08,0x0a,0x0a,0x40,0xfa,0xfa,0x50,0x50,0x55,0xf7,0xf7,0xf9,0x29,0x2c,0x7c,0x73 },
|
||||
// SUMAGA3P
|
||||
new byte[] { 0x0f,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff },
|
||||
// SONICOMI
|
||||
new byte[] { 0x0e,0x0b,0x0e,0x77,0x2e,0x2e,0x80,0x86,0xb9,0x2e,0x2e,0x29,0x89,0x82,0xad,0xaa },
|
||||
// LOSTX
|
||||
new byte[] { 0x38,0xba,0x4b,0x5b,0x55,0xae,0xee,0xe0,0x67,0x48,0x08,0x0a,0x6a,0x3d,0x32,0x8d },
|
||||
// LOSTXTRAILER
|
||||
new byte[] { 0x34,0x7a,0xbb,0xcb,0x11,0x65,0xea,0x5c,0x27,0x0f,0xcf,0xc6,0x66,0x39,0x39,0xfd },
|
||||
// DRAMATICALMURDER
|
||||
new byte[] { 0x05,0x0d,0x0d,0x13,0xb5,0x3d,0x8d,0x2d,0x20,0xc7,0xc7,0xcf,0x1f,0xef,0xef,0x48 },
|
||||
// TOTONO
|
||||
new byte[] { 0x6e,0x60,0x90,0xac,0xb3,0xe3,0x83,0xd6,0xde,0x7a,0x7a,0x7f,0xef,0xbf,0xb2,0xd6 },
|
||||
// PHENOMENO
|
||||
new byte[] { 0x30,0x96,0xdb,0x2b,0x3d,0x81,0x02,0x74,0x47,0x2b,0xeb,0xee,0x6e,0x35,0x35,0x5d },
|
||||
// NEKODA
|
||||
new byte[] { 0xdc,0xdc,0xec,0xcd,0xdb,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0x1e,0x4e,0x66,0xb6 },
|
||||
};
|
||||
}
|
||||
}
|
212
ArcFormats/ArcXFL.cs
Normal file
212
ArcFormats/ArcXFL.cs
Normal file
@ -0,0 +1,212 @@
|
||||
//! \file ArcXFL.cs
|
||||
//! \date Mon Jun 30 21:18:29 2014
|
||||
//! \brief XFL resource format implementation.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.MemoryMappedFiles;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
|
||||
namespace GameRes.Formats
|
||||
{
|
||||
[Export(typeof(ArchiveFormat))]
|
||||
public class XflOpener : ArchiveFormat
|
||||
{
|
||||
public override string Tag { get { return "XFL"; } }
|
||||
public override string Description { get { return "Liar-soft game resource archive"; } }
|
||||
public override uint Signature { get { return 0x0001424c; } }
|
||||
|
||||
public override ArcFile TryOpen (ArcView file)
|
||||
{
|
||||
uint dir_size = file.View.ReadUInt32 (4);
|
||||
int count = file.View.ReadInt32 (8);
|
||||
if (count <= 0)
|
||||
return null;
|
||||
long max_offset = file.MaxOffset;
|
||||
uint base_offset = dir_size + 12;
|
||||
if (dir_size >= max_offset || base_offset >= max_offset)
|
||||
return null;
|
||||
|
||||
file.View.Reserve (0, base_offset);
|
||||
long cur_offset = 12;
|
||||
|
||||
var dir = new List<Entry> (count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
if (cur_offset+40 > base_offset)
|
||||
return null;
|
||||
string name = file.View.ReadString (cur_offset, 32);
|
||||
var entry = FormatCatalog.Instance.CreateEntry (name);
|
||||
entry.Offset = base_offset + file.View.ReadUInt32 (cur_offset+32);
|
||||
entry.Size = file.View.ReadUInt32 (cur_offset+36);
|
||||
if (!entry.CheckPlacement (max_offset))
|
||||
return null;
|
||||
dir.Add (entry);
|
||||
cur_offset += 40;
|
||||
}
|
||||
return new ArcFile (file, this, dir);
|
||||
}
|
||||
}
|
||||
|
||||
public class LwgImageEntry : ImageEntry
|
||||
{
|
||||
public int PosX;
|
||||
public int PosY;
|
||||
public int BPP;
|
||||
}
|
||||
|
||||
[Export(typeof(ArchiveFormat))]
|
||||
public class LwgOpener : ArchiveFormat
|
||||
{
|
||||
public override string Tag { get { return "LWG"; } }
|
||||
public override string Description { get { return "Liar-soft image archive"; } }
|
||||
public override uint Signature { get { return 0x0001474c; } }
|
||||
|
||||
public override ArcFile TryOpen (ArcView file)
|
||||
{
|
||||
uint height = file.View.ReadUInt32 (4);
|
||||
uint width = file.View.ReadUInt32 (8);
|
||||
int count = file.View.ReadInt32 (12);
|
||||
if (count <= 0)
|
||||
return null;
|
||||
uint dir_size = file.View.ReadUInt32 (20);
|
||||
uint cur_offset = 24;
|
||||
uint data_offset = cur_offset + dir_size;
|
||||
uint data_size = file.View.ReadUInt32 (data_offset);
|
||||
data_offset += 4;
|
||||
|
||||
var dir = new List<Entry> (count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
var entry = new LwgImageEntry();
|
||||
entry.PosX = file.View.ReadInt32 (cur_offset);
|
||||
entry.PosY = file.View.ReadInt32 (cur_offset+4);
|
||||
entry.BPP = file.View.ReadByte (cur_offset+8);
|
||||
entry.Offset = data_offset + file.View.ReadUInt32 (cur_offset+9);
|
||||
entry.Size = file.View.ReadUInt32 (cur_offset+13);
|
||||
|
||||
uint name_length = file.View.ReadByte (cur_offset+17);
|
||||
string name = file.View.ReadString (cur_offset+18, name_length, Encoding.ASCII);
|
||||
entry.Name = name + ".wcg";
|
||||
cur_offset += 18+name_length;
|
||||
if (cur_offset > dir_size+24)
|
||||
return null;
|
||||
if (entry.CheckPlacement (data_offset + data_size))
|
||||
dir.Add (entry);
|
||||
}
|
||||
return new ArcFile (file, this, dir);
|
||||
}
|
||||
}
|
||||
|
||||
public class GscScriptData : ScriptData
|
||||
{
|
||||
public byte[] Header;
|
||||
public byte[] Code;
|
||||
public byte[] Footer;
|
||||
}
|
||||
|
||||
//[Export(typeof(ScriptFormat))]
|
||||
public class GscFormat : ScriptFormat
|
||||
{
|
||||
public override string Tag { get { return "GSC"; } }
|
||||
public override string Description { get { return "Liar-soft proprietary script format"; } }
|
||||
public override uint Signature { get { return 0; } }
|
||||
|
||||
public override ScriptData Read (string name, Stream stream)
|
||||
{
|
||||
using (var file = new BinaryReader (stream, Encodings.cp932, true))
|
||||
{
|
||||
uint signature = file.ReadUInt32();
|
||||
if (signature != file.BaseStream.Length)
|
||||
return null;
|
||||
uint header_size = file.ReadUInt32();
|
||||
if (header_size > 0x24 || header_size < 0x14)
|
||||
return null;
|
||||
uint code_size = file.ReadUInt32();
|
||||
uint text_index_size = file.ReadUInt32();
|
||||
uint text_size = file.ReadUInt32();
|
||||
byte[] header_data = file.ReadBytes ((int)header_size-0x14);
|
||||
byte[] code = file.ReadBytes ((int)code_size);
|
||||
uint[] index = new uint[text_index_size/4];
|
||||
for (int i = 0; i < index.Length; ++i)
|
||||
{
|
||||
index[i] = file.ReadUInt32();
|
||||
if (index[i] >= text_size)
|
||||
return null;
|
||||
}
|
||||
long text_offset = header_size + code_size + text_index_size;
|
||||
|
||||
var script = new GscScriptData();
|
||||
script.Header = header_data;
|
||||
script.Code = code;
|
||||
for (int i = 0; i < index.Length; ++i)
|
||||
{
|
||||
file.BaseStream.Position = text_offset + index[i];
|
||||
string text = StreamExtension.ReadCString (file.BaseStream);
|
||||
script.TextLines.Add (new ScriptLine { Id = (uint)i, Text = text });
|
||||
}
|
||||
long footer_pos = text_offset + text_size;
|
||||
file.BaseStream.Position = footer_pos;
|
||||
script.Footer = new byte[file.BaseStream.Length - footer_pos];
|
||||
file.BaseStream.Read (script.Footer, 0, script.Footer.Length);
|
||||
return script;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write (Stream stream, ScriptData script_data)
|
||||
{
|
||||
var script = script_data as GscScriptData;
|
||||
if (null == script)
|
||||
throw new InvalidFormatException();
|
||||
using (var file = new BinaryWriter (stream, Encodings.cp932, true))
|
||||
{
|
||||
long file_size_pos = file.BaseStream.Position;
|
||||
file.Write ((int)0);
|
||||
|
||||
file.Write ((int)(script.Header.Length + 0x14));
|
||||
file.Write ((int)script.Code.Length);
|
||||
int line_count = script.TextLines.Count;
|
||||
int text_index_size = line_count * 4;
|
||||
file.Write (text_index_size);
|
||||
|
||||
long text_size_pos = file.BaseStream.Position;
|
||||
file.Write ((int)0);
|
||||
if (0 < script.Header.Length)
|
||||
file.Write (script.Header);
|
||||
if (0 < script.Code.Length)
|
||||
file.Write (script.Code);
|
||||
|
||||
long text_index_pos = file.BaseStream.Position;
|
||||
var index = new uint[line_count];
|
||||
file.BaseStream.Seek (text_index_size, SeekOrigin.Current);
|
||||
int i = 0;
|
||||
long text_pos = file.BaseStream.Position;
|
||||
uint current_pos = 0;
|
||||
foreach (var line in script.TextLines)
|
||||
{
|
||||
index[i] = current_pos;
|
||||
var text = Encodings.cp932.GetBytes (line.Text);
|
||||
file.Write (text);
|
||||
file.Write ((byte)0);
|
||||
++i;
|
||||
current_pos += (uint)text.Length + 1;
|
||||
}
|
||||
uint text_size = (uint)(file.BaseStream.Position - text_pos);
|
||||
if (0 < script.Footer.Length)
|
||||
file.Write (script.Footer);
|
||||
uint file_size = (uint)(file.BaseStream.Position - file_size_pos);
|
||||
file.BaseStream.Position = file_size_pos;
|
||||
file.Write (file_size);
|
||||
file.BaseStream.Position = text_size_pos;
|
||||
file.Write (text_size);
|
||||
file.BaseStream.Position = text_index_pos;
|
||||
foreach (var offset in index)
|
||||
file.Write (offset);
|
||||
file.BaseStream.Position = file_size_pos + file_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
626
ArcFormats/ArcXP3.cs
Normal file
626
ArcFormats/ArcXP3.cs
Normal file
@ -0,0 +1,626 @@
|
||||
//! \file ArcXP3.cs
|
||||
//! \date Wed Jul 16 13:58:17 2014
|
||||
//! \brief KiriKiri engine archive implementation.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.MemoryMappedFiles;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Diagnostics;
|
||||
using GameRes.Utility;
|
||||
using ZLibNet;
|
||||
using GameRes.Formats.Strings;
|
||||
using GameRes.Formats.Properties;
|
||||
|
||||
namespace GameRes.Formats.KiriKiri
|
||||
{
|
||||
public struct Xp3Segment
|
||||
{
|
||||
public bool IsCompressed;
|
||||
public long Offset;
|
||||
public uint Size;
|
||||
public uint PackedSize;
|
||||
}
|
||||
|
||||
public class Xp3Entry : PackedEntry
|
||||
{
|
||||
List<Xp3Segment> m_segments = new List<Xp3Segment>();
|
||||
|
||||
public bool IsEncrypted { get; set; }
|
||||
public ICrypt Cipher { get; set; }
|
||||
public ICollection<Xp3Segment> Segments { get { return m_segments; } }
|
||||
public uint Hash { get; set; }
|
||||
}
|
||||
|
||||
// Archive version 1: encrypt file first, then calculate checksum
|
||||
// version 2: calculate checksum, then encrypt
|
||||
|
||||
[Export(typeof(ArchiveFormat))]
|
||||
public class Xp3Opener : ArchiveFormat
|
||||
{
|
||||
public override string Tag { get { return "XP3"; } }
|
||||
public override string Description { get { return "KiriKiri game engine resource archive"; } }
|
||||
public override uint Signature { get { return 0x0d335058; } }
|
||||
|
||||
private static readonly ICrypt NoCryptAlgorithm = new NoCrypt();
|
||||
|
||||
public static readonly Dictionary<string, ICrypt> KnownSchemes = new Dictionary<string, ICrypt> {
|
||||
{ arcStrings.ArcNoEncryption, NoCryptAlgorithm },
|
||||
{ "Fate/Stay Night", new FateCrypt() },
|
||||
{ "Swan Song", new SwanSongCrypt() },
|
||||
{ "Cafe Sourire", new XorCrypt (0xcd) },
|
||||
{ "Seirei Tenshou", new SeitenCrypt() },
|
||||
{ "Okiba ga Nai!", new OkibaCrypt() },
|
||||
};
|
||||
|
||||
public override ArcFile TryOpen (ArcView file)
|
||||
{
|
||||
if (!file.View.AsciiEqual (0, "XP3\x0d\x0a\x20\x0a\x1a\x8b\x67\x01"))
|
||||
return null;
|
||||
long dir_offset = file.View.ReadInt64 (0x0b);
|
||||
if (0x17 == dir_offset)
|
||||
{
|
||||
if (1 != file.View.ReadUInt32 (0x13))
|
||||
return null;
|
||||
if (0x80 != file.View.ReadUInt32 (0x17))
|
||||
return null;
|
||||
dir_offset = file.View.ReadInt64 (0x20);
|
||||
}
|
||||
int header_type = file.View.ReadByte (dir_offset);
|
||||
if (0 != header_type && 1 != header_type)
|
||||
return null;
|
||||
|
||||
Stream header_stream;
|
||||
if (0 == header_type) // read unpacked header
|
||||
{
|
||||
long header_size = file.View.ReadInt64 (dir_offset+1);
|
||||
if (header_size > uint.MaxValue)
|
||||
return null;
|
||||
header_stream = file.CreateStream (dir_offset+9, (uint)header_size);
|
||||
}
|
||||
else // read packed header
|
||||
{
|
||||
long packed_size = file.View.ReadInt64 (dir_offset+1);
|
||||
if (packed_size > uint.MaxValue)
|
||||
return null;
|
||||
long header_size = file.View.ReadInt64 (dir_offset+9);
|
||||
using (var input = file.CreateStream (dir_offset+17, (uint)packed_size))
|
||||
header_stream = ZLibCompressor.DeCompress (input);
|
||||
}
|
||||
|
||||
var crypt_algorithm = new Lazy<ICrypt> (QueryCryptAlgorithm);
|
||||
|
||||
var dir = new List<Entry>();
|
||||
dir_offset = 0;
|
||||
using (var header = new BinaryReader (header_stream, Encoding.Unicode))
|
||||
{
|
||||
while (-1 != header.PeekChar())
|
||||
{
|
||||
uint entry_signature = header.ReadUInt32();
|
||||
if (0x656c6946 != entry_signature) // "File"
|
||||
{
|
||||
break;
|
||||
}
|
||||
long entry_size = header.ReadInt64();
|
||||
dir_offset += 12 + entry_size;
|
||||
var entry = new Xp3Entry();
|
||||
while (entry_size > 0)
|
||||
{
|
||||
uint section = header.ReadUInt32();
|
||||
long section_size = header.ReadInt64();
|
||||
entry_size -= 12;
|
||||
if (section_size > entry_size)
|
||||
break;
|
||||
entry_size -= section_size;
|
||||
long next_section_pos = header.BaseStream.Position + section_size;
|
||||
switch (section)
|
||||
{
|
||||
case 0x6f666e69: // "info"
|
||||
{
|
||||
if (entry.Size != 0 || !string.IsNullOrEmpty (entry.Name))
|
||||
{
|
||||
goto NextEntry; // ambiguous entry, ignore
|
||||
}
|
||||
entry.IsEncrypted = 0 != header.ReadUInt32();
|
||||
long file_size = header.ReadInt64();
|
||||
long packed_size = header.ReadInt64();
|
||||
if (file_size > uint.MaxValue || packed_size > uint.MaxValue)
|
||||
{
|
||||
goto NextEntry;
|
||||
}
|
||||
entry.IsPacked = file_size != packed_size;
|
||||
entry.Size = (uint)packed_size;
|
||||
entry.UnpackedSize = (uint)file_size;
|
||||
|
||||
int name_size = header.ReadInt16();
|
||||
if (name_size > 0x100 || name_size <= 0)
|
||||
{
|
||||
goto NextEntry;
|
||||
}
|
||||
if (entry.IsEncrypted)
|
||||
entry.Cipher = crypt_algorithm.Value;
|
||||
else
|
||||
entry.Cipher = NoCryptAlgorithm;
|
||||
|
||||
char[] name = header.ReadChars (name_size);
|
||||
entry.Name = new string (name);
|
||||
entry.Type = FormatCatalog.Instance.GetTypeFromName (entry.Name);
|
||||
break;
|
||||
}
|
||||
case 0x6d676573: // "segm"
|
||||
{
|
||||
int segment_count = (int)(section_size / 0x1c);
|
||||
if (segment_count > 0)
|
||||
{
|
||||
for (int i = 0; i < segment_count; ++i)
|
||||
{
|
||||
bool compressed = 0 != header.ReadInt32();
|
||||
long segment_offset = header.ReadInt64();
|
||||
long segment_size = header.ReadInt64();
|
||||
long segment_packed_size = header.ReadInt64();
|
||||
if (segment_offset > file.MaxOffset || segment_size > file.MaxOffset
|
||||
|| segment_packed_size > file.MaxOffset)
|
||||
{
|
||||
goto NextEntry;
|
||||
}
|
||||
var segment = new Xp3Segment {
|
||||
IsCompressed = compressed,
|
||||
Offset = segment_offset,
|
||||
Size = (uint)segment_size,
|
||||
PackedSize = (uint)segment_packed_size
|
||||
};
|
||||
entry.Segments.Add (segment);
|
||||
}
|
||||
entry.Offset = entry.Segments.First().Offset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x726c6461: // "adlr"
|
||||
if (4 == section_size)
|
||||
entry.Hash = header.ReadUInt32();
|
||||
break;
|
||||
|
||||
default: // unknown section
|
||||
break;
|
||||
}
|
||||
header.BaseStream.Position = next_section_pos;
|
||||
}
|
||||
if (!string.IsNullOrEmpty (entry.Name) && entry.Segments.Any())
|
||||
dir.Add (entry);
|
||||
NextEntry:
|
||||
header.BaseStream.Position = dir_offset;
|
||||
}
|
||||
}
|
||||
return new ArcFile (file, this, dir);
|
||||
}
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
{
|
||||
var xp3_entry = entry as Xp3Entry;
|
||||
if (null == xp3_entry || !xp3_entry.Segments.Any())
|
||||
return arc.File.CreateStream (entry.Offset, entry.Size);
|
||||
if (1 == xp3_entry.Segments.Count && !xp3_entry.IsEncrypted)
|
||||
{
|
||||
var segment = xp3_entry.Segments.First();
|
||||
if (segment.IsCompressed)
|
||||
return new ZLibStream (arc.File.CreateStream (segment.Offset, segment.PackedSize),
|
||||
CompressionMode.Decompress);
|
||||
else
|
||||
return arc.File.CreateStream (segment.Offset, segment.Size);
|
||||
}
|
||||
return new Xp3Stream (arc.File, xp3_entry);
|
||||
}
|
||||
|
||||
string m_scheme = GetDefaultScheme();
|
||||
|
||||
ICrypt QueryCryptAlgorithm ()
|
||||
{
|
||||
var widget = new GUI.WidgetXP3 (m_scheme);
|
||||
var args = new ParametersRequestEventArgs
|
||||
{
|
||||
Notice = arcStrings.ArcEncryptedNotice,
|
||||
InputWidget = widget,
|
||||
};
|
||||
FormatCatalog.Instance.InvokeParametersRequest (this, args);
|
||||
if (!args.InputResult)
|
||||
throw new OperationCanceledException();
|
||||
|
||||
m_scheme = widget.GetScheme();
|
||||
if (null != m_scheme)
|
||||
{
|
||||
ICrypt algorithm;
|
||||
if (KnownSchemes.TryGetValue (m_scheme, out algorithm))
|
||||
{
|
||||
Settings.Default.XP3Scheme = m_scheme;
|
||||
return algorithm;
|
||||
}
|
||||
}
|
||||
return NoCryptAlgorithm;
|
||||
}
|
||||
|
||||
public static string GetDefaultScheme ()
|
||||
{
|
||||
string scheme = Settings.Default.XP3Scheme;
|
||||
if (!string.IsNullOrEmpty (scheme) && KnownSchemes.ContainsKey (scheme))
|
||||
return scheme;
|
||||
else
|
||||
return arcStrings.ArcNoEncryption;
|
||||
}
|
||||
|
||||
static uint GetFileCheckSum (Stream src)
|
||||
{
|
||||
// compute file checksum via adler32.
|
||||
// src's file pointer should be reset to zero.
|
||||
var sum = new Adler32();
|
||||
byte[] buf = new byte[64*1024];
|
||||
for (;;)
|
||||
{
|
||||
int read = src.Read (buf, 0, buf.Length);
|
||||
if (0 == read) break;
|
||||
sum.Update (buf, 0, read);
|
||||
}
|
||||
return sum.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public class Xp3Stream : Stream
|
||||
{
|
||||
ArcView m_file;
|
||||
Xp3Entry m_entry;
|
||||
IEnumerator<Xp3Segment> m_segment;
|
||||
Stream m_stream;
|
||||
long m_offset = 0;
|
||||
bool m_eof = false;
|
||||
|
||||
public override bool CanRead { get { return true; } }
|
||||
public override bool CanSeek { get { return false; } }
|
||||
public override bool CanWrite { get { return false; } }
|
||||
public override long Length { get { return m_entry.UnpackedSize; } }
|
||||
public override long Position
|
||||
{
|
||||
get { return m_offset; }
|
||||
set { throw new NotSupportedException ("Xp3Stream.Position not supported."); }
|
||||
}
|
||||
|
||||
public Xp3Stream (ArcView file, Xp3Entry entry)
|
||||
{
|
||||
m_file = file;
|
||||
m_entry = entry;
|
||||
m_segment = entry.Segments.GetEnumerator();
|
||||
NextSegment();
|
||||
}
|
||||
|
||||
private void NextSegment ()
|
||||
{
|
||||
if (!m_segment.MoveNext())
|
||||
{
|
||||
m_eof = true;
|
||||
return;
|
||||
}
|
||||
if (null != m_stream)
|
||||
m_stream.Dispose();
|
||||
var segment = m_segment.Current;
|
||||
if (segment.IsCompressed)
|
||||
m_stream = new ZLibStream (m_file.CreateStream (segment.Offset, segment.PackedSize),
|
||||
CompressionMode.Decompress);
|
||||
else
|
||||
m_stream = m_file.CreateStream (segment.Offset, segment.Size);
|
||||
}
|
||||
|
||||
public override int Read (byte[] buffer, int offset, int count)
|
||||
{
|
||||
int total = 0;
|
||||
while (!m_eof && count > 0)
|
||||
{
|
||||
int read = m_stream.Read (buffer, offset, count);
|
||||
m_entry.Cipher.Decrypt (m_entry, m_offset, buffer, offset, read);
|
||||
m_offset += read;
|
||||
total += read;
|
||||
offset += read;
|
||||
count -= read;
|
||||
if (0 != count)
|
||||
NextSegment();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public override int ReadByte ()
|
||||
{
|
||||
int b = -1;
|
||||
while (!m_eof)
|
||||
{
|
||||
b = m_stream.ReadByte();
|
||||
if (-1 != b)
|
||||
{
|
||||
b = m_entry.Cipher.Decrypt (m_entry, m_offset++, (byte)b);
|
||||
break;
|
||||
}
|
||||
NextSegment();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
public override void Flush ()
|
||||
{
|
||||
}
|
||||
|
||||
public override long Seek (long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotSupportedException ("Xp3Stream.Seek method is not supported");
|
||||
}
|
||||
|
||||
public override void SetLength (long length)
|
||||
{
|
||||
throw new NotSupportedException ("Xp3Stream.SetLength method is not supported");
|
||||
}
|
||||
|
||||
public override void Write (byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotSupportedException ("Xp3Stream.Write method is not supported");
|
||||
}
|
||||
|
||||
public override void WriteByte (byte value)
|
||||
{
|
||||
throw new NotSupportedException("Xp3Stream.WriteByte method is not supported");
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
bool disposed = false;
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
m_file = null;
|
||||
if (null != m_stream)
|
||||
{
|
||||
m_stream.Dispose();
|
||||
m_stream = null;
|
||||
}
|
||||
disposed = true;
|
||||
base.Dispose (disposing);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public abstract class ICrypt
|
||||
{
|
||||
public abstract byte Decrypt (Xp3Entry entry, long offset, byte value);
|
||||
|
||||
public virtual void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
values[pos+i] = this.Decrypt (entry, offset+i, values[pos+i]);
|
||||
}
|
||||
|
||||
public virtual void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
|
||||
{
|
||||
throw new NotImplementedException ("Encryption method not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
public class NoCrypt : ICrypt
|
||||
{
|
||||
public override byte Decrypt (Xp3Entry entry, long offset, byte value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
internal class FateCrypt : ICrypt
|
||||
{
|
||||
public override byte Decrypt (Xp3Entry entry, long offset, byte value)
|
||||
{
|
||||
byte result = (byte)(value ^ 0x36);
|
||||
if (0x13 == offset)
|
||||
result ^= 1;
|
||||
else if (0x2ea29 == offset)
|
||||
result ^= 3;
|
||||
return result;
|
||||
}
|
||||
|
||||
public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
values[pos+i] ^= 0x36;
|
||||
}
|
||||
if (offset > 0x2ea29)
|
||||
return;
|
||||
if (offset + count > 0x2ea29)
|
||||
values[pos+0x2ea29-offset] ^= 3;
|
||||
if (offset > 0x13)
|
||||
return;
|
||||
if (offset + count > 0x13)
|
||||
values[pos+0x13-offset] ^= 1;
|
||||
}
|
||||
|
||||
public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
|
||||
{
|
||||
Decrypt (entry, offset, values, pos, count);
|
||||
}
|
||||
}
|
||||
|
||||
internal class XorCrypt : ICrypt
|
||||
{
|
||||
private byte m_key;
|
||||
|
||||
public byte Key
|
||||
{
|
||||
get { return m_key; }
|
||||
set { m_key = value; }
|
||||
}
|
||||
|
||||
public XorCrypt (uint key)
|
||||
{
|
||||
m_key = (byte)key;
|
||||
}
|
||||
|
||||
public override byte Decrypt (Xp3Entry entry, long offset, byte value)
|
||||
{
|
||||
return (byte)(value ^ m_key);
|
||||
}
|
||||
|
||||
public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
values[pos+i] ^= m_key;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
|
||||
{
|
||||
Decrypt (entry, offset, values, pos, count);
|
||||
}
|
||||
}
|
||||
|
||||
internal class SwanSongCrypt : ICrypt
|
||||
{
|
||||
static private byte Adjust (uint hash, out int shift)
|
||||
{
|
||||
int cl = (int)(hash & 0xff);
|
||||
if (0 == cl) cl = 0x0f;
|
||||
shift = cl & 7;
|
||||
int ch = (int)((hash >> 8) & 0xff);
|
||||
if (0 == ch) ch = 0xf0;
|
||||
return (byte)ch;
|
||||
}
|
||||
|
||||
public override byte Decrypt (Xp3Entry entry, long offset, byte value)
|
||||
{
|
||||
int shift;
|
||||
byte xor = Adjust (entry.Hash, out shift);
|
||||
uint data = (uint)(value ^ xor);
|
||||
return (byte)((data >> shift) | (data << (8 - shift)));
|
||||
}
|
||||
|
||||
public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
|
||||
{
|
||||
int shift;
|
||||
byte xor = Adjust (entry.Hash, out shift);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
uint data = (uint)(values[pos+i] ^ xor);
|
||||
values[pos+i] = (byte)((data >> shift) | (data << (8 - shift)));
|
||||
}
|
||||
}
|
||||
|
||||
public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
|
||||
{
|
||||
int shift;
|
||||
byte xor = Adjust (entry.Hash, out shift);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
uint data = values[pos+i];
|
||||
data = (byte)((data << shift) | (data >> (8 - shift)));
|
||||
values[pos+i] = (byte)(data ^ xor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class SeitenCrypt : ICrypt
|
||||
{
|
||||
public override byte Decrypt (Xp3Entry entry, long offset, byte value)
|
||||
{
|
||||
uint key = entry.Hash ^ (uint)offset;
|
||||
if (0 != (key & 2))
|
||||
{
|
||||
int ecx = (int)key & 0x18;
|
||||
value ^= (byte)((key >> ecx) | (key >> (ecx & 8)));
|
||||
}
|
||||
if (0 != (key & 4))
|
||||
{
|
||||
value += (byte)key;
|
||||
}
|
||||
if (0 != (key & 8))
|
||||
{
|
||||
value -= (byte)(key >> (int)(key & 0x10));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
uint key = entry.Hash ^ (uint)offset;
|
||||
if (0 != (key & 8))
|
||||
{
|
||||
values[pos+i] += (byte)(key >> (int)(key & 0x10));
|
||||
}
|
||||
if (0 != (key & 4))
|
||||
{
|
||||
values[pos+i] -= (byte)key;
|
||||
}
|
||||
if (0 != (key & 2))
|
||||
{
|
||||
int ecx = (int)key & 0x18;
|
||||
values[pos+i] ^= (byte)((key >> ecx) | (key >> (ecx & 8)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class OkibaCrypt : ICrypt
|
||||
{
|
||||
public override byte Decrypt (Xp3Entry entry, long offset, byte value)
|
||||
{
|
||||
if (offset < 0x65)
|
||||
return (byte)(value ^ (byte)(entry.Hash >> 4));
|
||||
uint key = entry.Hash;
|
||||
// 0,1,2,3 -> 1,0,3,2
|
||||
key = ((key & 0xff0000) << 8) | ((key & 0xff000000) >> 8)
|
||||
| ((key & 0xff00) >> 8) | ((key & 0xff) << 8);
|
||||
key >>= 8 * ((int)(offset - 0x65) & 3);
|
||||
return (byte)(value ^ (byte)key);
|
||||
}
|
||||
|
||||
public override void Decrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
|
||||
{
|
||||
int i = 0;
|
||||
if (offset < 0x65)
|
||||
{
|
||||
uint key = entry.Hash >> 4;
|
||||
int limit = Math.Min (count, (int)(0x65 - offset));
|
||||
for (; i < limit; ++i)
|
||||
{
|
||||
values[pos+i] ^= (byte)key;
|
||||
++offset;
|
||||
}
|
||||
}
|
||||
if (i < count)
|
||||
{
|
||||
offset -= 0x65;
|
||||
uint key = entry.Hash;
|
||||
key = ((key & 0xff0000) << 8) | ((key & 0xff000000) >> 8)
|
||||
| ((key & 0xff00) >> 8) | ((key & 0xff) << 8);
|
||||
do
|
||||
{
|
||||
values[pos+i] ^= (byte)(key >> (8 * ((int)offset & 3)));
|
||||
++offset;
|
||||
}
|
||||
while (++i < count);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Encrypt (Xp3Entry entry, long offset, byte[] values, int pos, int count)
|
||||
{
|
||||
Decrypt (entry, offset, values, pos, count);
|
||||
}
|
||||
}
|
||||
}
|
193
ArcFormats/ArcYPF.cs
Normal file
193
ArcFormats/ArcYPF.cs
Normal file
@ -0,0 +1,193 @@
|
||||
//! \file ArcYPF.cs
|
||||
//! \date Mon Jul 14 14:40:06 2014
|
||||
//! \brief YPF resource format implementation.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using ZLibNet;
|
||||
using GameRes.Formats.Strings;
|
||||
using GameRes.Formats.Properties;
|
||||
|
||||
namespace GameRes.Formats
|
||||
{
|
||||
[Export(typeof(ArchiveFormat))]
|
||||
public class YpfOpener : ArchiveFormat
|
||||
{
|
||||
public override string Tag { get { return "YPF"; } }
|
||||
public override string Description { get { return "Yu-Ris game engine resource archive"; } }
|
||||
public override uint Signature { get { return 0x00465059; } }
|
||||
|
||||
private const uint DefaultKey = 0xffffffff;
|
||||
|
||||
public override ArcFile TryOpen (ArcView file)
|
||||
{
|
||||
uint count = file.View.ReadUInt32 (8);
|
||||
uint dir_size = file.View.ReadUInt32 (12);
|
||||
if (dir_size < count * 0x17)
|
||||
return null;
|
||||
if (0 != ((count - 1) >> 20))
|
||||
return null;
|
||||
// Reserve (0x20, dir_size)
|
||||
var parser = new Parser (file, count, dir_size);
|
||||
|
||||
uint key = QueryEncryptionKey();
|
||||
var dir = parser.ScanDir (key);
|
||||
if (0 == dir.Count)
|
||||
return null;
|
||||
|
||||
return new ArcFile (file, this, dir);
|
||||
}
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
{
|
||||
var input = arc.File.CreateStream (entry.Offset, entry.Size);
|
||||
var packed_entry = entry as PackedEntry;
|
||||
if (null == packed_entry || !packed_entry.IsPacked)
|
||||
return input;
|
||||
else
|
||||
return new ZLibStream (input, CompressionMode.Decompress);
|
||||
}
|
||||
|
||||
uint m_last_key = Settings.Default.YPFKey;
|
||||
|
||||
uint QueryEncryptionKey ()
|
||||
{
|
||||
uint? key = m_last_key;
|
||||
if (m_last_key > 0xff)
|
||||
key = null;
|
||||
var widget = new GUI.WidgetYPF (key);
|
||||
var args = new ParametersRequestEventArgs
|
||||
{
|
||||
Notice = arcStrings.YPFNotice,
|
||||
InputWidget = widget,
|
||||
};
|
||||
FormatCatalog.Instance.InvokeParametersRequest (this, args);
|
||||
if (!args.InputResult)
|
||||
throw new OperationCanceledException();
|
||||
|
||||
key = widget.GetKey();
|
||||
m_last_key = null != key && key.Value < 0x100 ? key.Value : DefaultKey;
|
||||
Settings.Default.YPFKey = m_last_key;
|
||||
return m_last_key;
|
||||
}
|
||||
|
||||
private class Parser
|
||||
{
|
||||
ArcView m_file;
|
||||
uint m_version;
|
||||
uint m_count;
|
||||
uint m_dir_size;
|
||||
|
||||
public Parser (ArcView file, uint count, uint dir_size)
|
||||
{
|
||||
m_file = file;
|
||||
m_count = count;
|
||||
m_dir_size = dir_size;
|
||||
m_version = file.View.ReadUInt32 (4);
|
||||
}
|
||||
// 4-name_checksum, 1-name_count, *-name, 1-file_type
|
||||
// 1-pack_flag, 4-size, 4-packed_size, 4-offset, 4-packed_adler32
|
||||
|
||||
public List<Entry> ScanDir (uint key)
|
||||
{
|
||||
uint dir_offset = 0x20;
|
||||
uint dir_remaining = m_dir_size;
|
||||
uint num;
|
||||
var dir = new List<Entry> ((int)m_count);
|
||||
for (num = 0; num < m_count; ++num)
|
||||
{
|
||||
if (dir_remaining < 0x17)
|
||||
break;
|
||||
dir_remaining -= 0x17;
|
||||
|
||||
uint name_size = Decrypt ((byte)(m_file.View.ReadByte (dir_offset+4) ^ 0xff));
|
||||
if (name_size > dir_remaining)
|
||||
break;
|
||||
dir_remaining -= name_size;
|
||||
dir_offset += 5;
|
||||
if (0 == name_size)
|
||||
break;
|
||||
if (0xffffffff == key)
|
||||
{
|
||||
if (name_size < 4)
|
||||
break;
|
||||
// assume filename contains '.' and 3-characters extension.
|
||||
key = (uint)(m_file.View.ReadByte (dir_offset+name_size-4) ^ 0x2e);
|
||||
}
|
||||
byte[] raw_name = new byte[name_size];
|
||||
for (int i = 0; i < name_size; ++i)
|
||||
{
|
||||
raw_name[i] = (byte)(m_file.View.ReadByte (dir_offset) ^ key);
|
||||
++dir_offset;
|
||||
}
|
||||
string name = Encodings.cp932.GetString (raw_name);
|
||||
// 0x0F7: 0-ybn, 1-bmp, 2-png, 3-jpg, 4-gif, 5-avi, 6-wav, 7-ogg, 8-psd
|
||||
// 0x122, 0x12C, 0x196: 0-ybn, 1-bmp, 2-png, 3-jpg, 4-gif, 5-wav, 6-ogg, 7-psd
|
||||
int type_id = m_file.View.ReadByte (dir_offset);
|
||||
string type = "";
|
||||
switch (type_id)
|
||||
{
|
||||
case 0:
|
||||
type = "script";
|
||||
break;
|
||||
case 1: case 2: case 3: case 4:
|
||||
type = "image";
|
||||
break;
|
||||
case 5:
|
||||
type = 0xf7 == m_version ? "video" : "audio";
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
type = "audio";
|
||||
break;
|
||||
}
|
||||
var entry = new PackedEntry { Name = name, Type = type };
|
||||
entry.IsPacked = 1 == m_file.View.ReadByte (dir_offset+1);
|
||||
entry.UnpackedSize = m_file.View.ReadUInt32 (dir_offset+2);
|
||||
entry.Size = m_file.View.ReadUInt32 (dir_offset+6);
|
||||
entry.Offset = m_file.View.ReadUInt32 (dir_offset+10);
|
||||
if (entry.CheckPlacement (m_file.MaxOffset))
|
||||
dir.Add (entry);
|
||||
dir_offset += 0x12;
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
static readonly byte[] s_crypt_table = {
|
||||
0x03,0x48,0x06,0x35, // 0x122, 0x196
|
||||
0x0C,0x10,0x11,0x19,0x1C,0x1E, // 0x0F7
|
||||
0x09,0x0B,0x0D,0x13,0x15,0x1B, // 0x12C
|
||||
0x20,0x23,0x26,0x29,
|
||||
0x2C,0x2F,0x2E,0x32,
|
||||
};
|
||||
// 0xFF 0x0F7 "Four-Leaf" adler32
|
||||
// 0x34 0x122 "Neko Koi!" crc32
|
||||
// 0x28 0x12C "Suzukaze no Melt" (no recovery - 00 00 00 00)
|
||||
// 0xFF 0x196 "Mamono Musume-tachi to no Rakuen ~Slime & Scylla~"
|
||||
|
||||
public uint Decrypt (byte value)
|
||||
{
|
||||
int pos = s_crypt_table.Length - 0x14;
|
||||
if (m_version >= 0x100)
|
||||
{
|
||||
pos -= 4;
|
||||
if (m_version >= 0x12c && m_version < 0x196)
|
||||
pos += 10;
|
||||
}
|
||||
pos = Array.FindIndex (s_crypt_table, pos, x => x == value);
|
||||
if (-1 == pos)
|
||||
return value;
|
||||
if (0 != (pos & 1))
|
||||
return s_crypt_table[pos-1];
|
||||
else
|
||||
return s_crypt_table[pos+1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
677
ArcFormats/Blowfish.cs
Normal file
677
ArcFormats/Blowfish.cs
Normal file
@ -0,0 +1,677 @@
|
||||
/****************************************************************************
|
||||
|
|
||||
| Copyright (c) 2007 Novell, Inc.
|
||||
| All Rights Reserved.
|
||||
|
|
||||
| This program is free software; you can redistribute it and/or
|
||||
| modify it under the terms of version 2 of the GNU General Public License as
|
||||
| published by the Free Software Foundation.
|
||||
|
|
||||
| This program is distributed in the hope that it will be useful,
|
||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
| GNU General Public License for more details.
|
||||
|
|
||||
| You should have received a copy of the GNU General Public License
|
||||
| along with this program; if not, contact Novell, Inc.
|
||||
|
|
||||
| To contact Novell about this file by physical or electronic mail,
|
||||
| you may find current contact information at www.novell.com
|
||||
|
|
||||
| Author: Russ Young
|
||||
| Thanks to: Bruce Schneier / Counterpane Labs
|
||||
| for the Blowfish encryption algorithm and
|
||||
| reference implementation. http://www.schneier.com/blowfish.html
|
||||
|***************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace Simias.Encryption
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that provides blowfish encryption.
|
||||
/// </summary>
|
||||
public class Blowfish
|
||||
{
|
||||
const int N = 16;
|
||||
const int KEYBYTES = 8;
|
||||
|
||||
static uint[] _P =
|
||||
{
|
||||
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
|
||||
0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
||||
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b
|
||||
};
|
||||
static uint[,] _S =
|
||||
{
|
||||
{
|
||||
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
|
||||
0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
|
||||
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
|
||||
0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
||||
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
|
||||
0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
|
||||
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
|
||||
0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
||||
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
|
||||
0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
|
||||
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
|
||||
0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
||||
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
|
||||
0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
|
||||
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
|
||||
0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
||||
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
|
||||
0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
|
||||
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
|
||||
0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
||||
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
|
||||
0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
|
||||
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
|
||||
0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
||||
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
|
||||
0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
|
||||
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
|
||||
0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
||||
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
|
||||
0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
|
||||
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
|
||||
0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
||||
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
|
||||
0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
|
||||
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
|
||||
0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
||||
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
|
||||
0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
|
||||
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
|
||||
0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
||||
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
|
||||
0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
||||
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
|
||||
},
|
||||
{
|
||||
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
|
||||
0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
|
||||
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
|
||||
0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
||||
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
|
||||
0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
|
||||
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
|
||||
0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
||||
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
|
||||
0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
|
||||
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
|
||||
0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
||||
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
|
||||
0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
|
||||
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
|
||||
0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
||||
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
|
||||
0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
|
||||
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
|
||||
0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
||||
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
|
||||
0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
|
||||
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
|
||||
0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
||||
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
|
||||
0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
|
||||
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
|
||||
0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
||||
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
|
||||
0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
|
||||
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
|
||||
0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
||||
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
|
||||
0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
|
||||
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
|
||||
0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
||||
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
|
||||
0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
|
||||
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
|
||||
0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
||||
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
|
||||
0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
|
||||
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
|
||||
},
|
||||
{
|
||||
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
|
||||
0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
|
||||
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
|
||||
0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
||||
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
|
||||
0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
|
||||
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
|
||||
0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
||||
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
|
||||
0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
|
||||
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
|
||||
0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
||||
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
|
||||
0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
|
||||
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
|
||||
0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
||||
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
|
||||
0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
|
||||
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
|
||||
0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
||||
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
|
||||
0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
|
||||
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
|
||||
0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
||||
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
|
||||
0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
|
||||
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
|
||||
0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
||||
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
|
||||
0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
|
||||
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
|
||||
0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
||||
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
|
||||
0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
|
||||
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
|
||||
0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
||||
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
|
||||
0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
|
||||
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
|
||||
0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
||||
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
|
||||
0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
|
||||
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
|
||||
},
|
||||
{
|
||||
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
|
||||
0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
||||
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
|
||||
0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
||||
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
|
||||
0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
|
||||
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
|
||||
0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
||||
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
|
||||
0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
|
||||
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
|
||||
0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
||||
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
|
||||
0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
|
||||
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
|
||||
0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
||||
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
|
||||
0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
|
||||
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
|
||||
0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
||||
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
|
||||
0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
|
||||
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
|
||||
0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
||||
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
|
||||
0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
|
||||
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
|
||||
0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
||||
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
|
||||
0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
|
||||
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
|
||||
0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
||||
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
|
||||
0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
|
||||
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
|
||||
0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
||||
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
|
||||
0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
|
||||
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
|
||||
0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
||||
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
|
||||
0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
||||
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
|
||||
}
|
||||
};
|
||||
|
||||
uint[] P;
|
||||
uint[,] S;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs and initializes a blowfish instance with the supplied key.
|
||||
/// </summary>
|
||||
/// <param name="key">The key to cipher with.</param>
|
||||
public Blowfish(byte[] key)
|
||||
{
|
||||
short i;
|
||||
short j;
|
||||
short k;
|
||||
uint data;
|
||||
uint datal;
|
||||
uint datar;
|
||||
|
||||
P = _P.Clone() as uint[];
|
||||
S = _S.Clone() as uint[,];
|
||||
|
||||
j = 0;
|
||||
for (i = 0; i < N + 2; ++i)
|
||||
{
|
||||
data = 0x00000000;
|
||||
for (k = 0; k < 4; ++k)
|
||||
{
|
||||
data = (data << 8) | key[j];
|
||||
j++;
|
||||
if (j >= key.Length)
|
||||
{
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
P[i] = P[i] ^ data;
|
||||
}
|
||||
|
||||
datal = 0x00000000;
|
||||
datar = 0x00000000;
|
||||
|
||||
for (i = 0; i < N + 2; i += 2)
|
||||
{
|
||||
Encipher(ref datal, ref datar);
|
||||
P[i] = datal;
|
||||
P[i + 1] = datar;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
for (j = 0; j < 256; j += 2)
|
||||
{
|
||||
Encipher(ref datal, ref datar);
|
||||
|
||||
S[i,j] = datal;
|
||||
S[i,j + 1] = datar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <returns></returns>
|
||||
private uint F(uint x)
|
||||
{
|
||||
ushort a;
|
||||
ushort b;
|
||||
ushort c;
|
||||
ushort d;
|
||||
uint y;
|
||||
|
||||
d = (ushort)(x & 0x00FF);
|
||||
x >>= 8;
|
||||
c = (ushort)(x & 0x00FF);
|
||||
x >>= 8;
|
||||
b = (ushort)(x & 0x00FF);
|
||||
x >>= 8;
|
||||
a = (ushort)(x & 0x00FF);
|
||||
//y = ((S[0][a] + S[1][b]) ^ S[2][c]) + S[3][d];
|
||||
y = S[0,a] + S[1,b];
|
||||
y = y ^ S[2,c];
|
||||
y = y + S[3,d];
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a byte array in place.
|
||||
/// </summary>
|
||||
/// <param name="data">The array to encrypt.</param>
|
||||
/// <param name="length">The amount to encrypt.</param>
|
||||
public void Encipher(byte[] data, int length)
|
||||
{
|
||||
uint xl, xr;
|
||||
if ((length % 8) != 0)
|
||||
throw new Exception("Invalid Length");
|
||||
for (int i = 0; i < length; i+=8)
|
||||
{
|
||||
// Encode the data in 8 byte blocks.
|
||||
xl = (uint)((data[i] << 24) | (data[i+1] << 16) | (data[i+2] << 8) | data[i+3]);
|
||||
xr = (uint)((data[i+4] << 24) | (data[i+5] << 16) | (data[i+6] << 8) | data[i+7]);
|
||||
Encipher(ref xl, ref xr);
|
||||
// Now Replace the data.
|
||||
data[i] = (byte)(xl >> 24);
|
||||
data[i+1] = (byte)(xl >> 16);
|
||||
data[i+2] = (byte)(xl >> 8);
|
||||
data[i+3] = (byte)(xl);
|
||||
data[i+4] = (byte)(xr >> 24);
|
||||
data[i+5] = (byte)(xr >> 16);
|
||||
data[i+6] = (byte)(xr >> 8);
|
||||
data[i+7] = (byte)(xr);}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts 8 bytes of data (1 block)
|
||||
/// </summary>
|
||||
/// <param name="xl">The left part of the 8 bytes.</param>
|
||||
/// <param name="xr">The right part of the 8 bytes.</param>
|
||||
private void Encipher(ref uint xl, ref uint xr)
|
||||
{
|
||||
uint Xl;
|
||||
uint Xr;
|
||||
uint temp;
|
||||
short i;
|
||||
|
||||
Xl = xl;
|
||||
Xr = xr;
|
||||
|
||||
for (i = 0; i < N; ++i)
|
||||
{
|
||||
Xl = Xl ^ P[i];
|
||||
Xr = F(Xl) ^ Xr;
|
||||
|
||||
temp = Xl;
|
||||
Xl = Xr;
|
||||
Xr = temp;
|
||||
}
|
||||
|
||||
temp = Xl;
|
||||
Xl = Xr;
|
||||
Xr = temp;
|
||||
|
||||
Xr = Xr ^ P[N];
|
||||
Xl = Xl ^ P[N + 1];
|
||||
|
||||
xl = Xl;
|
||||
xr = Xr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a byte array in place.
|
||||
/// </summary>
|
||||
/// <param name="data">The array to decrypt.</param>
|
||||
/// <param name="length">The amount to decrypt.</param>
|
||||
public void Decipher(byte[] data, int length)
|
||||
{
|
||||
uint xl, xr;
|
||||
if ((length % 8) != 0)
|
||||
throw new Exception("Invalid Length");
|
||||
for (int i = 0; i < length; i += 8)
|
||||
{
|
||||
// Encode the data in 8 byte blocks.
|
||||
xl = (uint)(data[i] | (data[i+1] << 8) | (data[i+2] << 16) | (data[i+3] << 24));
|
||||
xr = (uint)(data[i+4] | (data[i+5] << 8) | (data[i+6] << 16) | (data[i+7] << 24));
|
||||
Decipher(ref xl, ref xr);
|
||||
// Now Replace the data.
|
||||
data[i] = (byte)(xl);
|
||||
data[i+1] = (byte)(xl >> 8);
|
||||
data[i+2] = (byte)(xl >> 16);
|
||||
data[i+3] = (byte)(xl >> 24);
|
||||
data[i+4] = (byte)(xr);
|
||||
data[i+5] = (byte)(xr >> 8);
|
||||
data[i+6] = (byte)(xr >> 16);
|
||||
data[i+7] = (byte)(xr >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts 8 bytes of data (1 block)
|
||||
/// </summary>
|
||||
/// <param name="xl">The left part of the 8 bytes.</param>
|
||||
/// <param name="xr">The right part of the 8 bytes.</param>
|
||||
public void Decipher(ref uint xl, ref uint xr)
|
||||
{
|
||||
uint Xl;
|
||||
uint Xr;
|
||||
uint temp;
|
||||
short i;
|
||||
|
||||
Xl = xl;
|
||||
Xr = xr;
|
||||
|
||||
for (i = N + 1; i > 1; --i)
|
||||
{
|
||||
Xl = Xl ^ P[i];
|
||||
Xr = F(Xl) ^ Xr;
|
||||
|
||||
/* Exchange Xl and Xr */
|
||||
temp = Xl;
|
||||
Xl = Xr;
|
||||
Xr = temp;
|
||||
}
|
||||
|
||||
/* Exchange Xl and Xr */
|
||||
temp = Xl;
|
||||
Xl = Xr;
|
||||
Xr = temp;
|
||||
|
||||
Xr = Xr ^ P[1];
|
||||
Xl = Xl ^ P[0];
|
||||
|
||||
xl = Xl;
|
||||
xr = Xr;
|
||||
}
|
||||
}
|
||||
|
||||
public class BlowfishStream : Stream
|
||||
{
|
||||
class CBState : IAsyncResult
|
||||
{
|
||||
internal AsyncCallback callback;
|
||||
internal object state;
|
||||
internal byte[] buffer;
|
||||
internal IAsyncResult result;
|
||||
internal CBState(AsyncCallback callback, object state, byte[] buffer)
|
||||
{
|
||||
this.callback = callback;
|
||||
this.state = state;
|
||||
this.buffer = buffer;
|
||||
}
|
||||
#region IAsyncResult Members
|
||||
|
||||
public object AsyncState
|
||||
{
|
||||
get
|
||||
{
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CompletedSynchronously
|
||||
{
|
||||
get
|
||||
{
|
||||
return result.CompletedSynchronously;
|
||||
}
|
||||
}
|
||||
|
||||
public System.Threading.WaitHandle AsyncWaitHandle
|
||||
{
|
||||
get
|
||||
{
|
||||
return result.AsyncWaitHandle;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsCompleted
|
||||
{
|
||||
get
|
||||
{
|
||||
return result.IsCompleted;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public enum Target
|
||||
{
|
||||
Encrypted,
|
||||
Normal
|
||||
};
|
||||
|
||||
Stream stream;
|
||||
Blowfish bf;
|
||||
Target target;
|
||||
|
||||
BlowfishStream(Stream stream, Blowfish bf, Target target)
|
||||
{
|
||||
this.stream = stream;
|
||||
this.bf = bf;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the stream support reads.
|
||||
/// </summary>
|
||||
public override bool CanRead
|
||||
{
|
||||
get {return stream.CanRead;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true is the stream supports seeks.
|
||||
/// </summary>
|
||||
public override bool CanSeek
|
||||
{
|
||||
get {return stream.CanSeek;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the stream supports writes.
|
||||
/// </summary>
|
||||
public override bool CanWrite
|
||||
{
|
||||
get {return stream.CanWrite;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the length of the stream.
|
||||
/// </summary>
|
||||
public override long Length
|
||||
{
|
||||
get {return stream.Length;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets the posistion of the stream.
|
||||
/// </summary>
|
||||
public override long Position
|
||||
{
|
||||
get {return stream.Position;}
|
||||
set {stream.Position = value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flushes the stream.
|
||||
/// </summary>
|
||||
public override void Flush()
|
||||
{
|
||||
stream.Flush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read data from the stream and encrypt it.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to read into.</param>
|
||||
/// <param name="offset">The offset in the buffer to begin storing data.</param>
|
||||
/// <param name="count">The number of bytes to read.</param>
|
||||
/// <returns></returns>
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
int bytesRead = stream.Read(buffer, offset, count);
|
||||
if (target == Target.Normal)
|
||||
bf.Encipher(buffer, bytesRead);
|
||||
else
|
||||
bf.Decipher(buffer, bytesRead);
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write data to the stream after decrypting it.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer containing the data to write.</param>
|
||||
/// <param name="offset">The offset in the buffer where the data begins.</param>
|
||||
/// <param name="count">The number of bytes to write.</param>
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (target == Target.Normal)
|
||||
bf.Decipher(buffer, count);
|
||||
else
|
||||
bf.Encipher(buffer, count);
|
||||
stream.Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <param name="callback"></param>
|
||||
/// <param name="state"></param>
|
||||
/// <returns></returns>
|
||||
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
||||
{
|
||||
CBState cbs = new CBState(callback, state, buffer);
|
||||
cbs.result = base.BeginRead (buffer, offset, count, new AsyncCallback(ReadComplete), cbs);
|
||||
return cbs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="asyncResult"></param>
|
||||
/// <returns></returns>
|
||||
public override int EndRead(IAsyncResult asyncResult)
|
||||
{
|
||||
CBState cbs = (CBState)asyncResult.AsyncState;
|
||||
int bytesRead = base.EndRead (cbs.result);
|
||||
if (target == Target.Normal)
|
||||
bf.Encipher(cbs.buffer, bytesRead);
|
||||
else
|
||||
bf.Decipher(cbs.buffer, bytesRead);
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The Read has completed.
|
||||
/// </summary>
|
||||
/// <param name="result">The result of the async write.</param>
|
||||
private void ReadComplete(IAsyncResult result)
|
||||
{
|
||||
CBState cbs = (CBState)result.AsyncState;
|
||||
cbs.callback(cbs);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <param name="callback"></param>
|
||||
/// <param name="state"></param>
|
||||
/// <returns></returns>
|
||||
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
||||
{
|
||||
if (target == Target.Normal)
|
||||
bf.Decipher(buffer, count);
|
||||
else
|
||||
bf.Encipher(buffer, count);
|
||||
return base.BeginWrite (buffer, offset, count, callback, state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move the current stream posistion to the specified location.
|
||||
/// </summary>
|
||||
/// <param name="offset">The offset from the origin to seek.</param>
|
||||
/// <param name="origin">The origin to seek from.</param>
|
||||
/// <returns>The new position.</returns>
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
return stream.Seek(offset, origin);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the stream length.
|
||||
/// </summary>
|
||||
/// <param name="value">The length to set.</param>
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
stream.SetLength(value);
|
||||
}
|
||||
}
|
||||
}
|
342
ArcFormats/ImageHG3.cs
Normal file
342
ArcFormats/ImageHG3.cs
Normal file
@ -0,0 +1,342 @@
|
||||
//! \file ImageHG3.cs
|
||||
//! \date Sat Jul 19 17:31:09 2014
|
||||
//! \brief Frontwing HG3 image format implementation.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Media;
|
||||
using ZLibNet;
|
||||
using GameRes.Utility;
|
||||
|
||||
namespace GameRes.Formats
|
||||
{
|
||||
[Export(typeof(ImageFormat))]
|
||||
public class Hg3Format : ImageFormat
|
||||
{
|
||||
public override string Tag { get { return "HG3"; } }
|
||||
public override string Description { get { return "Frontwing proprietary image format"; } }
|
||||
public override uint Signature { get { return 0x332d4748; } }
|
||||
|
||||
public override ImageMetaData ReadMetaData (Stream stream)
|
||||
{
|
||||
var header = new byte[0x4c];
|
||||
if (0x4c != stream.Read (header, 0, header.Length))
|
||||
return null;
|
||||
if (LittleEndian.ToUInt32 (header, 0) != Signature)
|
||||
return null;
|
||||
if (LittleEndian.ToUInt32 (header, 4) != 0x0c)
|
||||
return null;
|
||||
if (!Binary.AsciiEqual (header, 0x14, "stdinfo\0"))
|
||||
return null;
|
||||
if (0x38 != LittleEndian.ToUInt32 (header, 0x1c))
|
||||
return null;
|
||||
if (0x20 != LittleEndian.ToUInt32 (header, 0x2c))
|
||||
return null;
|
||||
uint width = LittleEndian.ToUInt32 (header, 0x24); // @@L0
|
||||
uint height = LittleEndian.ToUInt32 (header, 0x28);
|
||||
int pos_x = LittleEndian.ToInt32 (header, 0x30);
|
||||
int pos_y = LittleEndian.ToInt32 (header, 0x34);
|
||||
pos_x -= LittleEndian.ToInt32 (header, 0x44);
|
||||
pos_y -= LittleEndian.ToInt32 (header, 0x48);
|
||||
|
||||
return new ImageMetaData
|
||||
{
|
||||
Width = width,
|
||||
Height = height,
|
||||
OffsetX = pos_x,
|
||||
OffsetY = pos_y,
|
||||
BPP = 32,
|
||||
};
|
||||
}
|
||||
|
||||
public override ImageData Read (Stream stream, ImageMetaData info)
|
||||
{
|
||||
stream.Position = 0x40;
|
||||
bool flipped = 0 == (stream.ReadByte() & 1) || info.OffsetY < 0;
|
||||
stream.Position = 0x4c;
|
||||
var header = new byte[0x28];
|
||||
if (0x28 != stream.Read (header, 0, header.Length))
|
||||
return null;
|
||||
if (!Binary.AsciiEqual (header, "img0000\0"))
|
||||
return null;
|
||||
uint data_size = LittleEndian.ToUInt32 (header, 0x0c);
|
||||
if (data_size < 0x18)
|
||||
return null;
|
||||
if (info.Height != LittleEndian.ToUInt32 (header, 0x14))
|
||||
return null;
|
||||
uint packed2_size = LittleEndian.ToUInt32 (header, 0x18);
|
||||
uint unpacked2_size = LittleEndian.ToUInt32 (header, 0x1c);
|
||||
uint packed1_size = LittleEndian.ToUInt32 (header, 0x20);
|
||||
uint unpacked1_size = LittleEndian.ToUInt32 (header, 0x24);
|
||||
if (packed2_size + packed1_size < packed2_size)
|
||||
return null;
|
||||
if (unpacked2_size + unpacked1_size < unpacked2_size)
|
||||
return null;
|
||||
|
||||
long data_pos = stream.Position;
|
||||
using (var unpacked2 = ZLibCompressor.DeCompress (stream))
|
||||
{
|
||||
stream.Position = data_pos + packed2_size;
|
||||
using (var unpacked1 = ZLibCompressor.DeCompress (stream))
|
||||
{
|
||||
var decoder = new Decoder (unpacked1.GetBuffer(), unpacked1_size,
|
||||
unpacked2.GetBuffer(), unpacked2_size,
|
||||
info.Width, info.Height);
|
||||
decoder.Unpack();
|
||||
var pixels = decoder.Data;
|
||||
int stride = (int)info.Width * 4;
|
||||
var bitmap = BitmapSource.Create ((int)info.Width, (int)info.Height, 96, 96,
|
||||
PixelFormats.Bgra32, null, pixels, stride);
|
||||
if (flipped)
|
||||
{
|
||||
var flipped_bitmap = new TransformedBitmap();
|
||||
flipped_bitmap.BeginInit();
|
||||
flipped_bitmap.Source = bitmap;
|
||||
flipped_bitmap.Transform = new ScaleTransform { ScaleY = -1 };
|
||||
flipped_bitmap.EndInit();
|
||||
bitmap = flipped_bitmap;
|
||||
}
|
||||
bitmap.Freeze();
|
||||
return new ImageData (bitmap, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write (Stream file, ImageData image)
|
||||
{
|
||||
throw new NotImplementedException ("Hg3Format.Write not implemented");
|
||||
}
|
||||
|
||||
class Decoder
|
||||
{
|
||||
byte[] m_in1;
|
||||
byte[] m_in2;
|
||||
byte[] m_image;
|
||||
uint m_in1_size;
|
||||
uint m_in2_size;
|
||||
uint m_dst_size;
|
||||
uint m_width;
|
||||
uint m_height;
|
||||
|
||||
public byte[] Data { get { return m_image; } }
|
||||
|
||||
public Decoder (byte[] in1, uint in1_size, byte[] in2, uint in2_size,
|
||||
uint width, uint height)
|
||||
{
|
||||
m_in1 = in1;
|
||||
m_in1_size = in1_size;
|
||||
m_in2 = in2;
|
||||
m_in2_size = in2_size;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_dst_size = width*height*4;
|
||||
m_image = new byte[(int)m_dst_size];
|
||||
}
|
||||
|
||||
uint esi;
|
||||
uint edi;
|
||||
uint eax;
|
||||
uint ebx;
|
||||
uint ecx;
|
||||
uint edx;
|
||||
|
||||
uint L0, L1, L2, L3, L4;
|
||||
uint m_plane;
|
||||
|
||||
public void Unpack ()
|
||||
{
|
||||
m_plane = 0;
|
||||
edi = 0;
|
||||
esi = 0;
|
||||
ebx = 0;
|
||||
eax = m_in1_size;
|
||||
L0 = m_in2_size;
|
||||
L1 = 0;
|
||||
bool skip_first = GetNextBit();
|
||||
Proc4();
|
||||
ecx = m_dst_size;
|
||||
if (eax > m_dst_size)
|
||||
throw new InvalidFormatException ("Underflow at Hg3Format.Decoder.Unpack()");
|
||||
m_dst_size -= eax;
|
||||
ecx >>= 2;
|
||||
L2 = eax;
|
||||
L3 = ecx;
|
||||
L4 = ecx;
|
||||
for (;;)
|
||||
{
|
||||
if (!skip_first)
|
||||
{
|
||||
// @@1:
|
||||
if (0 == L2)
|
||||
break;
|
||||
Proc4();
|
||||
ecx = eax;
|
||||
if (ecx > L2)
|
||||
throw new InvalidFormatException ("Overflow at Hg3Format.Decoder.Unpack()");
|
||||
L2 -= ecx;
|
||||
eax = 0;
|
||||
do
|
||||
Proc2();
|
||||
while (0 != --ecx);
|
||||
}
|
||||
// @@1a:
|
||||
if (0 == L2)
|
||||
break;
|
||||
Proc4();
|
||||
ecx = eax;
|
||||
if (ecx > L2 || ecx > L0)
|
||||
throw new InvalidFormatException ("Overflow (2) at Hg3Format.Decoder.Unpack()");
|
||||
L2 -= ecx;
|
||||
L0 -= ecx;
|
||||
do
|
||||
{
|
||||
eax = m_in2[L1++];
|
||||
Proc2();
|
||||
}
|
||||
while (0 != --ecx);
|
||||
skip_first = false;
|
||||
}
|
||||
// @@7:
|
||||
ecx = m_dst_size;
|
||||
esi = 0;
|
||||
if (0 != ecx)
|
||||
{
|
||||
eax = 0;
|
||||
do
|
||||
Proc2();
|
||||
while (0 != --ecx);
|
||||
}
|
||||
Proc6 (m_width, m_height);
|
||||
// @@9:
|
||||
eax = 0;
|
||||
edx = m_in1_size;
|
||||
}
|
||||
|
||||
void Proc2 () // @@2
|
||||
{
|
||||
m_image[edi] = (byte)eax;
|
||||
edi += 4;
|
||||
if (0 == --L3)
|
||||
{
|
||||
edi = ++m_plane;
|
||||
L3 = L4;
|
||||
}
|
||||
}
|
||||
|
||||
bool GetNextBit () // @@3
|
||||
{
|
||||
bool carry = 0 != (ebx & 1);
|
||||
ebx >>= 1;
|
||||
if (0 == ebx)
|
||||
{
|
||||
if (0 == m_in1_size--)
|
||||
throw new InvalidFormatException ("Hg3Format.Decoder.Underflow at GetNextBit()");
|
||||
ebx = (uint)(m_in1[esi++] | 0x100);
|
||||
carry = 0 != (ebx & 1);
|
||||
ebx >>= 1;
|
||||
}
|
||||
return carry;
|
||||
}
|
||||
|
||||
void Proc4 () // @@4
|
||||
{
|
||||
ecx = 0;
|
||||
eax = 0;
|
||||
do
|
||||
{
|
||||
if (ecx >= 0x20)
|
||||
throw new InvalidFormatException ("Hg3Format.Decoder.Overflow at Proc4");
|
||||
++ecx;
|
||||
}
|
||||
while (!GetNextBit());
|
||||
++eax;
|
||||
while (0 != --ecx)
|
||||
{
|
||||
eax += eax + (uint)(GetNextBit() ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Proc6 (uint width, uint height)
|
||||
{
|
||||
uint[] table = new uint[0x100];
|
||||
ecx = 0;
|
||||
for (uint i = 0; i < 0x100; ++i)
|
||||
{
|
||||
eax = 0xffffffff;
|
||||
edx = i;
|
||||
do
|
||||
{
|
||||
eax >>= 2;
|
||||
eax |= (edx & 3) << 30;
|
||||
eax >>= 6;
|
||||
edx >>= 2;
|
||||
}
|
||||
while (0 != (0x80 & eax));
|
||||
table[i] = eax;
|
||||
}
|
||||
ecx = width * height * 4;
|
||||
for (uint i = 0; i < ecx; i += 4)
|
||||
{
|
||||
eax = m_image[i];
|
||||
edx = table[eax];
|
||||
edx <<= 2;
|
||||
eax = m_image[i+1];
|
||||
edx += table[eax];
|
||||
edx <<= 2;
|
||||
eax = m_image[i+2];
|
||||
edx += table[eax];
|
||||
edx <<= 2;
|
||||
eax = m_image[i+3];
|
||||
edx += table[eax];
|
||||
m_image[i] = (byte)(edx);
|
||||
m_image[i+1] = (byte)(edx >> 8);
|
||||
m_image[i+2] = (byte)(edx >> 16);
|
||||
m_image[i+3] = (byte)(edx >> 24);
|
||||
}
|
||||
edi = 0;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
eax = m_image[edi];
|
||||
edx = (uint)(0 == (eax & 1) ? 0 : 0xff);
|
||||
eax >>= 1;
|
||||
eax ^= edx;
|
||||
m_image[edi++] = (byte)eax;
|
||||
}
|
||||
ecx = width;
|
||||
if (0 != --ecx)
|
||||
{
|
||||
ecx <<= 2;
|
||||
do
|
||||
{
|
||||
eax = m_image[edi];
|
||||
edx = (uint)(0 == (eax & 1) ? 0 : 0xff);
|
||||
eax >>= 1;
|
||||
eax ^= edx;
|
||||
eax += m_image[edi-4];
|
||||
m_image[edi++] = (byte)eax;
|
||||
}
|
||||
while (0 != --ecx);
|
||||
}
|
||||
ecx = height;
|
||||
if (0 != --ecx)
|
||||
{
|
||||
uint stride = width*4;
|
||||
ecx *= stride;
|
||||
do
|
||||
{
|
||||
eax = m_image[edi];
|
||||
edx = (uint)(0 == (eax & 1) ? 0 : 0xff);
|
||||
eax >>= 1;
|
||||
eax ^= edx;
|
||||
eax += m_image[edi-stride];
|
||||
m_image[edi++] = (byte)eax;
|
||||
}
|
||||
while (0 != --ecx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1006
ArcFormats/ImageTLG.cs
Normal file
1006
ArcFormats/ImageTLG.cs
Normal file
File diff suppressed because it is too large
Load Diff
477
ArcFormats/ImageWCG.cs
Normal file
477
ArcFormats/ImageWCG.cs
Normal file
@ -0,0 +1,477 @@
|
||||
//! \file ImageWCG.cs
|
||||
//! \date Sat Jul 19 23:07:32 2014
|
||||
//! \brief Liar-soft WCG image format implementation.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace GameRes.Formats
|
||||
{
|
||||
[Export(typeof(ImageFormat))]
|
||||
public class WcgFormat : ImageFormat
|
||||
{
|
||||
public override string Tag { get { return "WCG"; } }
|
||||
public override string Description { get { return "Liar-soft proprietary image format"; } }
|
||||
public override uint Signature { get { return 0x02714757; } }
|
||||
|
||||
public override ImageMetaData ReadMetaData (Stream stream)
|
||||
{
|
||||
if (0x57 != stream.ReadByte() || 0x47 != stream.ReadByte())
|
||||
return null;
|
||||
using (var file = new BinaryReader (stream, Encoding.ASCII, true))
|
||||
{
|
||||
uint flags = file.ReadUInt16();
|
||||
if (1 != (flags & 0x0f) || 0x20 != file.ReadByte() || 0 != file.ReadByte())
|
||||
return null;
|
||||
var meta = new ImageMetaData();
|
||||
file.BaseStream.Position = 8;
|
||||
meta.Width = file.ReadUInt32();
|
||||
meta.Height = file.ReadUInt32();
|
||||
meta.BPP = 32;
|
||||
return meta;
|
||||
}
|
||||
}
|
||||
|
||||
public override ImageData Read (Stream file, ImageMetaData info)
|
||||
{
|
||||
uint pixel_size = info.Width * info.Height;
|
||||
using (var reader = new Reader (file, pixel_size))
|
||||
{
|
||||
reader.Unpack();
|
||||
byte[] pixels = reader.Data;
|
||||
var bitmap = BitmapSource.Create ((int)info.Width, (int)info.Height, 96, 96,
|
||||
PixelFormats.Bgra32, null, pixels, (int)info.Width*4);
|
||||
bitmap.Freeze();
|
||||
return new ImageData (bitmap, info);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write (Stream file, ImageData image)
|
||||
{
|
||||
Stream stream = file;
|
||||
bool buffer_used = false;
|
||||
if (!stream.CanSeek)
|
||||
{
|
||||
stream = new MemoryStream();
|
||||
buffer_used = true;
|
||||
}
|
||||
try
|
||||
{
|
||||
using (var writer = new Writer (stream, image.Bitmap))
|
||||
{
|
||||
writer.Pack();
|
||||
}
|
||||
if (buffer_used)
|
||||
{
|
||||
stream.Position = 0;
|
||||
stream.CopyTo (file);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (buffer_used)
|
||||
stream.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private class Reader : IDisposable
|
||||
{
|
||||
private byte[] m_data;
|
||||
private BinaryReader m_input;
|
||||
private uint m_input_size;
|
||||
private ushort[] m_index;
|
||||
|
||||
private uint m_next_ptr;
|
||||
private uint m_next_size;
|
||||
private uint m_src;
|
||||
private uint m_src_size;
|
||||
private uint m_dst_size;
|
||||
private uint esi;
|
||||
private uint edi;
|
||||
|
||||
private uint m_index_length_limit;
|
||||
private int m_bits;
|
||||
|
||||
public byte[] Data { get { return m_data; } }
|
||||
|
||||
public Reader (Stream file, uint pixel_size)
|
||||
{
|
||||
m_data = new byte[pixel_size*4];
|
||||
m_input_size = (uint)file.Length;
|
||||
m_input = new BinaryReader (file, Encoding.ASCII, true);
|
||||
}
|
||||
|
||||
public void Unpack ()
|
||||
{
|
||||
m_next_ptr = 16;
|
||||
m_next_size = m_input_size-16;
|
||||
if (Unpack (2))
|
||||
Unpack (0);
|
||||
for (uint i = 3; i < m_data.Length; i += 4)
|
||||
m_data[i] = (byte)~m_data[i];
|
||||
}
|
||||
|
||||
private bool Unpack (uint offset)
|
||||
{
|
||||
m_src = m_next_ptr;
|
||||
m_src_size = m_next_size;
|
||||
m_dst_size = (uint)(m_data.Length / 4);
|
||||
if (m_src_size < 12)
|
||||
throw new InvalidFormatException ("Invalid file size");
|
||||
m_src_size -= 12;
|
||||
m_input.BaseStream.Position = m_next_ptr;
|
||||
uint unpacked_size = m_input.ReadUInt32();
|
||||
uint data_size = m_input.ReadUInt32();
|
||||
uint index_size = m_input.ReadUInt16(); // 8
|
||||
|
||||
if (unpacked_size != m_dst_size*2)
|
||||
throw new InvalidFormatException ("Invalid image size");
|
||||
|
||||
if (0 == index_size || index_size*2 > m_src_size)
|
||||
throw new InvalidFormatException ("Invalid palette size");
|
||||
|
||||
m_src_size -= index_size*2;
|
||||
if (data_size > m_src_size)
|
||||
throw new InvalidFormatException ("Invalid compressed data size");
|
||||
|
||||
esi = m_src + index_size*2 + 12;
|
||||
edi = offset;
|
||||
m_next_size = m_src_size - data_size;
|
||||
m_next_ptr = esi + data_size;
|
||||
m_src_size = data_size;
|
||||
return DecodeStream (index_size);
|
||||
}
|
||||
|
||||
void ReadIndex (uint index_size)
|
||||
{
|
||||
m_input.BaseStream.Position = m_src+12;
|
||||
m_index = new ushort[index_size];
|
||||
for (int i = 0; i < index_size; ++i)
|
||||
m_index[i] = m_input.ReadUInt16();
|
||||
}
|
||||
|
||||
bool DecodeStream (uint index_size)
|
||||
{
|
||||
ReadIndex (index_size);
|
||||
m_input.BaseStream.Position = esi;
|
||||
|
||||
bool small_index = index_size < 0x1002;
|
||||
m_index_length_limit = small_index ? 0x06u : 0x0eu;
|
||||
uint index_bit_length = small_index ? 3u : 4u;
|
||||
m_bits = 0;
|
||||
while (m_dst_size > 0)
|
||||
{
|
||||
uint dst_count = 1;
|
||||
uint index_length = GetBits (index_bit_length, 0);
|
||||
if (0 == index_length)
|
||||
{
|
||||
dst_count = GetBits (4, 0) + 2;
|
||||
index_length = GetBits (index_bit_length, 0);
|
||||
}
|
||||
if (0 == index_length)
|
||||
return false; // std::cerr << "zero index length\n";
|
||||
|
||||
uint index = GetIndex (index_length);
|
||||
if (index >= index_size)
|
||||
return false; // std::cerr << "invalid index\n";
|
||||
|
||||
if (dst_count > m_dst_size)
|
||||
return false;
|
||||
m_dst_size -= dst_count;
|
||||
ushort word = m_index[index];
|
||||
do {
|
||||
PutWord (word); // *(uint16_t*)edi = word;
|
||||
edi += 4;
|
||||
} while (0 != --dst_count);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PutWord (ushort word)
|
||||
{
|
||||
m_data[edi ] = (byte)(word & 0xff);
|
||||
m_data[edi+1] = (byte)(word >> 8);
|
||||
}
|
||||
|
||||
bool GetNextBit ()
|
||||
{
|
||||
bool carry = 0 != (m_bits & 0x80);
|
||||
m_bits <<= 1;
|
||||
if (0 == (m_bits & 0xff))
|
||||
{
|
||||
if (0 == m_src_size--)
|
||||
throw new InvalidFormatException ("Unexpected end of file");
|
||||
m_bits = (int)m_input.ReadByte();
|
||||
esi++;
|
||||
m_bits = (m_bits << 1) + 1;
|
||||
carry = 0 != (m_bits & 0x100);
|
||||
}
|
||||
return carry;
|
||||
}
|
||||
|
||||
uint GetIndex (uint count)
|
||||
{
|
||||
if (0 == --count)
|
||||
return GetNextBit() ? 1u : 0u;
|
||||
if (count < m_index_length_limit)
|
||||
return GetBits (count, 1);
|
||||
while (GetNextBit())
|
||||
{
|
||||
if (count >= 0x10)
|
||||
throw new InvalidFormatException ("Invalid index count");
|
||||
++count;
|
||||
}
|
||||
return GetBits (count, 1);
|
||||
}
|
||||
|
||||
uint GetBits (uint count, uint word)
|
||||
{
|
||||
do
|
||||
{
|
||||
bool carry = GetNextBit();
|
||||
word = (word << 1) + (carry ? 1u : 0u);
|
||||
}
|
||||
while (0 != --count);
|
||||
return word;
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
bool disposed = false;
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
if (disposing)
|
||||
m_input.Dispose();
|
||||
m_input = null;
|
||||
m_data = null;
|
||||
m_index = null;
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
private class Writer : IDisposable
|
||||
{
|
||||
private BinaryWriter m_out;
|
||||
private uint m_width;
|
||||
private uint m_height;
|
||||
private uint m_pixels;
|
||||
private byte[] m_data;
|
||||
|
||||
Dictionary<ushort, ushort> m_index = new Dictionary<ushort, ushort>();
|
||||
private uint m_base_length;
|
||||
private uint m_base_index_length;
|
||||
private int m_bits;
|
||||
|
||||
public Writer (Stream stream, BitmapSource bitmap)
|
||||
{
|
||||
m_width = (uint)bitmap.PixelWidth;
|
||||
m_height = (uint)bitmap.PixelHeight;
|
||||
m_pixels = m_width*m_height;
|
||||
if (bitmap.Format != PixelFormats.Bgra32)
|
||||
{
|
||||
var converted_bitmap = new FormatConvertedBitmap();
|
||||
converted_bitmap.BeginInit();
|
||||
converted_bitmap.Source = bitmap;
|
||||
converted_bitmap.DestinationFormat = PixelFormats.Bgra32;
|
||||
converted_bitmap.EndInit();
|
||||
bitmap = converted_bitmap;
|
||||
}
|
||||
m_data = new byte[m_pixels*4];
|
||||
bitmap.CopyPixels (m_data, bitmap.PixelWidth*4, 0);
|
||||
m_out = new BinaryWriter (stream, Encoding.ASCII, true);
|
||||
}
|
||||
|
||||
public void Pack ()
|
||||
{
|
||||
byte[] header = { (byte)'W', (byte)'G', 0x71, 2, 0x20, 0, 0, 0x40 };
|
||||
m_out.Write (header, 0, header.Length);
|
||||
m_out.Write (m_width);
|
||||
m_out.Write (m_height);
|
||||
|
||||
Pack (1, 0xff00);
|
||||
Pack (0, 0);
|
||||
}
|
||||
|
||||
ushort GetWord (int offset)
|
||||
{
|
||||
return (ushort)(m_data[offset*2] | m_data[offset*2+1] << 8);
|
||||
}
|
||||
|
||||
private void Pack (int data, ushort mask)
|
||||
{
|
||||
var header_pos = m_out.Seek (0, SeekOrigin.Current);
|
||||
m_out.Seek (12, SeekOrigin.Current);
|
||||
|
||||
BuildIndex (data, mask);
|
||||
bool small_index = m_index.Count < 0x1002;
|
||||
m_base_length = small_index ? 3u : 4u;
|
||||
m_base_index_length = small_index ? 7u : 15u;
|
||||
m_bits = 1;
|
||||
|
||||
// encode
|
||||
for (uint i = 0; i < m_pixels;)
|
||||
{
|
||||
ushort word = GetWord (data);
|
||||
data += 2;
|
||||
++i;
|
||||
ushort color = m_index[(ushort)(word^mask)];
|
||||
uint count = 1;
|
||||
while (i < m_pixels)
|
||||
{
|
||||
if (word != GetWord (data))
|
||||
break;
|
||||
++count;
|
||||
data += 2;
|
||||
++i;
|
||||
if (0x11 == count)
|
||||
break;
|
||||
}
|
||||
if (count > 1)
|
||||
{
|
||||
PutBits (m_base_length, 0);
|
||||
PutBits (4, count-2);
|
||||
}
|
||||
PutIndex (color);
|
||||
}
|
||||
Flush();
|
||||
|
||||
var end_pos = m_out.Seek (0, SeekOrigin.Current);
|
||||
uint data_size = (uint)(end_pos - header_pos - 12 - m_index.Count*2);
|
||||
m_out.Seek ((int)header_pos, SeekOrigin.Begin);
|
||||
m_out.Write (m_pixels*2u);
|
||||
m_out.Write (data_size);
|
||||
m_out.Write ((ushort)m_index.Count);
|
||||
m_out.Write ((ushort)(small_index ? 7 : 14)); // 0x0e
|
||||
m_out.Seek ((int)end_pos, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
void BuildIndex (int data, ushort mask)
|
||||
{
|
||||
m_index.Clear();
|
||||
uint[] freq_table = new uint[65536];
|
||||
for (var data_end = data + m_pixels*2; data < data_end; data += 2)
|
||||
freq_table[GetWord (data)^mask]++;
|
||||
|
||||
var index = new List<ushort>();
|
||||
for (int i = 0; i < freq_table.Length; ++i)
|
||||
{
|
||||
if (0 != freq_table[i])
|
||||
index.Add ((ushort)i);
|
||||
}
|
||||
index.Sort ((a, b) => freq_table[a] < freq_table[b] ? 1 : freq_table[a] == freq_table[b] ? 0 : -1);
|
||||
ushort j = 0;
|
||||
foreach (var color in index)
|
||||
{
|
||||
m_out.Write (color);
|
||||
m_index.Add (color, j++);
|
||||
}
|
||||
}
|
||||
|
||||
void Flush ()
|
||||
{
|
||||
if (1 != m_bits)
|
||||
{
|
||||
do
|
||||
m_bits <<= 1;
|
||||
while (0 == (m_bits & 0x100));
|
||||
m_out.Write ((byte)(m_bits & 0xff));
|
||||
m_bits = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void PutBit (bool bit)
|
||||
{
|
||||
m_bits <<= 1;
|
||||
m_bits |= bit ? 1 : 0;
|
||||
if (0 != (m_bits & 0x100))
|
||||
{
|
||||
m_out.Write ((byte)(m_bits & 0xff));
|
||||
m_bits = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void PutBits (uint length, uint x)
|
||||
{
|
||||
x <<= (int)(32-length);
|
||||
while (0 != length--)
|
||||
{
|
||||
PutBit (0 != (x & 0x80000000));
|
||||
x <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static uint GetBitsLength (ushort val)
|
||||
{
|
||||
uint length = 0;
|
||||
do
|
||||
{
|
||||
++length;
|
||||
val >>= 1;
|
||||
}
|
||||
while (0 != val);
|
||||
return length;
|
||||
}
|
||||
|
||||
void PutIndex (ushort index)
|
||||
{
|
||||
uint length = GetBitsLength (index);
|
||||
|
||||
if (length < m_base_index_length)
|
||||
{
|
||||
PutBits (m_base_length, length);
|
||||
if (1 == length)
|
||||
PutBit (index != 0);
|
||||
else
|
||||
PutBits (length-1, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
PutBits (m_base_length, m_base_index_length);
|
||||
for (uint i = m_base_index_length; i < length; ++i)
|
||||
PutBit (true);
|
||||
PutBit (false);
|
||||
PutBits (length-1, index);
|
||||
}
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
bool disposed = false;
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
if (disposing)
|
||||
m_out.Dispose();
|
||||
m_out = null;
|
||||
m_data = null;
|
||||
m_index = null;
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
36
ArcFormats/Properties/AssemblyInfo.cs
Normal file
36
ArcFormats/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("ArcFormats")]
|
||||
[assembly: AssemblyDescription("Visual Novel resources library")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ArcFormats")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014 mørkt")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("b9f45cc0-a966-4ccb-ac73-e99ee087567a")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
73
ArcFormats/Properties/Settings.Designer.cs
generated
Normal file
73
ArcFormats/Properties/Settings.Designer.cs
generated
Normal file
@ -0,0 +1,73 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.18444
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace GameRes.Formats.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")]
|
||||
public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("NotEncrypted")]
|
||||
public global::GameRes.Formats.NpaTitleId NPAScheme {
|
||||
get {
|
||||
return ((global::GameRes.Formats.NpaTitleId)(this["NPAScheme"]));
|
||||
}
|
||||
set {
|
||||
this["NPAScheme"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string XP3Scheme {
|
||||
get {
|
||||
return ((string)(this["XP3Scheme"]));
|
||||
}
|
||||
set {
|
||||
this["XP3Scheme"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("4294967295")]
|
||||
public uint YPFKey {
|
||||
get {
|
||||
return ((uint)(this["YPFKey"]));
|
||||
}
|
||||
set {
|
||||
this["YPFKey"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
public global::GameRes.Formats.IntEncryptionInfo INTEncryption {
|
||||
get {
|
||||
return ((global::GameRes.Formats.IntEncryptionInfo)(this["INTEncryption"]));
|
||||
}
|
||||
set {
|
||||
this["INTEncryption"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
18
ArcFormats/Properties/Settings.settings
Normal file
18
ArcFormats/Properties/Settings.settings
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="GameRes.Formats.Properties" GeneratedClassName="Settings">
|
||||
<Profiles />
|
||||
<Settings>
|
||||
<Setting Name="NPAScheme" Type="GameRes.Formats.NpaTitleId" Scope="User">
|
||||
<Value Profile="(Default)">NotEncrypted</Value>
|
||||
</Setting>
|
||||
<Setting Name="XP3Scheme" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
<Setting Name="YPFKey" Type="System.UInt32" Scope="User">
|
||||
<Value Profile="(Default)">4294967295</Value>
|
||||
</Setting>
|
||||
<Setting Name="INTEncryption" Type="GameRes.Formats.IntEncryptionInfo" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
36
ArcFormats/Settings.cs
Normal file
36
ArcFormats/Settings.cs
Normal file
@ -0,0 +1,36 @@
|
||||
namespace GameRes.Formats.Properties {
|
||||
|
||||
|
||||
// This class allows you to handle specific events on the settings class:
|
||||
// The SettingChanging event is raised before a setting's value is changed.
|
||||
// The PropertyChanged event is raised after a setting's value is changed.
|
||||
// The SettingsLoaded event is raised after the setting values are loaded.
|
||||
// The SettingsSaving event is raised before the setting values are saved.
|
||||
public sealed partial class Settings {
|
||||
|
||||
public Settings() {
|
||||
// // To add event handlers for saving and changing settings, uncomment the lines below:
|
||||
//
|
||||
// this.SettingChanging += this.SettingChangingEventHandler;
|
||||
//
|
||||
// this.SettingsSaving += this.SettingsSavingEventHandler;
|
||||
//
|
||||
|
||||
if (null != System.Windows.Application.Current)
|
||||
System.Windows.Application.Current.Exit += ApplicationExitHandler;
|
||||
}
|
||||
|
||||
void ApplicationExitHandler (object sender, System.Windows.ExitEventArgs args)
|
||||
{
|
||||
Default.Save();
|
||||
}
|
||||
|
||||
private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
|
||||
// Add code to handle the SettingChangingEvent event here.
|
||||
}
|
||||
|
||||
private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
|
||||
// Add code to handle the SettingsSaving event here.
|
||||
}
|
||||
}
|
||||
}
|
139
ArcFormats/Strings/arcStrings.Designer.cs
generated
Normal file
139
ArcFormats/Strings/arcStrings.Designer.cs
generated
Normal file
@ -0,0 +1,139 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.18444
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace GameRes.Formats.Strings {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class arcStrings {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal arcStrings() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GameRes.Formats.Strings.arcStrings", typeof(arcStrings).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Archive content is encrypted.
|
||||
///Choose appropriate encryption scheme..
|
||||
/// </summary>
|
||||
public static string ArcEncryptedNotice {
|
||||
get {
|
||||
return ResourceManager.GetString("ArcEncryptedNotice", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to no encryption.
|
||||
/// </summary>
|
||||
public static string ArcNoEncryption {
|
||||
get {
|
||||
return ResourceManager.GetString("ArcNoEncryption", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Numeric key.
|
||||
/// </summary>
|
||||
public static string INTLabelNumericKey {
|
||||
get {
|
||||
return ResourceManager.GetString("INTLabelNumericKey", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Passphrase.
|
||||
/// </summary>
|
||||
public static string INTLabelPassphrase {
|
||||
get {
|
||||
return ResourceManager.GetString("INTLabelPassphrase", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Scheme.
|
||||
/// </summary>
|
||||
public static string INTLabelScheme {
|
||||
get {
|
||||
return ResourceManager.GetString("INTLabelScheme", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Archive directory is encrypted.
|
||||
///Enter archive encryption key or choose
|
||||
///predefined encryption scheme..
|
||||
/// </summary>
|
||||
public static string INTNotice {
|
||||
get {
|
||||
return ResourceManager.GetString("INTNotice", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 8-bit encryption key.
|
||||
/// </summary>
|
||||
public static string YPFLabelKey {
|
||||
get {
|
||||
return ResourceManager.GetString("YPFLabelKey", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Archive directory is encrypted.
|
||||
///Enter archive encryption key..
|
||||
/// </summary>
|
||||
public static string YPFNotice {
|
||||
get {
|
||||
return ResourceManager.GetString("YPFNotice", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
148
ArcFormats/Strings/arcStrings.resx
Normal file
148
ArcFormats/Strings/arcStrings.resx
Normal file
@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ArcEncryptedNotice" xml:space="preserve">
|
||||
<value>Archive content is encrypted.
|
||||
Choose appropriate encryption scheme.</value>
|
||||
</data>
|
||||
<data name="ArcNoEncryption" xml:space="preserve">
|
||||
<value>no encryption</value>
|
||||
</data>
|
||||
<data name="INTLabelNumericKey" xml:space="preserve">
|
||||
<value>Numeric key</value>
|
||||
</data>
|
||||
<data name="INTLabelPassphrase" xml:space="preserve">
|
||||
<value>Passphrase</value>
|
||||
</data>
|
||||
<data name="INTLabelScheme" xml:space="preserve">
|
||||
<value>Scheme</value>
|
||||
</data>
|
||||
<data name="INTNotice" xml:space="preserve">
|
||||
<value>Archive directory is encrypted.
|
||||
Enter archive encryption key or choose
|
||||
predefined encryption scheme.</value>
|
||||
</data>
|
||||
<data name="YPFLabelKey" xml:space="preserve">
|
||||
<value>8-bit encryption key</value>
|
||||
</data>
|
||||
<data name="YPFNotice" xml:space="preserve">
|
||||
<value>Archive directory is encrypted.
|
||||
Enter archive encryption key.</value>
|
||||
</data>
|
||||
</root>
|
148
ArcFormats/Strings/arcStrings.ru-RU.resx
Normal file
148
ArcFormats/Strings/arcStrings.ru-RU.resx
Normal file
@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ArcEncryptedNotice" xml:space="preserve">
|
||||
<value>Содержимое архива зашифровано.
|
||||
Выберите алгоритм шифрования.</value>
|
||||
</data>
|
||||
<data name="ArcNoEncryption" xml:space="preserve">
|
||||
<value>без шифрования</value>
|
||||
</data>
|
||||
<data name="INTLabelNumericKey" xml:space="preserve">
|
||||
<value>Цифровой ключ</value>
|
||||
</data>
|
||||
<data name="INTLabelPassphrase" xml:space="preserve">
|
||||
<value>Пароль</value>
|
||||
</data>
|
||||
<data name="INTLabelScheme" xml:space="preserve">
|
||||
<value>Вариант</value>
|
||||
</data>
|
||||
<data name="INTNotice" xml:space="preserve">
|
||||
<value>Заголовок архива зашифрован.
|
||||
Введите ключ шифрования или выберите
|
||||
один из предопределённых вариантов.</value>
|
||||
</data>
|
||||
<data name="YPFLabelKey" xml:space="preserve">
|
||||
<value>8-битный ключ шифрования</value>
|
||||
</data>
|
||||
<data name="YPFNotice" xml:space="preserve">
|
||||
<value>Заголовок архива зашифрован.
|
||||
Введите ключ шифрования.</value>
|
||||
</data>
|
||||
</root>
|
57
ArcFormats/WidgetINT.xaml
Normal file
57
ArcFormats/WidgetINT.xaml
Normal file
@ -0,0 +1,57 @@
|
||||
<Grid x:Class="GameRes.Formats.GUI.WidgetINT"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="clr-namespace:GameRes.Formats.Strings"
|
||||
xmlns:local="clr-namespace:GameRes.Formats.GUI"
|
||||
MaxWidth="250">
|
||||
<Grid.Resources>
|
||||
<local:KeyConverter x:Key="keyConverter"/>
|
||||
<Style TargetType="{x:Type TextBox}">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Validation.HasError" Value="true">
|
||||
<Setter Property="ToolTip"
|
||||
Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Grid.Resources>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition MinWidth="100" Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<Label Content="{x:Static s:arcStrings.INTLabelNumericKey}" Target="{Binding ElementName=Passkey}"
|
||||
Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right"/>
|
||||
<TextBox Name="Passkey" Grid.Column="1" Grid.Row="0" Margin="0,3,0,3">
|
||||
<TextBox.Text>
|
||||
<Binding Path="Key" Converter="{StaticResource keyConverter}" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
<local:PasskeyRule/>
|
||||
</Binding.ValidationRules>
|
||||
</Binding>
|
||||
</TextBox.Text>
|
||||
<Validation.ErrorTemplate>
|
||||
<ControlTemplate>
|
||||
<DockPanel>
|
||||
<TextBlock DockPanel.Dock="Right" Foreground="Red" FontWeight="Bold" Text="!" VerticalAlignment="Center"/>
|
||||
<Border BorderBrush="Red" BorderThickness="1">
|
||||
<AdornedElementPlaceholder Name="ValidationAdorner" />
|
||||
</Border>
|
||||
</DockPanel>
|
||||
</ControlTemplate>
|
||||
</Validation.ErrorTemplate>
|
||||
</TextBox>
|
||||
<Label Content="{x:Static s:arcStrings.INTLabelPassphrase}" Target="{Binding ElementName=Passphrase}"
|
||||
Grid.Column="0" Grid.Row="1" HorizontalAlignment="Right"/>
|
||||
<TextBox Name="Passphrase" Grid.Column="1" Grid.Row="1" Margin="0,3,0,3"
|
||||
Text="{Binding Path=Password}"/>
|
||||
<Label Content="{x:Static s:arcStrings.INTLabelScheme}" Target="{Binding ElementName=EncScheme}"
|
||||
Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right"/>
|
||||
<ComboBox Name="EncScheme" Grid.Column="1" Grid.Row="2" Margin="0,3,0,0"
|
||||
Width="{Binding ElementName=Passkey, Path=ActualWidth}"
|
||||
SelectedValue="{Binding Path=Scheme}"/>
|
||||
</Grid>
|
126
ArcFormats/WidgetINT.xaml.cs
Normal file
126
ArcFormats/WidgetINT.xaml.cs
Normal file
@ -0,0 +1,126 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace GameRes.Formats.GUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for WidgetINT.xaml
|
||||
/// </summary>
|
||||
public partial class WidgetINT : Grid
|
||||
{
|
||||
public WidgetINT (IntEncryptionInfo encryption_info)
|
||||
{
|
||||
InitializeComponent();
|
||||
this.DataContext = encryption_info;
|
||||
EncScheme.ItemsSource = IntOpener.KnownSchemes.Keys;
|
||||
|
||||
Passphrase.TextChanged += OnPassphraseChanged;
|
||||
EncScheme.SelectionChanged += OnSchemeChanged;
|
||||
}
|
||||
|
||||
public IntEncryptionInfo Info { get { return this.DataContext as IntEncryptionInfo; } }
|
||||
|
||||
void OnPasskeyChanged (object sender, TextChangedEventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
void OnPassphraseChanged (object sender, TextChangedEventArgs e)
|
||||
{
|
||||
var widget = sender as TextBox;
|
||||
uint key = IntOpener.EncodePassPhrase (widget.Text);
|
||||
Passkey.Text = key.ToString ("X8");
|
||||
}
|
||||
|
||||
void OnSchemeChanged (object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
var widget = sender as ComboBox;
|
||||
IntOpener.KeyData keydata;
|
||||
if (IntOpener.KnownSchemes.TryGetValue (widget.SelectedItem as string, out keydata))
|
||||
{
|
||||
Passphrase.TextChanged -= OnPassphraseChanged;
|
||||
try
|
||||
{
|
||||
Passphrase.Text = keydata.Passphrase;
|
||||
Passkey.Text = keydata.Key.ToString ("X8");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Passphrase.TextChanged += OnPassphraseChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public uint? GetKey ()
|
||||
{
|
||||
if (null != Info.Key && Info.Key.HasValue)
|
||||
return Info.Key;
|
||||
|
||||
if (!string.IsNullOrEmpty (Info.Scheme))
|
||||
{
|
||||
IntOpener.KeyData keydata;
|
||||
if (IntOpener.KnownSchemes.TryGetValue (Info.Scheme, out keydata))
|
||||
return keydata.Key;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty (Info.Password))
|
||||
return IntOpener.EncodePassPhrase (Info.Password);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
[ValueConversion(typeof(uint?), typeof(string))]
|
||||
public class KeyConverter : IValueConverter
|
||||
{
|
||||
public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
uint? key = (uint?)value;
|
||||
return null != key ? key.Value.ToString ("X") : "";
|
||||
}
|
||||
|
||||
public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
string strValue = value as string;
|
||||
uint result_key;
|
||||
if (uint.TryParse(strValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out result_key))
|
||||
return new uint? (result_key);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class PasskeyRule : ValidationRule
|
||||
{
|
||||
public PasskeyRule()
|
||||
{
|
||||
}
|
||||
|
||||
public override ValidationResult Validate (object value, CultureInfo cultureInfo)
|
||||
{
|
||||
uint key = 0;
|
||||
try
|
||||
{
|
||||
if (((string)value).Length > 0)
|
||||
key = UInt32.Parse ((string)value, NumberStyles.HexNumber);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new ValidationResult (false, "Numeric key should be a 32-bit hexadecimal integer");
|
||||
}
|
||||
return new ValidationResult (true, null);
|
||||
}
|
||||
}
|
||||
}
|
6
ArcFormats/WidgetNPA.xaml
Normal file
6
ArcFormats/WidgetNPA.xaml
Normal file
@ -0,0 +1,6 @@
|
||||
<Grid x:Class="GameRes.Formats.GUI.WidgetNPA"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
MaxWidth="250">
|
||||
<ComboBox Name="Scheme" Margin="5" Width="180"/>
|
||||
</Grid>
|
23
ArcFormats/WidgetNPA.xaml.cs
Normal file
23
ArcFormats/WidgetNPA.xaml.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace GameRes.Formats.GUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for WidgetNPA.xaml
|
||||
/// </summary>
|
||||
public partial class WidgetNPA : Grid
|
||||
{
|
||||
public WidgetNPA (string scheme)
|
||||
{
|
||||
InitializeComponent();
|
||||
Scheme.ItemsSource = NpaOpener.KnownSchemes;
|
||||
Scheme.SelectedItem = scheme;
|
||||
}
|
||||
|
||||
public string GetScheme()
|
||||
{
|
||||
return Scheme.SelectedItem as string;
|
||||
}
|
||||
}
|
||||
}
|
6
ArcFormats/WidgetXP3.xaml
Normal file
6
ArcFormats/WidgetXP3.xaml
Normal file
@ -0,0 +1,6 @@
|
||||
<Grid x:Class="GameRes.Formats.GUI.WidgetXP3"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
MaxWidth="250">
|
||||
<ComboBox Name="Scheme" Margin="5" Width="180"/>
|
||||
</Grid>
|
24
ArcFormats/WidgetXP3.xaml.cs
Normal file
24
ArcFormats/WidgetXP3.xaml.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using GameRes.Formats.KiriKiri;
|
||||
|
||||
namespace GameRes.Formats.GUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for WidgetXP3.xaml
|
||||
/// </summary>
|
||||
public partial class WidgetXP3 : Grid
|
||||
{
|
||||
public WidgetXP3 (string scheme)
|
||||
{
|
||||
InitializeComponent();
|
||||
Scheme.ItemsSource = Xp3Opener.KnownSchemes.Keys;
|
||||
Scheme.SelectedItem = scheme;
|
||||
}
|
||||
|
||||
public string GetScheme ()
|
||||
{
|
||||
return Scheme.SelectedItem as string;
|
||||
}
|
||||
}
|
||||
}
|
12
ArcFormats/WidgetYPF.xaml
Normal file
12
ArcFormats/WidgetYPF.xaml
Normal file
@ -0,0 +1,12 @@
|
||||
<Grid x:Class="GameRes.Formats.GUI.WidgetYPF"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="clr-namespace:GameRes.Formats.Strings"
|
||||
MaxWidth="250">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition MinWidth="100" Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Content="{x:Static s:arcStrings.YPFLabelKey}" Target="{Binding ElementName=Passkey}" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right"/>
|
||||
<TextBox Name="Passkey" Margin="5" Width="100" Grid.Column="1" Grid.Row="0"/>
|
||||
</Grid>
|
29
ArcFormats/WidgetYPF.xaml.cs
Normal file
29
ArcFormats/WidgetYPF.xaml.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace GameRes.Formats.GUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for WidgetYPF.xaml
|
||||
/// </summary>
|
||||
public partial class WidgetYPF : Grid
|
||||
{
|
||||
public WidgetYPF (uint? key)
|
||||
{
|
||||
InitializeComponent();
|
||||
if (null != key)
|
||||
this.Passkey.Text = key.Value.ToString();
|
||||
else
|
||||
this.Passkey.Text = null;
|
||||
}
|
||||
|
||||
public uint? GetKey ()
|
||||
{
|
||||
uint key;
|
||||
if (uint.TryParse (this.Passkey.Text, out key))
|
||||
return key;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
21
ArcFormats/app.config
Normal file
21
ArcFormats/app.config
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||
<section name="GameRes.Formats.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<userSettings>
|
||||
<GameRes.Formats.Properties.Settings>
|
||||
<setting name="NPAScheme" serializeAs="String">
|
||||
<value>NotEncrypted</value>
|
||||
</setting>
|
||||
<setting name="XP3Scheme" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="YPFKey" serializeAs="String">
|
||||
<value>4294967295</value>
|
||||
</setting>
|
||||
</GameRes.Formats.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
4
ArcFormats/packages.config
Normal file
4
ArcFormats/packages.config
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
|
||||
</packages>
|
24
ArcParameters.xaml
Normal file
24
ArcParameters.xaml
Normal file
@ -0,0 +1,24 @@
|
||||
<Window x:Class="GARbro.GUI.ArcParametersDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="clr-namespace:GARbro.GUI.Strings"
|
||||
xmlns:local="clr-namespace:GARbro.GUI"
|
||||
Title="{x:Static s:guiStrings.TextParametersTitle}" SizeToContent="WidthAndHeight"
|
||||
UseLayoutRounding="True" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
|
||||
ShowInTaskbar="False" WindowStartupLocation="CenterOwner" ResizeMode="NoResize">
|
||||
<Window.Resources>
|
||||
<BitmapImage x:Key="Icon64x64Info" UriSource="Images/64x64/info.png"/>
|
||||
</Window.Resources>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image Width="64" Height="64" Source="Images/64x64/info.png"
|
||||
SnapsToDevicePixels="True" VerticalAlignment="Top"
|
||||
RenderOptions.BitmapScalingMode="HighQuality" Margin="10,10,0,0"/>
|
||||
<DockPanel Name="WidgetPane" VerticalAlignment="Top" Margin="10">
|
||||
<TextBlock Name="Notice" DockPanel.Dock="Top" TextWrapping="WrapWithOverflow" Margin="0,0,0,10"/>
|
||||
<StackPanel DockPanel.Dock="Bottom" HorizontalAlignment="Right" Orientation="Horizontal" Margin="20,20,0,0">
|
||||
<Button Content="Ok" Click="Button_Click" IsDefault="True" Width="70" Margin="0,0,10,0"/>
|
||||
<Button Content="Cancel" IsCancel="True" Width="70" Margin="10,0,0,0"/>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
</Window>
|
22
ArcParameters.xaml.cs
Normal file
22
ArcParameters.xaml.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace GARbro.GUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ArcParameters.xaml
|
||||
/// </summary>
|
||||
public partial class ArcParametersDialog : Window
|
||||
{
|
||||
public ArcParametersDialog (UIElement widget, string notice)
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WidgetPane.Children.Add (widget);
|
||||
this.Notice.Text = notice;
|
||||
}
|
||||
|
||||
private void Button_Click (object sender, RoutedEventArgs e)
|
||||
{
|
||||
DialogResult = true;
|
||||
}
|
||||
}
|
||||
}
|
6
Console/App.config
Normal file
6
Console/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/>
|
||||
</startup>
|
||||
</configuration>
|
137
Console/ConsoleBrowser.cs
Normal file
137
Console/ConsoleBrowser.cs
Normal file
@ -0,0 +1,137 @@
|
||||
//! \file Program.cs
|
||||
//! \date Mon Jun 30 20:12:13 2014
|
||||
//! \brief game resources browser.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.MemoryMappedFiles;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using GameRes;
|
||||
|
||||
namespace GARbro
|
||||
{
|
||||
class ConsoleBrowser
|
||||
{
|
||||
private string m_arc_name;
|
||||
|
||||
void ListFormats ()
|
||||
{
|
||||
Console.WriteLine ("Recognized resource formats:");
|
||||
foreach (var impl in FormatCatalog.Instance.ArcFormats)
|
||||
{
|
||||
Console.WriteLine ("{0,-4} {1}", impl.Tag, impl.Description);
|
||||
}
|
||||
}
|
||||
|
||||
void ExtractAll (ArcFile arc)
|
||||
{
|
||||
arc.ExtractFiles ((i, entry) => {
|
||||
Console.WriteLine ("Extracting {0} ...", entry.Name);
|
||||
return ExtractAction.Continue;
|
||||
});
|
||||
}
|
||||
|
||||
void ExtractFile (ArcFile arc, string name)
|
||||
{
|
||||
Entry entry = arc.Dir.FirstOrDefault (e => e.Name.Equals (name, StringComparison.OrdinalIgnoreCase));
|
||||
if (null == entry)
|
||||
{
|
||||
Console.Error.WriteLine ("'{0}' not found within {1}", name, m_arc_name);
|
||||
return;
|
||||
}
|
||||
Console.WriteLine ("Extracting {0} ...", entry.Name);
|
||||
arc.Extract (entry);
|
||||
}
|
||||
void TestArc (string[] args)
|
||||
{
|
||||
/*
|
||||
if (args.Length > 1)
|
||||
{
|
||||
uint pass = GameRes.Formats.IntOpener.EncodePassPhrase (args[1]);
|
||||
Console.WriteLine ("{0:X8}", pass);
|
||||
}
|
||||
*/
|
||||
}
|
||||
void Run (string[] args)
|
||||
{
|
||||
int argn = 0;
|
||||
if (args[argn].Equals ("-l"))
|
||||
{
|
||||
ListFormats();
|
||||
return;
|
||||
}
|
||||
if (args[argn].Equals ("-t"))
|
||||
{
|
||||
TestArc (args);
|
||||
return;
|
||||
}
|
||||
if (args[argn].Equals ("-x"))
|
||||
{
|
||||
++argn;
|
||||
if (args.Length < 2)
|
||||
{
|
||||
Usage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_arc_name = args[argn];
|
||||
var arc = ArcFile.TryOpen (m_arc_name);
|
||||
if (null == arc)
|
||||
{
|
||||
Console.Error.WriteLine ("{0}: unknown format", m_arc_name);
|
||||
return;
|
||||
}
|
||||
using (arc)
|
||||
{
|
||||
if (args.Length > argn+1)
|
||||
{
|
||||
for (int i = argn+1; i < args.Length; ++i)
|
||||
ExtractFile (arc, args[i]);
|
||||
}
|
||||
else if (args[0].Equals ("-x"))
|
||||
{
|
||||
ExtractAll (arc);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var entry in arc.Dir)
|
||||
{
|
||||
Console.WriteLine ("{0,9} {1}", entry.Size, entry.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Usage ()
|
||||
{
|
||||
Console.WriteLine ("Usage: gameres [OPTIONS] ARC [ENTRIES]");
|
||||
Console.WriteLine (" -l list recognized archive formats");
|
||||
Console.WriteLine (" -x extract all files");
|
||||
Console.WriteLine ("Without options displays contents of specified archive.");
|
||||
}
|
||||
|
||||
static void Main (string[] args)
|
||||
{
|
||||
if (0 == args.Length)
|
||||
{
|
||||
Usage();
|
||||
return;
|
||||
}
|
||||
var listener = new TextWriterTraceListener (Console.Error);
|
||||
Trace.Listeners.Add(listener);
|
||||
try
|
||||
{
|
||||
var browser = new ConsoleBrowser();
|
||||
browser.Run (args);
|
||||
}
|
||||
catch (Exception X)
|
||||
{
|
||||
Console.Error.WriteLine (X.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
101
Console/GARbro.Console.csproj
Normal file
101
Console/GARbro.Console.csproj
Normal file
@ -0,0 +1,101 @@
|
||||
<?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>{B966F292-431A-4D8A-A1D3-1EB45048A1D2}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>GARbro</RootNamespace>
|
||||
<AssemblyName>GARbro.Console</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<PublishUrl>publish\</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>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</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|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</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="ConsoleBrowser.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\GameRes\GameRes.csproj">
|
||||
<Project>{453c087f-e416-4ae9-8c03-d8760da0574b}</Project>
|
||||
<Name>GameRes</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<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>
|
16
Console/GARbro.Console.csproj.user
Normal file
16
Console/GARbro.Console.csproj.user
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<PublishUrlHistory>publish\</PublishUrlHistory>
|
||||
<InstallUrlHistory />
|
||||
<SupportUrlHistory />
|
||||
<UpdateUrlHistory />
|
||||
<BootstrapperUrlHistory />
|
||||
<ErrorReportUrlHistory />
|
||||
<FallbackCulture>en-US</FallbackCulture>
|
||||
<VerifyUploadedFiles>false</VerifyUploadedFiles>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||
<StartArguments>-l</StartArguments>
|
||||
</PropertyGroup>
|
||||
</Project>
|
36
Console/Properties/AssemblyInfo.cs
Normal file
36
Console/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("GARbro.Console")]
|
||||
[assembly: AssemblyDescription("Game Archive browser")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("GARbro")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014 mørkt")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("a0e89f40-24ea-4958-a80c-d4f7b1386c91")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
166
DragScroll.cs
Normal file
166
DragScroll.cs
Normal file
@ -0,0 +1,166 @@
|
||||
//! \file DragScroll.cs
|
||||
//! \date Sun Jul 06 10:47:20 2014
|
||||
//! \brief Scroll control contents by dragging.
|
||||
//
|
||||
// http://matthamilton.net/touchscrolling-for-scrollviewer
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace GARbro.GUI
|
||||
{
|
||||
public class TouchScrolling : DependencyObject
|
||||
{
|
||||
public static bool GetIsEnabled(DependencyObject obj)
|
||||
{
|
||||
return (bool)obj.GetValue(IsEnabledProperty);
|
||||
}
|
||||
|
||||
public static void SetIsEnabled(DependencyObject obj, bool value)
|
||||
{
|
||||
obj.SetValue(IsEnabledProperty, value);
|
||||
}
|
||||
|
||||
public bool IsEnabled
|
||||
{
|
||||
get { return (bool)GetValue(IsEnabledProperty); }
|
||||
set { SetValue(IsEnabledProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsEnabledProperty =
|
||||
DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(TouchScrolling), new UIPropertyMetadata(false, IsEnabledChanged));
|
||||
|
||||
static Dictionary<object, MouseCapture> _captures = new Dictionary<object, MouseCapture>();
|
||||
|
||||
static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var target = d as FrameworkElement;
|
||||
if (target == null) return;
|
||||
|
||||
if ((bool)e.NewValue)
|
||||
{
|
||||
target.Loaded += target_Loaded;
|
||||
}
|
||||
else
|
||||
{
|
||||
target_Unloaded(target, new RoutedEventArgs());
|
||||
}
|
||||
}
|
||||
|
||||
static void target_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Target Unloaded");
|
||||
|
||||
var target = sender as FrameworkElement;
|
||||
if (null == target)
|
||||
return;
|
||||
|
||||
_captures.Remove(sender);
|
||||
|
||||
target.Loaded -= target_Loaded;
|
||||
target.Unloaded -= target_Unloaded;
|
||||
target.PreviewMouseLeftButtonDown -= target_PreviewMouseLeftButtonDown;
|
||||
target.PreviewMouseMove -= target_PreviewMouseMove;
|
||||
|
||||
target.PreviewMouseLeftButtonUp -= target_PreviewMouseLeftButtonUp;
|
||||
}
|
||||
|
||||
static void target_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
var target = sender as FrameworkElement;
|
||||
if (null == target)
|
||||
return;
|
||||
var scroller = FindVisualParent<ScrollViewer> (target);
|
||||
if (null == scroller)
|
||||
{
|
||||
Trace.WriteLine ("Control should be placed inside ScrollViewer for drag scrolling to work");
|
||||
return;
|
||||
}
|
||||
|
||||
_captures[sender] = new MouseCapture
|
||||
{
|
||||
HorizontalOffset = scroller.HorizontalOffset,
|
||||
VerticalOffset = scroller.VerticalOffset,
|
||||
Point = e.GetPosition(scroller),
|
||||
};
|
||||
}
|
||||
|
||||
static void target_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var target = sender as FrameworkElement;
|
||||
if (target == null) return;
|
||||
|
||||
// Debug.WriteLine("DragScroll target Loaded", sender);
|
||||
|
||||
target.Unloaded += target_Unloaded;
|
||||
target.PreviewMouseLeftButtonDown += target_PreviewMouseLeftButtonDown;
|
||||
target.PreviewMouseMove += target_PreviewMouseMove;
|
||||
|
||||
target.PreviewMouseLeftButtonUp += target_PreviewMouseLeftButtonUp;
|
||||
}
|
||||
|
||||
static void target_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
var target = sender as FrameworkElement;
|
||||
if (target == null) return;
|
||||
|
||||
target.ReleaseMouseCapture();
|
||||
target.Cursor = Cursors.Arrow;
|
||||
}
|
||||
|
||||
static void target_PreviewMouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (!_captures.ContainsKey(sender)) return;
|
||||
|
||||
if (e.LeftButton != MouseButtonState.Pressed)
|
||||
{
|
||||
_captures.Remove(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
var target = sender as FrameworkElement;
|
||||
if (null == target)
|
||||
return;
|
||||
var scroller = FindVisualParent<ScrollViewer> (target);
|
||||
if (null == scroller)
|
||||
return;
|
||||
|
||||
var capture = _captures[sender];
|
||||
|
||||
var point = e.GetPosition (scroller);
|
||||
|
||||
var dx = point.X - capture.Point.X;
|
||||
var dy = point.Y - capture.Point.Y;
|
||||
if (System.Math.Abs(dy) > 5 || System.Math.Abs(dx) > 5)
|
||||
{
|
||||
target.CaptureMouse();
|
||||
target.Cursor = Cursors.SizeAll;
|
||||
}
|
||||
scroller.ScrollToHorizontalOffset(capture.HorizontalOffset - dx);
|
||||
scroller.ScrollToVerticalOffset(capture.VerticalOffset - dy);
|
||||
}
|
||||
|
||||
static parentItem FindVisualParent<parentItem> (DependencyObject obj) where parentItem : DependencyObject
|
||||
{
|
||||
if (null == obj)
|
||||
return null;
|
||||
DependencyObject parent = VisualTreeHelper.GetParent (obj);
|
||||
while (parent != null && !(parent is parentItem))
|
||||
{
|
||||
parent = VisualTreeHelper.GetParent (parent);
|
||||
}
|
||||
return parent as parentItem;
|
||||
}
|
||||
|
||||
internal class MouseCapture
|
||||
{
|
||||
public double HorizontalOffset { get; set; }
|
||||
public double VerticalOffset { get; set; }
|
||||
public Point Point { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
37
ExtractArchive.xaml
Normal file
37
ExtractArchive.xaml
Normal file
@ -0,0 +1,37 @@
|
||||
<local:ExtractDialog x:Class="GARbro.GUI.ExtractArchiveDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="clr-namespace:GARbro.GUI.Strings"
|
||||
xmlns:p="clr-namespace:GARbro.GUI.Properties"
|
||||
xmlns:local="clr-namespace:GARbro.GUI"
|
||||
Title="{x:Static s:guiStrings.TextExtractTitle}" Height="200" Width="411.713"
|
||||
ShowInTaskbar="False" WindowStartupLocation="CenterOwner" ResizeMode="NoResize" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}">
|
||||
<Grid Margin="0,0,0,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="61*"/>
|
||||
<RowDefinition Height="70*"/>
|
||||
<RowDefinition Height="41*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock x:Name="ExtractLabel" Text="{x:Static s:guiStrings.TextExtractAllTo}" Margin="10,10,10,0" VerticalAlignment="Top" Height="15"/>
|
||||
<local:ExtAutoCompleteBox x:Name="DestinationDir" Margin="10,0,41,9" VerticalAlignment="Bottom"/>
|
||||
<Button Margin="0,0,10,9" VerticalAlignment="Bottom" HorizontalAlignment="Right"
|
||||
Command="{x:Static local:Commands.Browse}">
|
||||
<Image Source="{StaticResource IconSearch}" Stretch="Uniform" UseLayoutRounding="True" SnapsToDevicePixels="True" Width="16" Height="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Button>
|
||||
<CheckBox Name="ExtractImages" Content="{x:Static s:guiStrings.TextExtractImages}" HorizontalAlignment="Left" Margin="10,7.061,0,0" Grid.Row="1" VerticalAlignment="Top" Width="147" Height="15" IsChecked="True"/>
|
||||
<Border BorderBrush="{x:Null}" Height="28" Width="115" Margin="0,0.061,127.87,0" Grid.Row="1" VerticalAlignment="Top" HorizontalAlignment="Right" >
|
||||
<TextBlock Text="{x:Static s:guiStrings.TextSaveImagesAs}" TextWrapping="Wrap" TextAlignment="Right" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
</Border>
|
||||
<ComboBox Name="ImageConversionFormat" DisplayMemberPath="Tag" Margin="0,4.061,41.87,0" Grid.Row="1" VerticalAlignment="Top" Height="21" HorizontalAlignment="Right" Width="75">
|
||||
</ComboBox>
|
||||
<CheckBox x:Name="ExtractText" Content="{x:Static s:guiStrings.TextExtractText}" HorizontalAlignment="Left" Margin="10,35.061,0,0" Grid.Row="1" VerticalAlignment="Top" Width="120" Height="15" IsChecked="True"/>
|
||||
<TextBlock Text="{x:Static s:guiStrings.TextEncoding}" Margin="0,35.061,128,0" TextAlignment="Right" VerticalAlignment="Top" Height="20" Grid.Row="1" HorizontalAlignment="Right" Width="109"/>
|
||||
<ComboBox x:Name="TextEncoding" Margin="0,33.061,41.87,0" Grid.Row="1" VerticalAlignment="Top" Height="21" HorizontalAlignment="Right" Width="76">
|
||||
</ComboBox>
|
||||
<Button Content="{x:Static s:guiStrings.ButtonExtract}" Click="ExtractButton_Click" HorizontalAlignment="Right" Margin="0,0,103,10" Grid.Row="2" Width="75" Height="21" VerticalAlignment="Bottom" IsDefault="True"/>
|
||||
<Button Content="{x:Static s:guiStrings.ButtonCancel}" Margin="0,0,10,10" Grid.Row="2" Height="21" VerticalAlignment="Bottom" IsCancel="True" HorizontalAlignment="Right" Width="75"/>
|
||||
</Grid>
|
||||
<Window.CommandBindings>
|
||||
<CommandBinding Command="{x:Static local:Commands.Browse}" Executed="BrowseExec" CanExecute="CanExecuteAlways"/>
|
||||
</Window.CommandBindings>
|
||||
</local:ExtractDialog>
|
80
ExtractArchive.xaml.cs
Normal file
80
ExtractArchive.xaml.cs
Normal file
@ -0,0 +1,80 @@
|
||||
// Game Resource Browser
|
||||
//
|
||||
// Copyright (C) 2014 by morkt
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.WindowsAPICodePack.Dialogs;
|
||||
using GARbro.GUI.Properties;
|
||||
using GARbro.GUI.Strings;
|
||||
using GameRes;
|
||||
|
||||
namespace GARbro.GUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ExtractArchive.xaml
|
||||
/// </summary>
|
||||
public partial class ExtractArchiveDialog : ExtractDialog
|
||||
{
|
||||
public ExtractArchiveDialog (string filename, string destination)
|
||||
{
|
||||
InitializeComponent();
|
||||
ExtractLabel.Text = string.Format (guiStrings.TextExtractAllTo, filename);
|
||||
DestinationDir.Text = destination;
|
||||
|
||||
ExtractImages.IsChecked = Settings.Default.appExtractImages;
|
||||
ExtractText.IsChecked = Settings.Default.appExtractText;
|
||||
ExtractText.IsEnabled = false;
|
||||
TextEncoding.IsEnabled = false;
|
||||
|
||||
InitImageFormats (ImageConversionFormat);
|
||||
}
|
||||
|
||||
private void BrowseExec (object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
string folder = ChooseFolder (guiStrings.TextChooseDestDir, DestinationDir.Text);
|
||||
if (null != folder)
|
||||
DestinationDir.Text = folder;
|
||||
}
|
||||
|
||||
void ExtractButton_Click (object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.DialogResult = true;
|
||||
Settings.Default.appExtractImages = this.ExtractImages.IsChecked.Value;
|
||||
Settings.Default.appExtractText = this.ExtractText.IsChecked.Value;
|
||||
ExportImageFormat (ImageConversionFormat);
|
||||
}
|
||||
|
||||
public ImageFormat GetImageFormat ()
|
||||
{
|
||||
var selected = ImageConversionFormat.SelectedItem as ImageFormatModel;
|
||||
return null != selected ? selected.Source : null;
|
||||
}
|
||||
}
|
||||
}
|
83
ExtractDialog.cs
Normal file
83
ExtractDialog.cs
Normal file
@ -0,0 +1,83 @@
|
||||
//! \file ExtractDialog.cs
|
||||
//! \date Wed Jul 09 11:26:08 2014
|
||||
//! \brief Extract dialog window.
|
||||
//
|
||||
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Microsoft.WindowsAPICodePack.Dialogs;
|
||||
using GARbro.GUI.Properties;
|
||||
using GARbro.GUI.Strings;
|
||||
using GameRes;
|
||||
using System.Windows.Input;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GARbro.GUI
|
||||
{
|
||||
public partial class ExtractDialog : Window
|
||||
{
|
||||
public void InitImageFormats (ComboBox image_format)
|
||||
{
|
||||
var default_format = Settings.Default.appImageFormat;
|
||||
var formats = FormatCatalog.Instance.ImageFormats.Where (f => f.IsBuiltin);
|
||||
ImageFormatModel[] default_model = { new ImageFormatModel() };
|
||||
var models = default_model.Concat (formats.Select (f => new ImageFormatModel (f))).ToList();
|
||||
|
||||
var selected = models.FirstOrDefault (f => f.Tag.Equals (default_format));
|
||||
image_format.ItemsSource = models;
|
||||
Trace.WriteLine (selected != null ? selected.Tag : "null", "image_format");
|
||||
if (null != selected)
|
||||
image_format.SelectedItem = selected;
|
||||
else if (models.Any())
|
||||
image_format.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
public ImageFormat GetImageFormat (ComboBox image_format)
|
||||
{
|
||||
var selected = image_format.SelectedItem as ImageFormatModel;
|
||||
if (null != selected)
|
||||
return selected.Source;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public void ExportImageFormat (ComboBox image_format)
|
||||
{
|
||||
var format = GetImageFormat (image_format);
|
||||
if (null != format)
|
||||
Settings.Default.appImageFormat = format.Tag;
|
||||
else
|
||||
Settings.Default.appImageFormat = "";
|
||||
}
|
||||
|
||||
public string ChooseFolder (string title, string initial)
|
||||
{
|
||||
var dlg = new CommonOpenFileDialog();
|
||||
dlg.Title = title;
|
||||
dlg.IsFolderPicker = true;
|
||||
dlg.InitialDirectory = initial;
|
||||
|
||||
dlg.AddToMostRecentlyUsedList = false;
|
||||
dlg.AllowNonFileSystemItems = false;
|
||||
dlg.EnsureFileExists = true;
|
||||
dlg.EnsurePathExists = true;
|
||||
dlg.EnsureReadOnly = false;
|
||||
dlg.EnsureValidNames = true;
|
||||
dlg.Multiselect = false;
|
||||
dlg.ShowPlacesList = true;
|
||||
|
||||
if (dlg.ShowDialog (this) == CommonFileDialogResult.Ok)
|
||||
return dlg.FileName;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public void CanExecuteAlways (object sender, CanExecuteRoutedEventArgs e)
|
||||
{
|
||||
e.CanExecute = true;
|
||||
}
|
||||
}
|
||||
}
|
34
ExtractFile.xaml
Normal file
34
ExtractFile.xaml
Normal file
@ -0,0 +1,34 @@
|
||||
<local:ExtractDialog x:Class="GARbro.GUI.ExtractFile"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="clr-namespace:GARbro.GUI.Strings"
|
||||
xmlns:p="clr-namespace:GARbro.GUI.Properties"
|
||||
xmlns:local="clr-namespace:GARbro.GUI"
|
||||
Title="{x:Static s:guiStrings.TextExtractTitle}" Height="165.774" Width="400.861"
|
||||
ShowInTaskbar="False" WindowStartupLocation="CenterOwner" ResizeMode="NoResize" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}">
|
||||
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock x:Name="ExtractLabel" Text="{x:Static s:guiStrings.TextExtractFileTo}" Margin="10,10,9.157,0" VerticalAlignment="Top" Height="15"/>
|
||||
<local:ExtAutoCompleteBox x:Name="DestinationDir" Margin="10,28,0,0"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Width="337"/>
|
||||
<Button Margin="0,28,10,0" VerticalAlignment="Top" HorizontalAlignment="Right"
|
||||
Command="{x:Static local:Commands.Browse}">
|
||||
<Image Source="{StaticResource IconSearch}" Stretch="Uniform" UseLayoutRounding="True" SnapsToDevicePixels="True" Width="16" Height="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Button>
|
||||
<StackPanel x:Name="ImageConversionOptions" Visibility="Visible" Orientation="Horizontal" Margin="10,60,0,0" Height="25" VerticalAlignment="Top" HorizontalAlignment="Left" Width="300">
|
||||
<TextBlock Text="{x:Static s:guiStrings.TextSaveAs}" Margin="0,0,7,0" TextWrapping="Wrap" TextAlignment="Right" VerticalAlignment="Center" HorizontalAlignment="Left"/>
|
||||
<ComboBox x:Name="ImageConversionFormat" DisplayMemberPath="Tag" Margin="0" VerticalAlignment="Center" Height="21" Width="76"/>
|
||||
</StackPanel>
|
||||
<StackPanel x:Name="TextConversionOptions" Visibility="Collapsed" Orientation="Horizontal" Margin="10,60,0,0" Height="25" VerticalAlignment="Top" HorizontalAlignment="Left" Width="300">
|
||||
<TextBlock Text="{x:Static s:guiStrings.TextEncoding}" Margin="0,0,7,0" TextAlignment="Right" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
<ComboBox x:Name="TextEncoding" Margin="0" VerticalAlignment="Center" Height="21" HorizontalAlignment="Right" Width="76"/>
|
||||
</StackPanel>
|
||||
<Button Content="{x:Static s:guiStrings.ButtonExtract}" Click="ExtractButton_Click" HorizontalAlignment="Right" Margin="0,0,102.157,10" Width="75" IsDefault="True" Height="21" VerticalAlignment="Bottom"/>
|
||||
<Button Content="{x:Static s:guiStrings.ButtonCancel}" Margin="0,0,10.157,10" IsCancel="True" HorizontalAlignment="Right" Width="75" Height="21" VerticalAlignment="Bottom"/>
|
||||
</Grid>
|
||||
<Window.CommandBindings>
|
||||
<CommandBinding Command="{x:Static local:Commands.Browse}" Executed="BrowseExec" CanExecute="CanExecuteAlways"/>
|
||||
</Window.CommandBindings>
|
||||
</local:ExtractDialog>
|
83
ExtractFile.xaml.cs
Normal file
83
ExtractFile.xaml.cs
Normal file
@ -0,0 +1,83 @@
|
||||
// Game Resource Browser
|
||||
//
|
||||
// Copyright (C) 2014 by morkt
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using Microsoft.WindowsAPICodePack.Dialogs;
|
||||
using GARbro.GUI.Properties;
|
||||
using GARbro.GUI.Strings;
|
||||
|
||||
namespace GARbro.GUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ExtractFile.xaml
|
||||
/// </summary>
|
||||
public partial class ExtractFile : ExtractDialog
|
||||
{
|
||||
public ExtractFile (EntryViewModel entry, string destination)
|
||||
{
|
||||
InitializeComponent();
|
||||
ExtractLabel.Text = string.Format (guiStrings.TextExtractFileTo, entry.Name);
|
||||
DestinationDir.Text = destination;
|
||||
if ("image" == entry.Type)
|
||||
{
|
||||
ImageConversionOptions.Visibility = Visibility.Visible;
|
||||
TextConversionOptions.Visibility = Visibility.Collapsed;
|
||||
InitImageFormats (ImageConversionFormat);
|
||||
}
|
||||
else if ("script" == entry.Type)
|
||||
{
|
||||
ImageConversionOptions.Visibility = Visibility.Collapsed;
|
||||
TextConversionOptions.Visibility = Visibility.Visible;
|
||||
TextEncoding.IsEnabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ImageConversionOptions.Visibility = Visibility.Collapsed;
|
||||
TextConversionOptions.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
private void BrowseExec (object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
string folder = ChooseFolder (guiStrings.TextChooseDestDir, DestinationDir.Text);
|
||||
if (null != folder)
|
||||
DestinationDir.Text = folder;
|
||||
}
|
||||
|
||||
void ExtractButton_Click (object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.DialogResult = true;
|
||||
if (ImageConversionOptions.Visibility == Visibility.Visible)
|
||||
{
|
||||
ExportImageFormat (ImageConversionFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
305
GARbro.GUI.csproj
Normal file
305
GARbro.GUI.csproj
Normal file
@ -0,0 +1,305 @@
|
||||
<?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>{2935BE57-C4E0-43E7-86DE-C1848C820B19}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>GARbro.GUI</RootNamespace>
|
||||
<AssemblyName>GARbro.GUI</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<TargetFrameworkProfile />
|
||||
<PublishUrl>publish\</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>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<PublishWizardCompleted>true</PublishWizardCompleted>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</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|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>
|
||||
</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>Images\sample.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ManifestCertificateThumbprint>751F4A9FD4F4CC3D99D70509FF1F9D9CC9E49516</ManifestCertificateThumbprint>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ManifestKeyFile>GARbro.GUI_TemporaryKey.pfx</ManifestKeyFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<GenerateManifests>false</GenerateManifests>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetZone>LocalIntranet</TargetZone>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignManifests>true</SignManifests>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualBasic" />
|
||||
<Reference Include="Microsoft.WindowsAPICodePack">
|
||||
<HintPath>packages\WindowsAPICodePack-Core.1.1\lib\Microsoft.WindowsAPICodePack.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.WindowsAPICodePack.Shell">
|
||||
<HintPath>packages\WindowsAPICodePack-Shell.1.1\lib\Microsoft.WindowsAPICodePack.Shell.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Ookii.Dialogs.Wpf, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0c15020868fd6249, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>packages\Ookii.Dialogs.1.0\lib\net35\Ookii.Dialogs.Wpf.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Windows.Controls.Input.Toolkit, Version=3.5.40128.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>D:\Program Files\WPF Toolkit\v3.5.50211.1\System.Windows.Controls.Input.Toolkit.dll</HintPath>
|
||||
</Reference>
|
||||
<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" />
|
||||
<Reference Include="WPFToolkit, Version=3.5.40128.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>D:\Program Files\WPF Toolkit\v3.5.50211.1\WPFToolkit.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="AboutBox.xaml.cs">
|
||||
<DependentUpon>AboutBox.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ArcParameters.xaml.cs">
|
||||
<DependentUpon>ArcParameters.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="DragScroll.cs" />
|
||||
<Compile Include="ExtractArchive.xaml.cs">
|
||||
<DependentUpon>ExtractArchive.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ExtractDialog.cs" />
|
||||
<Compile Include="ExtractFile.xaml.cs">
|
||||
<DependentUpon>ExtractFile.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="HistoryStack.cs" />
|
||||
<Compile Include="ImagePreview.cs" />
|
||||
<Compile Include="ModalWindow.cs" />
|
||||
<Compile Include="Settings.cs" />
|
||||
<Compile Include="Strings\guiStrings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>guiStrings.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Utility.cs" />
|
||||
<Compile Include="ViewModel.cs" />
|
||||
<Page Include="AboutBox.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="ArcParameters.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="ExtractArchive.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="ExtractFile.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="MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</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>
|
||||
<EmbeddedResource Include="Strings\guiStrings.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>guiStrings.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Strings\guiStrings.ru-RU.resx" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\app.manifest" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<AppDesigner Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Images\16x16\add file.png" />
|
||||
<Resource Include="Images\16x16\add folder.png" />
|
||||
<Resource Include="Images\16x16\add note.png" />
|
||||
<Resource Include="Images\16x16\add window.png" />
|
||||
<Resource Include="Images\16x16\add.png" />
|
||||
<Resource Include="Images\16x16\addd.png" />
|
||||
<Resource Include="Images\16x16\flag green.png" />
|
||||
<Resource Include="Images\16x16\folder video.png" />
|
||||
<Resource Include="Images\16x16\folder.png" />
|
||||
<Resource Include="Images\16x16\info.png" />
|
||||
<Resource Include="Images\16x16\play.png" />
|
||||
<Resource Include="Images\16x16\remove.png" />
|
||||
<Resource Include="Images\16x16\tools.png" />
|
||||
<Resource Include="Images\16x16\undo.png" />
|
||||
<Resource Include="Images\16x16\video.png" />
|
||||
<Resource Include="Images\32x32\add file.png" />
|
||||
<Resource Include="Images\32x32\add folder.png" />
|
||||
<Resource Include="Images\32x32\add note.png" />
|
||||
<Resource Include="Images\32x32\add window.png" />
|
||||
<Resource Include="Images\32x32\add.png" />
|
||||
<Resource Include="Images\32x32\addd.png" />
|
||||
<Resource Include="Images\32x32\back button.png" />
|
||||
<Resource Include="Images\32x32\back.png" />
|
||||
<Resource Include="Images\32x32\delete.png" />
|
||||
<Resource Include="Images\32x32\flag green.png" />
|
||||
<Resource Include="Images\32x32\folder video.png" />
|
||||
<Resource Include="Images\32x32\folder.png" />
|
||||
<Resource Include="Images\32x32\forward button.png" />
|
||||
<Resource Include="Images\32x32\help.png" />
|
||||
<Resource Include="Images\32x32\info.png" />
|
||||
<Resource Include="Images\32x32\play.png" />
|
||||
<Resource Include="Images\32x32\remove.png" />
|
||||
<Resource Include="Images\32x32\tools.png" />
|
||||
<Resource Include="Images\32x32\undo.png" />
|
||||
<Resource Include="Images\32x32\video.png" />
|
||||
<Resource Include="Images\64x64\add file.png" />
|
||||
<Resource Include="Images\64x64\add folder.png" />
|
||||
<Resource Include="Images\64x64\add note.png" />
|
||||
<Resource Include="Images\64x64\add window.png" />
|
||||
<Resource Include="Images\64x64\add.png" />
|
||||
<Resource Include="Images\64x64\addd.png" />
|
||||
<Resource Include="Images\64x64\folder video.png" />
|
||||
<Resource Include="Images\64x64\folder.png" />
|
||||
<Resource Include="Images\64x64\info.png" />
|
||||
<Resource Include="Images\64x64\play.png" />
|
||||
<Resource Include="Images\64x64\remove.png" />
|
||||
<Resource Include="Images\64x64\tools.png" />
|
||||
<Resource Include="Images\64x64\undo.png" />
|
||||
<Resource Include="Images\64x64\video.png" />
|
||||
<Resource Include="Images\sample.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="zlib\zlib32.dll">
|
||||
<Link>zlib32.dll</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="zlib\zlib64.dll">
|
||||
<Link>zlib64.dll</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Resource Include="Images\search4files.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="ArcFormats\ArcFormats.csproj">
|
||||
<Project>{a8865685-27cc-427b-ac38-e48d2ad05df4}</Project>
|
||||
<Name>ArcFormats</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="GameRes\GameRes.csproj">
|
||||
<Project>{453c087f-e416-4ae9-8c03-d8760da0574b}</Project>
|
||||
<Name>GameRes</Name>
|
||||
<EmbedInteropTypes>False</EmbedInteropTypes>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<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>
|
17
GARbro.GUI.csproj.user
Normal file
17
GARbro.GUI.csproj.user
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<PublishUrlHistory>publish\</PublishUrlHistory>
|
||||
<InstallUrlHistory />
|
||||
<SupportUrlHistory />
|
||||
<UpdateUrlHistory />
|
||||
<BootstrapperUrlHistory />
|
||||
<ErrorReportUrlHistory />
|
||||
<FallbackCulture>en-US</FallbackCulture>
|
||||
<VerifyUploadedFiles>false</VerifyUploadedFiles>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||
<StartArguments>
|
||||
</StartArguments>
|
||||
</PropertyGroup>
|
||||
</Project>
|
59
GARbro.sln
Normal file
59
GARbro.sln
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.21005.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GARbro.Console", "Console\GARbro.Console.csproj", "{B966F292-431A-4D8A-A1D3-1EB45048A1D2}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{453C087F-E416-4AE9-8C03-D8760DA0574B} = {453C087F-E416-4AE9-8C03-D8760DA0574B}
|
||||
{A8865685-27CC-427B-AC38-E48D2AD05DF4} = {A8865685-27CC-427B-AC38-E48D2AD05DF4}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArcFormats", "ArcFormats\ArcFormats.csproj", "{A8865685-27CC-427B-AC38-E48D2AD05DF4}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{453C087F-E416-4AE9-8C03-D8760DA0574B} = {453C087F-E416-4AE9-8C03-D8760DA0574B}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameRes", "GameRes\GameRes.csproj", "{453C087F-E416-4AE9-8C03-D8760DA0574B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GARbro.GUI", "GARbro.GUI.csproj", "{2935BE57-C4E0-43E7-86DE-C1848C820B19}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{A8865685-27CC-427B-AC38-E48D2AD05DF4} = {A8865685-27CC-427B-AC38-E48D2AD05DF4}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Image.Convert", "Image.Convert\Image.Convert.csproj", "{757EB8B1-F62C-4690-AC3D-DAE4A5576B3E}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{A8865685-27CC-427B-AC38-E48D2AD05DF4} = {A8865685-27CC-427B-AC38-E48D2AD05DF4}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{B966F292-431A-4D8A-A1D3-1EB45048A1D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B966F292-431A-4D8A-A1D3-1EB45048A1D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B966F292-431A-4D8A-A1D3-1EB45048A1D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B966F292-431A-4D8A-A1D3-1EB45048A1D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A8865685-27CC-427B-AC38-E48D2AD05DF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A8865685-27CC-427B-AC38-E48D2AD05DF4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A8865685-27CC-427B-AC38-E48D2AD05DF4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A8865685-27CC-427B-AC38-E48D2AD05DF4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{453C087F-E416-4AE9-8C03-D8760DA0574B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{453C087F-E416-4AE9-8C03-D8760DA0574B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{453C087F-E416-4AE9-8C03-D8760DA0574B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{453C087F-E416-4AE9-8C03-D8760DA0574B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2935BE57-C4E0-43E7-86DE-C1848C820B19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2935BE57-C4E0-43E7-86DE-C1848C820B19}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2935BE57-C4E0-43E7-86DE-C1848C820B19}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2935BE57-C4E0-43E7-86DE-C1848C820B19}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{757EB8B1-F62C-4690-AC3D-DAE4A5576B3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{757EB8B1-F62C-4690-AC3D-DAE4A5576B3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{757EB8B1-F62C-4690-AC3D-DAE4A5576B3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{757EB8B1-F62C-4690-AC3D-DAE4A5576B3E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
245
GameRes/ArcFile.cs
Normal file
245
GameRes/ArcFile.cs
Normal file
@ -0,0 +1,245 @@
|
||||
//! \file ArcFile.cs
|
||||
//! \date Tue Jul 08 12:53:45 2014
|
||||
//! \brief Game Archive file class.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace GameRes
|
||||
{
|
||||
public enum ExtractAction
|
||||
{
|
||||
Abort,
|
||||
Skip,
|
||||
Continue,
|
||||
}
|
||||
|
||||
public class ArcFile : IDisposable
|
||||
{
|
||||
private ArcView m_arc;
|
||||
private ArchiveFormat m_interface;
|
||||
private ICollection<Entry> m_dir;
|
||||
|
||||
/// <summary>Tag that identifies this archive format.</summary>
|
||||
public string Tag { get { return m_interface.Tag; } }
|
||||
|
||||
/// <summary>Short archive format description.</summary>
|
||||
public string Description { get { return m_interface.Description; } }
|
||||
|
||||
/// <summary>Memory-mapped view of the archive.</summary>
|
||||
public ArcView File { get { return m_arc; } }
|
||||
|
||||
/// <summary>Archive contents.</summary>
|
||||
public ICollection<Entry> Dir { get { return m_dir; } }
|
||||
|
||||
public delegate ExtractAction ExtractCallback (int num, Entry entry);
|
||||
|
||||
public ArcFile (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir)
|
||||
{
|
||||
m_arc = arc;
|
||||
m_interface = impl;
|
||||
m_dir = dir;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to open <paramref name="filename"/> as archive.
|
||||
/// Returns: ArcFile object if file is opened successfully, null otherwise.
|
||||
/// </summary>
|
||||
public static ArcFile TryOpen (string filename)
|
||||
{
|
||||
var file = new ArcView (filename);
|
||||
try
|
||||
{
|
||||
uint signature = file.View.ReadUInt32 (0);
|
||||
for (;;)
|
||||
{
|
||||
var range = FormatCatalog.Instance.LookupSignature<ArchiveFormat> (signature);
|
||||
foreach (var impl in range)
|
||||
{
|
||||
try
|
||||
{
|
||||
var arc = impl.TryOpen (file);
|
||||
if (null != arc)
|
||||
{
|
||||
file = null; // file ownership passed to ArcFile
|
||||
return arc;
|
||||
}
|
||||
}
|
||||
catch (Exception X)
|
||||
{
|
||||
// ignore failed open attmepts
|
||||
Trace.WriteLine (string.Format ("[{0}] {1}: {2}", impl.Tag, filename, X.Message));
|
||||
FormatCatalog.Instance.LastError = X;
|
||||
}
|
||||
}
|
||||
if (0 == signature)
|
||||
break;
|
||||
signature = 0;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (null != file)
|
||||
file.Dispose();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract all entries from the archive into current directory.
|
||||
/// <paramref name="callback"/> could be used to observe/control extraction process.
|
||||
/// </summary>
|
||||
public void ExtractFiles (ExtractCallback callback)
|
||||
{
|
||||
int i = 0;
|
||||
foreach (var entry in Dir.OrderBy (e => e.Offset))
|
||||
{
|
||||
var action = callback (i, entry);
|
||||
if (ExtractAction.Abort == action)
|
||||
break;
|
||||
if (ExtractAction.Skip != action)
|
||||
Extract (entry);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract specified <paramref name="entry"/> into current directory.
|
||||
/// </summary>
|
||||
public void Extract (Entry entry)
|
||||
{
|
||||
if (-1 != entry.Offset)
|
||||
m_interface.Extract (this, entry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open specified <paramref name="entry"/> as Stream.
|
||||
/// </summary>
|
||||
public Stream OpenEntry (Entry entry)
|
||||
{
|
||||
return m_interface.OpenEntry (this, entry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create file corresponding to <paramref name="entry"/> within current directory and open
|
||||
/// it for writing.
|
||||
/// </summary>
|
||||
public Stream CreateFile (Entry entry)
|
||||
{
|
||||
return m_interface.CreateFile (entry);
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
bool disposed = false;
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
if (disposing)
|
||||
m_arc.Dispose();
|
||||
m_arc = null;
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class AppendStream : System.IO.Stream
|
||||
{
|
||||
private Stream m_base;
|
||||
private long m_start_pos;
|
||||
|
||||
public override bool CanRead { get { return true; } }
|
||||
public override bool CanSeek { get { return true; } }
|
||||
public override bool CanWrite { get { return true; } }
|
||||
public override long Length { get { return m_base.Length - m_start_pos; } }
|
||||
public override long Position
|
||||
{
|
||||
get { return m_base.Position - m_start_pos; }
|
||||
set { m_base.Position = Math.Max (m_start_pos+value, m_start_pos); }
|
||||
}
|
||||
|
||||
public AppendStream (System.IO.Stream file)
|
||||
{
|
||||
m_base = file;
|
||||
m_start_pos = m_base.Seek (0, SeekOrigin.End);
|
||||
}
|
||||
|
||||
public AppendStream (System.IO.Stream file, long offset)
|
||||
{
|
||||
m_base = file;
|
||||
m_start_pos = m_base.Seek (offset, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
public Stream BaseStream { get { return m_base; } }
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
m_base.Flush();
|
||||
}
|
||||
|
||||
public override long Seek (long offset, SeekOrigin origin)
|
||||
{
|
||||
if (SeekOrigin.Begin == origin)
|
||||
{
|
||||
offset = Math.Max (offset + m_start_pos, m_start_pos);
|
||||
}
|
||||
long position = m_base.Seek (offset, origin);
|
||||
if (position < m_start_pos)
|
||||
{
|
||||
m_base.Seek (m_start_pos, SeekOrigin.Begin);
|
||||
position = m_start_pos;
|
||||
}
|
||||
return position - m_start_pos;
|
||||
}
|
||||
|
||||
public override void SetLength (long length)
|
||||
{
|
||||
if (length < 0)
|
||||
length = 0;
|
||||
m_base.SetLength (length + m_start_pos);
|
||||
}
|
||||
|
||||
public override int Read (byte[] buffer, int offset, int count)
|
||||
{
|
||||
return m_base.Read (buffer, offset, count);
|
||||
}
|
||||
|
||||
public override int ReadByte ()
|
||||
{
|
||||
return m_base.ReadByte();
|
||||
}
|
||||
|
||||
public override void Write (byte[] buffer, int offset, int count)
|
||||
{
|
||||
m_base.Write (buffer, offset, count);
|
||||
}
|
||||
|
||||
public override void WriteByte (byte value)
|
||||
{
|
||||
m_base.WriteByte (value);
|
||||
}
|
||||
|
||||
bool disposed = false;
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
m_base = null;
|
||||
disposed = true;
|
||||
base.Dispose (disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
470
GameRes/ArcView.cs
Normal file
470
GameRes/ArcView.cs
Normal file
@ -0,0 +1,470 @@
|
||||
//! \file ArcView.cs
|
||||
//! \date Mon Jul 07 10:31:10 2014
|
||||
//! \brief Memory mapped view of gameres file.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.MemoryMappedFiles;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace GameRes
|
||||
{
|
||||
public static class Encodings
|
||||
{
|
||||
public static readonly Encoding cp932 = Encoding.GetEncoding (932);
|
||||
}
|
||||
|
||||
public static class StreamExtension
|
||||
{
|
||||
static public string ReadStringUntil (this Stream file, byte delim, Encoding enc)
|
||||
{
|
||||
byte[] buffer = new byte[16];
|
||||
int size = 0;
|
||||
for (;;)
|
||||
{
|
||||
int b = file.ReadByte ();
|
||||
if (-1 == b || delim == b)
|
||||
break;
|
||||
if (buffer.Length == size)
|
||||
{
|
||||
byte[] new_buffer = new byte[checked(size/2*3)];
|
||||
Array.Copy (buffer, new_buffer, size);
|
||||
buffer = new_buffer;
|
||||
}
|
||||
buffer[size++] = (byte)b;
|
||||
}
|
||||
return enc.GetString (buffer, 0, size);
|
||||
}
|
||||
|
||||
static public string ReadCString (this Stream file, Encoding enc)
|
||||
{
|
||||
return ReadStringUntil (file, 0, enc);
|
||||
}
|
||||
|
||||
static public string ReadCString (this Stream file)
|
||||
{
|
||||
return ReadStringUntil (file, 0, Encodings.cp932);
|
||||
}
|
||||
}
|
||||
|
||||
public static class MappedViewExtension
|
||||
{
|
||||
static public string ReadString (this MemoryMappedViewAccessor view, long offset, uint size, Encoding enc)
|
||||
{
|
||||
byte[] buffer = new byte[size];
|
||||
uint n;
|
||||
for (n = 0; n < size; ++n)
|
||||
{
|
||||
byte b = view.ReadByte (offset+n);
|
||||
if (0 == b)
|
||||
break;
|
||||
buffer[n] = b;
|
||||
}
|
||||
return enc.GetString (buffer, 0, (int)n);
|
||||
}
|
||||
|
||||
static public string ReadString (this MemoryMappedViewAccessor view, long offset, uint size)
|
||||
{
|
||||
return ReadString (view, offset, size, Encodings.cp932);
|
||||
}
|
||||
|
||||
unsafe public static byte* GetPointer (this MemoryMappedViewAccessor view, long offset)
|
||||
{
|
||||
var num = view.PointerOffset % info.dwAllocationGranularity;
|
||||
byte* ptr = null;
|
||||
view.SafeMemoryMappedViewHandle.AcquirePointer (ref ptr);
|
||||
ptr += num;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern void GetSystemInfo (ref SYSTEM_INFO lpSystemInfo);
|
||||
|
||||
internal struct SYSTEM_INFO
|
||||
{
|
||||
internal int dwOemId;
|
||||
internal int dwPageSize;
|
||||
internal IntPtr lpMinimumApplicationAddress;
|
||||
internal IntPtr lpMaximumApplicationAddress;
|
||||
internal IntPtr dwActiveProcessorMask;
|
||||
internal int dwNumberOfProcessors;
|
||||
internal int dwProcessorType;
|
||||
internal int dwAllocationGranularity;
|
||||
internal short wProcessorLevel;
|
||||
internal short wProcessorRevision;
|
||||
}
|
||||
|
||||
static SYSTEM_INFO info;
|
||||
|
||||
static MappedViewExtension()
|
||||
{
|
||||
GetSystemInfo (ref info);
|
||||
}
|
||||
}
|
||||
|
||||
public class ArcView : IDisposable
|
||||
{
|
||||
private MemoryMappedFile m_map;
|
||||
|
||||
public const long PageSize = 4096;
|
||||
public long MaxOffset { get; private set; }
|
||||
public Frame View { get; private set; }
|
||||
|
||||
public ArcView (string name)
|
||||
{
|
||||
using (var fs = new FileStream(name, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
MaxOffset = fs.Length;
|
||||
m_map = MemoryMappedFile.CreateFromFile (fs, null, 0,
|
||||
MemoryMappedFileAccess.Read, null, HandleInheritability.None, false);
|
||||
try {
|
||||
View = new Frame (this);
|
||||
} catch {
|
||||
m_map.Dispose(); // dispose on error only
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Frame CreateFrame ()
|
||||
{
|
||||
return new Frame (View);
|
||||
}
|
||||
|
||||
public ArcStream CreateStream ()
|
||||
{
|
||||
return new ArcStream (this);
|
||||
}
|
||||
|
||||
public ArcStream CreateStream (long offset, uint size)
|
||||
{
|
||||
return new ArcStream (this, offset, size);
|
||||
}
|
||||
|
||||
public MemoryMappedViewAccessor CreateViewAccessor (long offset, uint size)
|
||||
{
|
||||
return m_map.CreateViewAccessor (offset, size, MemoryMappedFileAccess.Read);
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
bool disposed = false;
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
View.Dispose();
|
||||
m_map.Dispose();
|
||||
}
|
||||
disposed = true;
|
||||
m_map = null;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
public class Frame : IDisposable
|
||||
{
|
||||
private ArcView m_arc;
|
||||
private MemoryMappedViewAccessor m_view;
|
||||
private long m_offset;
|
||||
private uint m_size;
|
||||
|
||||
public long Offset { get { return m_offset; } }
|
||||
public uint Reserved { get { return m_size; } }
|
||||
|
||||
public Frame (ArcView arc)
|
||||
{
|
||||
m_arc = arc;
|
||||
m_offset = 0;
|
||||
m_size = (uint)Math.Min (ArcView.PageSize, m_arc.MaxOffset);
|
||||
m_view = m_arc.CreateViewAccessor (m_offset, m_size);
|
||||
}
|
||||
|
||||
public Frame (Frame other)
|
||||
{
|
||||
m_arc = other.m_arc;
|
||||
m_offset = 0;
|
||||
m_size = (uint)Math.Min (ArcView.PageSize, m_arc.MaxOffset);
|
||||
m_view = m_arc.CreateViewAccessor (m_offset, m_size);
|
||||
}
|
||||
|
||||
public Frame (ArcView arc, long offset, uint size)
|
||||
{
|
||||
m_arc = arc;
|
||||
m_offset = Math.Min (offset, m_arc.MaxOffset);
|
||||
m_size = (uint)Math.Min (size, m_arc.MaxOffset-m_offset);
|
||||
m_view = m_arc.CreateViewAccessor (m_offset, m_size);
|
||||
}
|
||||
|
||||
public uint Reserve (long offset, uint size)
|
||||
{
|
||||
if (offset < m_offset || offset+size > m_offset+m_size)
|
||||
{
|
||||
if (offset > m_arc.MaxOffset)
|
||||
throw new ArgumentOutOfRangeException ("offset", "Too large offset specified for memory mapped file view.");
|
||||
if (size < ArcView.PageSize)
|
||||
size = (uint)ArcView.PageSize;
|
||||
if (size > m_arc.MaxOffset-offset)
|
||||
size = (uint)(m_arc.MaxOffset-offset);
|
||||
m_view.Dispose();
|
||||
m_view = m_arc.CreateViewAccessor (offset, size);
|
||||
m_offset = offset;
|
||||
m_size = size;
|
||||
}
|
||||
return (uint)(m_offset + m_size - offset);
|
||||
}
|
||||
|
||||
public bool AsciiEqual (long offset, string data)
|
||||
{
|
||||
if (Reserve (offset, (uint)data.Length) < (uint)data.Length)
|
||||
return false;
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = m_view.GetPointer (m_offset);
|
||||
try {
|
||||
for (int i = 0; i < data.Length; ++i)
|
||||
{
|
||||
if (ptr[offset-m_offset+i] != data[i])
|
||||
return false;
|
||||
}
|
||||
} finally {
|
||||
m_view.SafeMemoryMappedViewHandle.ReleasePointer();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int Read (long offset, byte[] buf, int buf_offset, uint count)
|
||||
{
|
||||
// supposedly faster version of
|
||||
//Reserve (offset, count);
|
||||
//return m_view.ReadArray (offset-m_offset, buf, buf_offset, (int)count);
|
||||
|
||||
if (buf == null)
|
||||
throw new ArgumentNullException ("buf", "Buffer cannot be null.");
|
||||
if (buf_offset < 0)
|
||||
throw new ArgumentOutOfRangeException ("buf_offset", "Buffer offset should be non-negative.");
|
||||
|
||||
int total = (int)Math.Min (Reserve (offset, count), count);
|
||||
if (buf.Length - buf_offset < total)
|
||||
throw new ArgumentException ("Buffer offset and length are out of bounds.");
|
||||
|
||||
unsafe
|
||||
{
|
||||
byte* ptr = m_view.GetPointer (m_offset);
|
||||
try {
|
||||
Marshal.Copy ((IntPtr)(ptr+(offset-m_offset)), buf, buf_offset, total);
|
||||
} finally {
|
||||
m_view.SafeMemoryMappedViewHandle.ReleasePointer();
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public byte ReadByte (long offset)
|
||||
{
|
||||
Reserve (offset, 1);
|
||||
return m_view.ReadByte (offset-m_offset);
|
||||
}
|
||||
|
||||
public ushort ReadUInt16 (long offset)
|
||||
{
|
||||
Reserve (offset, 2);
|
||||
return m_view.ReadUInt16 (offset-m_offset);
|
||||
}
|
||||
|
||||
public short ReadInt16 (long offset)
|
||||
{
|
||||
Reserve (offset, 2);
|
||||
return m_view.ReadInt16 (offset-m_offset);
|
||||
}
|
||||
|
||||
public uint ReadUInt32 (long offset)
|
||||
{
|
||||
Reserve (offset, 4);
|
||||
return m_view.ReadUInt32 (offset-m_offset);
|
||||
}
|
||||
|
||||
public int ReadInt32 (long offset)
|
||||
{
|
||||
Reserve (offset, 4);
|
||||
return m_view.ReadInt32 (offset-m_offset);
|
||||
}
|
||||
|
||||
public ulong ReadUInt64 (long offset)
|
||||
{
|
||||
Reserve (offset, 8);
|
||||
return m_view.ReadUInt64 (offset-m_offset);
|
||||
}
|
||||
|
||||
public long ReadInt64 (long offset)
|
||||
{
|
||||
Reserve (offset, 8);
|
||||
return m_view.ReadInt64 (offset-m_offset);
|
||||
}
|
||||
|
||||
public string ReadString (long offset, uint size, Encoding enc)
|
||||
{
|
||||
Reserve (offset, size);
|
||||
return m_view.ReadString (offset-m_offset, size, enc);
|
||||
}
|
||||
|
||||
public string ReadString (long offset, uint size)
|
||||
{
|
||||
return ReadString (offset, size, Encodings.cp932);
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
bool disposed = false;
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
m_view.Dispose();
|
||||
}
|
||||
m_arc = null;
|
||||
m_view = null;
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class ArcStream : System.IO.Stream
|
||||
{
|
||||
private Frame m_view;
|
||||
private long m_start;
|
||||
private uint m_size;
|
||||
private long m_position;
|
||||
|
||||
public override bool CanRead { get { return true; } }
|
||||
public override bool CanSeek { get { return true; } }
|
||||
public override bool CanWrite { get { return false; } }
|
||||
public override long Length { get { return m_size; } }
|
||||
public override long Position
|
||||
{
|
||||
get { return m_position; }
|
||||
set { m_position = Math.Max (value, 0); }
|
||||
}
|
||||
|
||||
public ArcStream (ArcView file)
|
||||
{
|
||||
m_view = file.CreateFrame();
|
||||
m_start = 0;
|
||||
m_size = (uint)Math.Min (file.MaxOffset, uint.MaxValue);
|
||||
m_position = 0;
|
||||
}
|
||||
|
||||
public ArcStream (ArcView file, long offset, uint size)
|
||||
{
|
||||
m_view = new Frame (file, offset, size);
|
||||
m_start = m_view.Offset;
|
||||
m_size = m_view.Reserved;
|
||||
m_position = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read stream signature (first 4 bytes) without altering current read position.
|
||||
/// </summary>
|
||||
public uint ReadSignature ()
|
||||
{
|
||||
return m_view.ReadUInt32 (m_start);
|
||||
}
|
||||
|
||||
#region System.IO.Stream methods
|
||||
public override void Flush()
|
||||
{
|
||||
}
|
||||
|
||||
public override long Seek (long offset, SeekOrigin origin)
|
||||
{
|
||||
switch (origin)
|
||||
{
|
||||
case SeekOrigin.Begin: m_position = offset; break;
|
||||
case SeekOrigin.Current: m_position += offset; break;
|
||||
case SeekOrigin.End: m_position = m_size + offset; break;
|
||||
}
|
||||
if (m_position < 0)
|
||||
m_position = 0;
|
||||
return m_position;
|
||||
}
|
||||
|
||||
public override void SetLength (long length)
|
||||
{
|
||||
throw new NotSupportedException ("GameRes.ArcStream.SetLength method is not supported");
|
||||
}
|
||||
|
||||
public override int Read (byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (m_position >= m_size)
|
||||
return 0;
|
||||
count = (int)Math.Min (count, m_size - m_position);
|
||||
int read = m_view.Read (m_start + m_position, buffer, offset, (uint)count);
|
||||
m_position += read;
|
||||
return read;
|
||||
}
|
||||
|
||||
public override int ReadByte ()
|
||||
{
|
||||
if (m_position >= m_size)
|
||||
return -1;
|
||||
byte b = m_view.ReadByte (m_start+m_position);
|
||||
++m_position;
|
||||
return b;
|
||||
}
|
||||
|
||||
public override void Write (byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotSupportedException("GameRes.ArcStream.Write method is not supported");
|
||||
}
|
||||
|
||||
public override void WriteByte (byte value)
|
||||
{
|
||||
throw new NotSupportedException("GameRes.ArcStream.WriteByte method is not supported");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
bool disposed = false;
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
m_view.Dispose();
|
||||
}
|
||||
disposed = true;
|
||||
base.Dispose (disposing);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class Reader : System.IO.BinaryReader
|
||||
{
|
||||
public Reader (Stream stream) : base (stream, Encoding.ASCII, true)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
347
GameRes/GameRes.cs
Normal file
347
GameRes/GameRes.cs
Normal file
@ -0,0 +1,347 @@
|
||||
//! \file GameRes.cs
|
||||
//! \date Mon Jun 30 20:12:13 2014
|
||||
//! \brief game resources browser.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.ComponentModel.Composition.Hosting;
|
||||
using System.Reflection;
|
||||
using GameRes.Collections;
|
||||
using GameRes.Strings;
|
||||
|
||||
namespace GameRes
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic filesystem entry.
|
||||
/// </summary>
|
||||
public class Entry
|
||||
{
|
||||
public virtual string Name { get; set; }
|
||||
public virtual string Type { get; set; }
|
||||
public long Offset { get; set; }
|
||||
public uint Size { get; set; }
|
||||
|
||||
public Entry ()
|
||||
{
|
||||
Type = "";
|
||||
Offset = -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check whether entry lies within specified file bound.
|
||||
/// </summary>
|
||||
public bool CheckPlacement (long max_offset)
|
||||
{
|
||||
return Offset < max_offset && Size < max_offset && Offset <= max_offset - Size;
|
||||
}
|
||||
}
|
||||
|
||||
public class PackedEntry : Entry
|
||||
{
|
||||
public uint UnpackedSize { get; set; }
|
||||
public bool IsPacked { get; set; }
|
||||
}
|
||||
|
||||
public abstract class IResource
|
||||
{
|
||||
/// <summary>Short tag sticked to resource (usually filename extension)</summary>
|
||||
public abstract string Tag { get; }
|
||||
|
||||
/// <summary>Resource description (its source/inventor)</summary>
|
||||
public abstract string Description { get; }
|
||||
|
||||
/// <summary>Resource type (image/archive/script)</summary>
|
||||
public abstract string Type { get; }
|
||||
|
||||
/// <summary>First 4 bytes of the resource file as little-endian 32-bit integer,
|
||||
/// or zero if it could vary.</summary>
|
||||
public abstract uint Signature { get; }
|
||||
|
||||
/// <summary>Signatures peculiar to the resource (the one above is also included here).</summary>
|
||||
public IEnumerable<uint> Signatures
|
||||
{
|
||||
get { return m_signatures; }
|
||||
protected set { m_signatures = value; }
|
||||
}
|
||||
|
||||
/// <summary>Filename extensions peculiar to the resource.</summary>
|
||||
public IEnumerable<string> Extensions
|
||||
{
|
||||
get { return m_extensions; }
|
||||
protected set { m_extensions = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create empty Entry that corresponds to implemented resource.
|
||||
/// </summary>
|
||||
public virtual Entry CreateEntry ()
|
||||
{
|
||||
return new Entry { Type = this.Type };
|
||||
}
|
||||
|
||||
private IEnumerable<string> m_extensions;
|
||||
private IEnumerable<uint> m_signatures;
|
||||
|
||||
protected IResource ()
|
||||
{
|
||||
m_extensions = new string[] { Tag.ToLower() };
|
||||
m_signatures = new uint[] { Signature };
|
||||
}
|
||||
}
|
||||
|
||||
public class ResourceOptions
|
||||
{
|
||||
public object Widget { get; set; }
|
||||
}
|
||||
|
||||
public abstract class ArchiveFormat : IResource
|
||||
{
|
||||
public override string Type { get { return "archive"; } }
|
||||
|
||||
public abstract ArcFile TryOpen (ArcView view);
|
||||
|
||||
/// <summary>
|
||||
/// Extract file referenced by <paramref name="entry"/> into current directory.
|
||||
/// </summary>
|
||||
public virtual void Extract (ArcFile file, Entry entry)
|
||||
{
|
||||
using (var reader = OpenEntry (file, entry))
|
||||
{
|
||||
using (var writer = CreateFile (entry))
|
||||
{
|
||||
reader.CopyTo (writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open file referenced by <paramref name="entry"/> as Stream.
|
||||
/// </summary>
|
||||
public virtual Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
{
|
||||
return arc.File.CreateStream (entry.Offset, entry.Size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create file corresponding to <paramref name="entry"/> in current directory and open it
|
||||
/// for writing.
|
||||
/// </summary>
|
||||
public virtual Stream CreateFile (Entry entry)
|
||||
{
|
||||
string dir = Path.GetDirectoryName (entry.Name);
|
||||
if (!string.IsNullOrEmpty (dir))
|
||||
{
|
||||
Directory.CreateDirectory (dir);
|
||||
}
|
||||
return File.Create (entry.Name);
|
||||
}
|
||||
|
||||
/// /// <summary>
|
||||
/// Create resource archive named <paramref name="filename"/> containing entries from the
|
||||
/// supplied <paramref name="list"/> and applying necessary <paramref name="options"/>.
|
||||
/// </summary>
|
||||
public virtual void Create (string filename, IEnumerable<Entry> list, ResourceOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException ("ArchiveFormat.Create is not implemented");
|
||||
}
|
||||
|
||||
public virtual ResourceOptions GetOptions ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void ParametersRequestEventHandler (object sender, ParametersRequestEventArgs e);
|
||||
|
||||
public class ParametersRequestEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// String describing request nature (encryption key etc).
|
||||
/// </summary>
|
||||
public string Notice { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// UIElement responsible for displaying request.
|
||||
/// </summary>
|
||||
public object InputWidget { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Return value from ShowDialog()
|
||||
/// </summary>
|
||||
public bool InputResult { get; set; }
|
||||
}
|
||||
|
||||
public sealed class FormatCatalog
|
||||
{
|
||||
private static readonly FormatCatalog m_instance = new FormatCatalog();
|
||||
|
||||
#pragma warning disable 649
|
||||
[ImportMany(typeof(ArchiveFormat))]
|
||||
private IEnumerable<ArchiveFormat> m_arc_formats;
|
||||
[ImportMany(typeof(ImageFormat))]
|
||||
private IEnumerable<ImageFormat> m_image_formats;
|
||||
[ImportMany(typeof(ScriptFormat))]
|
||||
private IEnumerable<ScriptFormat> m_script_formats;
|
||||
#pragma warning restore 649
|
||||
|
||||
private MultiValueDictionary<string, IResource> m_extension_map = new MultiValueDictionary<string, IResource>();
|
||||
private MultiValueDictionary<uint, IResource> m_signature_map = new MultiValueDictionary<uint, IResource>();
|
||||
|
||||
/// <summary> The only instance of this class.</summary>
|
||||
public static FormatCatalog Instance { get { return m_instance; } }
|
||||
|
||||
public IEnumerable<ArchiveFormat> ArcFormats { get { return m_arc_formats; } }
|
||||
public IEnumerable<ImageFormat> ImageFormats { get { return m_image_formats; } }
|
||||
public IEnumerable<ScriptFormat> ScriptFormats { get { return m_script_formats; } }
|
||||
|
||||
public Exception LastError { get; set; }
|
||||
|
||||
public event ParametersRequestEventHandler ParametersRequest;
|
||||
|
||||
private FormatCatalog ()
|
||||
{
|
||||
//An aggregate catalog that combines multiple catalogs
|
||||
var catalog = new AggregateCatalog();
|
||||
//Adds all the parts found in the same assembly as the Program class
|
||||
catalog.Catalogs.Add (new AssemblyCatalog (typeof(FormatCatalog).Assembly));
|
||||
//Adds parts matching pattern found in the directory of the assembly
|
||||
catalog.Catalogs.Add (new DirectoryCatalog (Path.GetDirectoryName (System.Reflection.Assembly.GetExecutingAssembly().Location), "Arc*.dll"));
|
||||
|
||||
//Create the CompositionContainer with the parts in the catalog
|
||||
var container = new CompositionContainer (catalog);
|
||||
|
||||
//Fill the imports of this object
|
||||
container.ComposeParts (this);
|
||||
AddResourceImpl (m_arc_formats);
|
||||
AddResourceImpl (m_image_formats);
|
||||
AddResourceImpl (m_script_formats);
|
||||
}
|
||||
|
||||
private void AddResourceImpl (IEnumerable<IResource> formats)
|
||||
{
|
||||
foreach (var impl in formats)
|
||||
{
|
||||
foreach (var ext in impl.Extensions)
|
||||
{
|
||||
m_extension_map.Add (ext.ToUpper(), impl);
|
||||
}
|
||||
foreach (var signature in impl.Signatures)
|
||||
{
|
||||
m_signature_map.Add (signature, impl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Look up filename in format registry by filename extension and return corresponding interfaces.
|
||||
/// if no formats available, return empty range.
|
||||
/// </summary>
|
||||
public IEnumerable<IResource> LookupFileName (string filename)
|
||||
{
|
||||
string ext = Path.GetExtension (filename);
|
||||
if (null == ext)
|
||||
return new IResource[0];
|
||||
return LookupTag (ext.TrimStart ('.'));
|
||||
}
|
||||
|
||||
public IEnumerable<IResource> LookupTag (string tag)
|
||||
{
|
||||
return m_extension_map.GetValues (tag.ToUpper(), true);
|
||||
}
|
||||
|
||||
public IEnumerable<Type> LookupTag<Type> (string tag) where Type : IResource
|
||||
{
|
||||
return LookupTag (tag).OfType<Type>();
|
||||
}
|
||||
|
||||
public IEnumerable<IResource> LookupSignature (uint signature)
|
||||
{
|
||||
return m_signature_map.GetValues (signature, true);
|
||||
}
|
||||
|
||||
public IEnumerable<Type> LookupSignature<Type> (uint signature) where Type : IResource
|
||||
{
|
||||
return LookupSignature (signature).OfType<Type>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create GameRes.Entry corresponding to <paramref name="filename"/> extension.
|
||||
/// </summary>
|
||||
public Entry CreateEntry (string filename)
|
||||
{
|
||||
Entry entry = null;
|
||||
string ext = Path.GetExtension (filename);
|
||||
if (null != ext)
|
||||
{
|
||||
ext = ext.TrimStart ('.').ToUpper();
|
||||
var range = m_extension_map.GetValues (ext, false);
|
||||
if (null != range)
|
||||
entry = range.First().CreateEntry();
|
||||
}
|
||||
if (null == entry)
|
||||
entry = new Entry();
|
||||
entry.Name = filename;
|
||||
return entry;
|
||||
}
|
||||
|
||||
public string GetTypeFromName (string filename)
|
||||
{
|
||||
var formats = LookupFileName (filename);
|
||||
if (formats.Any())
|
||||
return formats.First().Type;
|
||||
return "";
|
||||
}
|
||||
|
||||
public void InvokeParametersRequest (object source, ParametersRequestEventArgs args)
|
||||
{
|
||||
if (null != ParametersRequest)
|
||||
ParametersRequest (source, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read first 4 bytes from stream and return them as 32-bit signature.
|
||||
/// </summary>
|
||||
public static uint ReadSignature (Stream file)
|
||||
{
|
||||
file.Position = 0;
|
||||
uint signature = (byte)file.ReadByte();
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
signature |= (uint)file.ReadByte() << 8;
|
||||
signature |= (uint)file.ReadByte() << 16;
|
||||
signature |= (uint)file.ReadByte() << 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
signature <<= 24;
|
||||
signature |= (uint)file.ReadByte() << 16;
|
||||
signature |= (uint)file.ReadByte() << 8;
|
||||
signature |= (byte)file.ReadByte();
|
||||
}
|
||||
return signature;
|
||||
}
|
||||
}
|
||||
|
||||
public class InvalidFormatException : Exception
|
||||
{
|
||||
public InvalidFormatException() : base(garStrings.MsgInvalidFormat) { }
|
||||
public InvalidFormatException (string msg) : base (msg) { }
|
||||
}
|
||||
|
||||
public class UnknownEncryptionScheme : Exception
|
||||
{
|
||||
public UnknownEncryptionScheme() : base(garStrings.MsgUnknownEncryption) { }
|
||||
public UnknownEncryptionScheme (string msg) : base (msg) { }
|
||||
}
|
||||
|
||||
public class InvalidEncryptionScheme : Exception
|
||||
{
|
||||
public InvalidEncryptionScheme() : base(garStrings.MsgInvalidEncryption) { }
|
||||
public InvalidEncryptionScheme (string msg) : base (msg) { }
|
||||
}
|
||||
}
|
89
GameRes/GameRes.csproj
Normal file
89
GameRes/GameRes.csproj
Normal file
@ -0,0 +1,89 @@
|
||||
<?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>{453C087F-E416-4AE9-8C03-D8760DA0574B}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>GameRes</RootNamespace>
|
||||
<AssemblyName>GameRes</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<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' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\bin\Release\</OutputPath>
|
||||
<DefineConstants>
|
||||
</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xaml" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ArcFile.cs" />
|
||||
<Compile Include="ArcView.cs" />
|
||||
<Compile Include="GameRes.cs" />
|
||||
<Compile Include="Image.cs" />
|
||||
<Compile Include="ImageBMP.cs" />
|
||||
<Compile Include="ImageJPEG.cs" />
|
||||
<Compile Include="ImagePNG.cs" />
|
||||
<Compile Include="ImageTGA.cs" />
|
||||
<Compile Include="ImageTIFF.cs" />
|
||||
<Compile Include="MultiDict.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ScriptText.cs" />
|
||||
<Compile Include="Strings\garStrings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>garStrings.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Utility.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<WCFMetadata Include="Service References\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Strings\garStrings.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>garStrings.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Strings\garStrings.ru-RU.resx" />
|
||||
</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>
|
100
GameRes/Image.cs
Normal file
100
GameRes/Image.cs
Normal file
@ -0,0 +1,100 @@
|
||||
//! \file Image.cs
|
||||
//! \date Tue Jul 01 11:29:52 2014
|
||||
//! \brief image class.
|
||||
//
|
||||
|
||||
using System.IO;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace GameRes
|
||||
{
|
||||
public class ImageMetaData
|
||||
{
|
||||
public uint Width { get; set; }
|
||||
public uint Height { get; set; }
|
||||
public int OffsetX { get; set; }
|
||||
public int OffsetY { get; set; }
|
||||
public int BPP { get; set; }
|
||||
}
|
||||
|
||||
public class ImageEntry : Entry
|
||||
{
|
||||
public override string Type { get { return "image"; } }
|
||||
/*
|
||||
public ImageEntry ()
|
||||
{
|
||||
Type = "image";
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
public class ImageData
|
||||
{
|
||||
private BitmapSource m_bitmap;
|
||||
|
||||
public BitmapSource Bitmap { get { return m_bitmap; } }
|
||||
public uint Width { get { return (uint)m_bitmap.PixelWidth; } }
|
||||
public uint Height { get { return (uint)m_bitmap.PixelHeight; } }
|
||||
public int OffsetX { get; set; }
|
||||
public int OffsetY { get; set; }
|
||||
public int BPP { get { return m_bitmap.Format.BitsPerPixel; } }
|
||||
|
||||
public ImageData (BitmapSource data, ImageMetaData meta)
|
||||
{
|
||||
m_bitmap = data;
|
||||
OffsetX = meta.OffsetX;
|
||||
OffsetY = meta.OffsetY;
|
||||
}
|
||||
|
||||
public ImageData (BitmapSource data, int x = 0, int y = 0)
|
||||
{
|
||||
m_bitmap = data;
|
||||
OffsetX = x;
|
||||
OffsetY = y;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class ImageFormat : IResource
|
||||
{
|
||||
public override string Type { get { return "image"; } }
|
||||
|
||||
public ImageData Read (Stream file)
|
||||
{
|
||||
bool need_dispose = false;
|
||||
try
|
||||
{
|
||||
if (!file.CanSeek)
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
file.CopyTo (stream);
|
||||
file = stream;
|
||||
need_dispose = true;
|
||||
}
|
||||
var info = ReadMetaData (file);
|
||||
if (null == info)
|
||||
throw new InvalidFormatException();
|
||||
return Read (file, info);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (need_dispose)
|
||||
file.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract ImageData Read (Stream file, ImageMetaData info);
|
||||
public abstract void Write (Stream file, ImageData bitmap);
|
||||
|
||||
public abstract ImageMetaData ReadMetaData (Stream file);
|
||||
|
||||
public override Entry CreateEntry ()
|
||||
{
|
||||
return new ImageEntry();
|
||||
}
|
||||
|
||||
public bool IsBuiltin
|
||||
{
|
||||
get { return this.GetType().Assembly == typeof(ImageFormat).Assembly; }
|
||||
}
|
||||
}
|
||||
}
|
81
GameRes/ImageBMP.cs
Normal file
81
GameRes/ImageBMP.cs
Normal file
@ -0,0 +1,81 @@
|
||||
//! \file ImageBMP.cs
|
||||
//! \date Wed Jul 16 18:06:47 2014
|
||||
//! \brief BMP image implementation.
|
||||
//
|
||||
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Windows.Media.Imaging;
|
||||
using GameRes.Utility;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace GameRes
|
||||
{
|
||||
[Export(typeof(ImageFormat))]
|
||||
public class BmpFormat : ImageFormat
|
||||
{
|
||||
public override string Tag { get { return "BMP"; } }
|
||||
public override string Description { get { return "Windows device independent bitmap"; } }
|
||||
public override uint Signature { get { return 0; } }
|
||||
|
||||
public override ImageData Read (Stream file, ImageMetaData info)
|
||||
{
|
||||
var decoder = new BmpBitmapDecoder (file,
|
||||
BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
||||
BitmapSource frame = decoder.Frames.First();
|
||||
frame.Freeze();
|
||||
return new ImageData (frame, info);
|
||||
}
|
||||
|
||||
public override void Write (Stream file, ImageData image)
|
||||
{
|
||||
var encoder = new BmpBitmapEncoder();
|
||||
encoder.Frames.Add (BitmapFrame.Create (image.Bitmap));
|
||||
encoder.Save (file);
|
||||
}
|
||||
|
||||
void SkipBytes (BinaryReader file, uint num)
|
||||
{
|
||||
if (file.BaseStream.CanSeek)
|
||||
file.BaseStream.Seek (num, SeekOrigin.Current);
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < num / 4; ++i)
|
||||
file.ReadInt32();
|
||||
for (int i = 0; i < num % 4; ++i)
|
||||
file.ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
public override ImageMetaData ReadMetaData (Stream stream)
|
||||
{
|
||||
int c1 = stream.ReadByte();
|
||||
int c2 = stream.ReadByte();
|
||||
if (0x42 != c1 || 0x4d != c2)
|
||||
return null;
|
||||
using (var file = new ArcView.Reader (stream))
|
||||
{
|
||||
uint size = file.ReadUInt32();
|
||||
if (size < 14+40)
|
||||
return null;
|
||||
SkipBytes (file, 8);
|
||||
uint header_size = file.ReadUInt32();
|
||||
if (header_size < 40 || size-14 < header_size)
|
||||
return null;
|
||||
uint width = file.ReadUInt32();
|
||||
uint height = file.ReadUInt32();
|
||||
file.ReadInt16();
|
||||
int bpp = file.ReadInt16();
|
||||
return new ImageMetaData {
|
||||
Width = width,
|
||||
Height = height,
|
||||
OffsetX = 0,
|
||||
OffsetY = 0,
|
||||
BPP = bpp
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
79
GameRes/ImageJPEG.cs
Normal file
79
GameRes/ImageJPEG.cs
Normal file
@ -0,0 +1,79 @@
|
||||
//! \file ImageJPEG.cs
|
||||
//! \date Thu Jul 17 15:56:27 2014
|
||||
//! \brief JPEG image implementation.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Windows.Media.Imaging;
|
||||
using GameRes.Utility;
|
||||
|
||||
namespace GameRes
|
||||
{
|
||||
[Export(typeof(ImageFormat))]
|
||||
public class JpegFormat : ImageFormat
|
||||
{
|
||||
public override string Tag { get { return "JPEG"; } }
|
||||
public override string Description { get { return "JPEG image file format"; } }
|
||||
public override uint Signature { get { return 0; } }
|
||||
|
||||
public int Quality { get; set; }
|
||||
|
||||
public JpegFormat ()
|
||||
{
|
||||
Extensions = new string[] { "jpg", "jpeg" };
|
||||
Quality = 90;
|
||||
}
|
||||
|
||||
public override ImageData Read (Stream file, ImageMetaData info)
|
||||
{
|
||||
var decoder = new JpegBitmapDecoder (file,
|
||||
BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
||||
var frame = decoder.Frames[0];
|
||||
frame.Freeze();
|
||||
return new ImageData (frame, info);
|
||||
}
|
||||
|
||||
public override void Write (Stream file, ImageData image)
|
||||
{
|
||||
var encoder = new JpegBitmapEncoder();
|
||||
encoder.QualityLevel = Quality;
|
||||
encoder.Frames.Add (BitmapFrame.Create (image.Bitmap));
|
||||
encoder.Save (file);
|
||||
}
|
||||
|
||||
public override ImageMetaData ReadMetaData (Stream stream)
|
||||
{
|
||||
if (0xff != stream.ReadByte() || 0xd8 != stream.ReadByte())
|
||||
return null;
|
||||
using (var file = new ArcView.Reader (stream))
|
||||
{
|
||||
while (-1 != file.PeekChar())
|
||||
{
|
||||
ushort marker = Binary.BigEndian (file.ReadUInt16());
|
||||
if ((marker & 0xff00) != 0xff00)
|
||||
break;
|
||||
int length = Binary.BigEndian (file.ReadUInt16());
|
||||
if ((marker & 0x00f0) == 0xc0 && marker != 0xffc4)
|
||||
{
|
||||
if (length < 8)
|
||||
break;
|
||||
int bits = file.ReadByte();
|
||||
uint height = Binary.BigEndian (file.ReadUInt16());
|
||||
uint width = Binary.BigEndian (file.ReadUInt16());
|
||||
int components = file.ReadByte();
|
||||
return new ImageMetaData {
|
||||
Width = width,
|
||||
Height = height,
|
||||
BPP = bits * components,
|
||||
};
|
||||
}
|
||||
file.BaseStream.Seek (length-2, SeekOrigin.Current);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
195
GameRes/ImagePNG.cs
Normal file
195
GameRes/ImagePNG.cs
Normal file
@ -0,0 +1,195 @@
|
||||
//! \file ImagePNG.cs
|
||||
//! \date Sat Jul 05 00:09:15 2014
|
||||
//! \brief PNG image implementation.
|
||||
//
|
||||
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Windows.Media.Imaging;
|
||||
using GameRes.Utility;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace GameRes
|
||||
{
|
||||
[Export(typeof(ImageFormat))]
|
||||
public class PngFormat : ImageFormat
|
||||
{
|
||||
public override string Tag { get { return "PNG"; } }
|
||||
public override string Description { get { return "Portable Network Graphics image"; } }
|
||||
public override uint Signature { get { return 0x474e5089; } }
|
||||
|
||||
public override ImageData Read (Stream file, ImageMetaData info)
|
||||
{
|
||||
var decoder = new PngBitmapDecoder (file,
|
||||
BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
||||
BitmapSource frame = decoder.Frames.First();
|
||||
frame.Freeze();
|
||||
return new ImageData (frame, info);
|
||||
}
|
||||
|
||||
public override void Write (Stream file, ImageData image)
|
||||
{
|
||||
var encoder = new PngBitmapEncoder();
|
||||
encoder.Frames.Add (BitmapFrame.Create (image.Bitmap));
|
||||
if (0 == image.OffsetX && 0 == image.OffsetY)
|
||||
{
|
||||
encoder.Save (file);
|
||||
return;
|
||||
}
|
||||
using (var mem_stream = new MemoryStream())
|
||||
{
|
||||
encoder.Save (mem_stream);
|
||||
byte[] buf = mem_stream.GetBuffer();
|
||||
long header_pos = 8;
|
||||
mem_stream.Position = header_pos;
|
||||
uint header_length = ReadChunkLength (mem_stream);
|
||||
file.Write (buf, 0, (int)(header_pos+header_length+12));
|
||||
WriteOffsChunk (file, image);
|
||||
mem_stream.Position = header_pos+header_length+12;
|
||||
mem_stream.CopyTo (file);
|
||||
}
|
||||
}
|
||||
|
||||
uint ReadChunkLength (Stream file)
|
||||
{
|
||||
int length = file.ReadByte() << 24;
|
||||
length |= file.ReadByte() << 16;
|
||||
length |= file.ReadByte() << 8;
|
||||
length |= file.ReadByte();
|
||||
return (uint)length;
|
||||
}
|
||||
|
||||
void WriteOffsChunk (Stream file, ImageData image)
|
||||
{
|
||||
using (var membuf = new MemoryStream (32))
|
||||
{
|
||||
using (var bin = new BinaryWriter (membuf, Encoding.ASCII, true))
|
||||
{
|
||||
bin.Write (Binary.BigEndian ((uint)9));
|
||||
char[] tag = { 'o', 'F', 'F', 's' };
|
||||
bin.Write (tag);
|
||||
bin.Write (Binary.BigEndian ((uint)image.OffsetX));
|
||||
bin.Write (Binary.BigEndian ((uint)image.OffsetY));
|
||||
bin.Write ((byte)0);
|
||||
bin.Flush();
|
||||
uint crc = Crc32.Compute (membuf.GetBuffer(), 8, 9);
|
||||
bin.Write (Binary.BigEndian (crc));
|
||||
}
|
||||
file.Write (membuf.GetBuffer(), 0, 9+12); // chunk + size+id+crc
|
||||
}
|
||||
}
|
||||
|
||||
void SkipBytes (BinaryReader file, uint num)
|
||||
{
|
||||
if (file.BaseStream.CanSeek)
|
||||
file.BaseStream.Seek (num, SeekOrigin.Current);
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < num / 4; ++i)
|
||||
file.ReadInt32();
|
||||
for (int i = 0; i < num % 4; ++i)
|
||||
file.ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
public override ImageMetaData ReadMetaData (Stream stream)
|
||||
{
|
||||
ImageMetaData meta = null;
|
||||
var file = new ArcView.Reader (stream);
|
||||
try
|
||||
{
|
||||
if (file.ReadUInt32() != Signature)
|
||||
return null;
|
||||
if (file.ReadUInt32() != 0x0a1a0a0d)
|
||||
return null;
|
||||
uint chunk_size = Binary.BigEndian (file.ReadUInt32());
|
||||
char[] chunk_type = new char[4];
|
||||
file.Read (chunk_type, 0, 4);
|
||||
if (!chunk_type.SequenceEqual ("IHDR"))
|
||||
return null;
|
||||
|
||||
meta = new ImageMetaData();
|
||||
meta.Width = Binary.BigEndian (file.ReadUInt32());
|
||||
meta.Height = Binary.BigEndian (file.ReadUInt32());
|
||||
int bpp = file.ReadByte();
|
||||
int color_type = file.ReadByte();
|
||||
switch (color_type)
|
||||
{
|
||||
case 2: meta.BPP = bpp*3; break;
|
||||
case 3: meta.BPP = 24; break;
|
||||
case 4: meta.BPP = bpp*2; break;
|
||||
case 6: meta.BPP = bpp*4; break;
|
||||
default: meta.BPP = bpp; break;
|
||||
}
|
||||
SkipBytes (file, 7);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
chunk_size = Binary.BigEndian (file.ReadUInt32());
|
||||
file.Read (chunk_type, 0, 4);
|
||||
if (chunk_type.SequenceEqual ("IDAT") || chunk_type.SequenceEqual ("IEND"))
|
||||
break;
|
||||
if (chunk_type.SequenceEqual ("oFFs"))
|
||||
{
|
||||
int x = Binary.BigEndian (file.ReadInt32());
|
||||
int y = Binary.BigEndian (file.ReadInt32());
|
||||
if (0 == file.ReadByte())
|
||||
{
|
||||
meta.OffsetX = x;
|
||||
meta.OffsetY = y;
|
||||
}
|
||||
break;
|
||||
}
|
||||
SkipBytes (file, chunk_size+4);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
meta = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
file.Dispose();
|
||||
if (stream.CanSeek)
|
||||
stream.Position = 0;
|
||||
}
|
||||
return meta;
|
||||
}
|
||||
|
||||
long FindChunk (Stream stream, string chunk)
|
||||
{
|
||||
char[] find_name = chunk.ToCharArray();
|
||||
long found_offset = -1;
|
||||
var file = new ArcView.Reader (stream);
|
||||
try
|
||||
{
|
||||
char[] buf = new char[4];
|
||||
file.BaseStream.Position = 8;
|
||||
while (-1 != file.PeekChar())
|
||||
{
|
||||
long chunk_offset = file.BaseStream.Position;
|
||||
uint chunk_size = Binary.BigEndian (file.ReadUInt32());
|
||||
if (4 != file.Read (buf, 0, 4))
|
||||
break;
|
||||
if (chunk.SequenceEqual (buf))
|
||||
{
|
||||
found_offset = chunk_offset;
|
||||
break;
|
||||
}
|
||||
file.BaseStream.Position += chunk_size + 4;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore errors
|
||||
}
|
||||
finally
|
||||
{
|
||||
file.Dispose();
|
||||
}
|
||||
return found_offset;
|
||||
}
|
||||
}
|
||||
}
|
204
GameRes/ImageTGA.cs
Normal file
204
GameRes/ImageTGA.cs
Normal file
@ -0,0 +1,204 @@
|
||||
//! \file ImageTGA.cs
|
||||
//! \date Fri Jul 04 07:24:38 2014
|
||||
//! \brief Targa image implementation.
|
||||
//
|
||||
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.ComponentModel.Composition;
|
||||
|
||||
namespace GameRes
|
||||
{
|
||||
public class TgaMetaData : ImageMetaData
|
||||
{
|
||||
public short ImageType;
|
||||
public short ColormapType;
|
||||
public uint ColormapOffset;
|
||||
public ushort ColormapFirst;
|
||||
public ushort ColormapLength;
|
||||
public short ColormapDepth;
|
||||
public short Descriptor;
|
||||
}
|
||||
|
||||
[Export(typeof(ImageFormat))]
|
||||
public class TgaFormat : ImageFormat
|
||||
{
|
||||
public override string Tag { get { return "TGA"; } }
|
||||
public override string Description { get { return "Truevision TGA image"; } }
|
||||
public override uint Signature { get { return 0; } }
|
||||
|
||||
public override ImageData Read (Stream stream, ImageMetaData metadata)
|
||||
{
|
||||
var meta = metadata as TgaMetaData;
|
||||
if (null == meta)
|
||||
throw new System.ArgumentException ("TgaFormat.Read should be supplied with TgaMetaData", "metadata");
|
||||
int colormap_size = meta.ColormapLength * meta.ColormapDepth / 8;
|
||||
int width = (int)meta.Width;
|
||||
int height = (int)meta.Height;
|
||||
int bpp = meta.BPP;
|
||||
long image_offset = meta.ColormapOffset;
|
||||
if (1 == meta.ColormapType)
|
||||
image_offset += colormap_size;
|
||||
switch (meta.ImageType)
|
||||
{
|
||||
case 1: // Uncompressed, color-mapped images.
|
||||
case 3: // Uncompressed, black and white images.
|
||||
case 9: // Runlength encoded color-mapped images.
|
||||
case 10: // Runlength encoded RGB images.
|
||||
case 11: // Compressed, black and white images.
|
||||
case 32: // Compressed color-mapped data, using Huffman, Delta, and
|
||||
// runlength encoding.
|
||||
case 33: // Compressed color-mapped data, using Huffman, Delta, and
|
||||
// runlength encoding. 4-pass quadtree-type process.
|
||||
throw new System.NotImplementedException();
|
||||
default:
|
||||
throw new InvalidFormatException();
|
||||
case 2: // Uncompressed, RGB images.
|
||||
{
|
||||
PixelFormat pixel_format;
|
||||
switch (bpp)
|
||||
{
|
||||
default: throw new InvalidFormatException();
|
||||
case 24: pixel_format = PixelFormats.Bgr24; break;
|
||||
case 32: pixel_format = PixelFormats.Bgra32; break;
|
||||
case 15: pixel_format = PixelFormats.Bgr555; break;
|
||||
case 16: pixel_format = PixelFormats.Bgr565; break;
|
||||
}
|
||||
stream.Position = image_offset;
|
||||
int stride = width*((bpp+7)/8);
|
||||
byte[] data = new byte[stride*height];
|
||||
if (0 != (meta.Descriptor & 0x20))
|
||||
{
|
||||
if (data.Length != stream.Read (data, 0, data.Length))
|
||||
throw new InvalidFormatException();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int row = height-1; row >= 0; --row)
|
||||
{
|
||||
if (stride != stream.Read (data, row*stride, stride))
|
||||
throw new InvalidFormatException();
|
||||
}
|
||||
}
|
||||
var bitmap = BitmapSource.Create (width, height, 96, 96, pixel_format, null,
|
||||
data, stride);
|
||||
bitmap.Freeze();
|
||||
return new ImageData (bitmap, meta);
|
||||
}
|
||||
throw new InvalidFormatException();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write (Stream stream, ImageData image)
|
||||
{
|
||||
using (var file = new BinaryWriter (stream, System.Text.Encoding.ASCII, true))
|
||||
{
|
||||
file.Write ((byte)0); // idlength
|
||||
file.Write ((byte)0); // colourmaptype
|
||||
file.Write ((byte)2); // datatypecode
|
||||
file.Write ((short)0); // colourmaporigin
|
||||
file.Write ((short)0); // colourmaplength
|
||||
file.Write ((byte)0); // colourmapdepth
|
||||
file.Write ((short)image.OffsetX);
|
||||
file.Write ((short)image.OffsetY);
|
||||
file.Write ((ushort)image.Width);
|
||||
file.Write ((ushort)image.Height);
|
||||
|
||||
var bitmap = image.Bitmap;
|
||||
int bpp = 0;
|
||||
int stride = 0;
|
||||
byte descriptor = 0;
|
||||
if (PixelFormats.Bgr24 == bitmap.Format)
|
||||
{
|
||||
bpp = 24;
|
||||
stride = (int)image.Width*3;
|
||||
}
|
||||
else if (PixelFormats.Bgr32 == bitmap.Format)
|
||||
{
|
||||
bpp = 32;
|
||||
stride = (int)image.Width*4;
|
||||
}
|
||||
else
|
||||
{
|
||||
bpp = 32;
|
||||
stride = (int)image.Width*4;
|
||||
if (PixelFormats.Bgra32 != bitmap.Format)
|
||||
{
|
||||
var converted_bitmap = new FormatConvertedBitmap();
|
||||
converted_bitmap.BeginInit();
|
||||
converted_bitmap.Source = image.Bitmap;
|
||||
converted_bitmap.DestinationFormat = PixelFormats.Bgra32;
|
||||
converted_bitmap.EndInit();
|
||||
bitmap = converted_bitmap;
|
||||
}
|
||||
}
|
||||
file.Write ((byte)bpp);
|
||||
file.Write (descriptor);
|
||||
byte[] row_data = new byte[stride];
|
||||
Int32Rect rect = new Int32Rect (0, (int)image.Height, (int)image.Width, 1);
|
||||
for (uint row = 0; row < image.Height; ++row)
|
||||
{
|
||||
--rect.Y;
|
||||
bitmap.CopyPixels (rect, row_data, stride, 0);
|
||||
file.Write (row_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override ImageMetaData ReadMetaData (Stream stream)
|
||||
{
|
||||
using (var file = new ArcView.Reader (stream))
|
||||
{
|
||||
short id_length = file.ReadByte();
|
||||
short colormap_type = file.ReadByte();
|
||||
if (colormap_type > 1)
|
||||
return null;
|
||||
short image_type = file.ReadByte();
|
||||
ushort colormap_first = file.ReadUInt16();
|
||||
ushort colormap_length = file.ReadUInt16();
|
||||
short colormap_depth = file.ReadByte();
|
||||
int pos_x = file.ReadInt16();
|
||||
int pos_y = file.ReadInt16();
|
||||
uint width = file.ReadUInt16();
|
||||
uint height = file.ReadUInt16();
|
||||
int bpp = file.ReadByte();
|
||||
if (bpp != 32 && bpp != 24 && bpp != 16 && bpp != 15 && bpp != 8)
|
||||
return null;
|
||||
short descriptor = file.ReadByte();
|
||||
uint colormap_offset = (uint)(18 + id_length);
|
||||
switch (image_type)
|
||||
{
|
||||
default: return null;
|
||||
case 1: // Uncompressed, color-mapped images.
|
||||
case 2: // Uncompressed, RGB images.
|
||||
case 3: // Uncompressed, black and white images.
|
||||
case 9: // Runlength encoded color-mapped images.
|
||||
case 10: // Runlength encoded RGB images.
|
||||
case 11: // Compressed, black and white images.
|
||||
case 32: // Compressed color-mapped data, using Huffman, Delta, and
|
||||
// runlength encoding.
|
||||
case 33: // Compressed color-mapped data, using Huffman, Delta, and
|
||||
// runlength encoding. 4-pass quadtree-type process.
|
||||
break;
|
||||
}
|
||||
return new TgaMetaData {
|
||||
OffsetX = pos_x,
|
||||
OffsetY = pos_y,
|
||||
Width = width,
|
||||
Height = height,
|
||||
BPP = bpp,
|
||||
ImageType = image_type,
|
||||
ColormapType = colormap_type,
|
||||
ColormapOffset = colormap_offset,
|
||||
ColormapFirst = colormap_first,
|
||||
ColormapLength = colormap_length,
|
||||
ColormapDepth = colormap_depth,
|
||||
Descriptor = descriptor,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
363
GameRes/ImageTIFF.cs
Normal file
363
GameRes/ImageTIFF.cs
Normal file
@ -0,0 +1,363 @@
|
||||
//! \file ImageTIFF.cs
|
||||
//! \date Mon Jul 07 06:39:45 2014
|
||||
//! \brief TIFF image implementation.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Windows.Media.Imaging;
|
||||
using GameRes.Utility;
|
||||
|
||||
namespace GameRes
|
||||
{
|
||||
#if DEBUG
|
||||
// FIXME
|
||||
// .Net TIFF encoder messes up transparency,
|
||||
// therefore this class is disabled in release build
|
||||
[Export(typeof(ImageFormat))]
|
||||
#endif
|
||||
public class TifFormat : ImageFormat
|
||||
{
|
||||
public override string Tag { get { return "TIFF"; } }
|
||||
public override string Description { get { return "Tagged Image File Format"; } }
|
||||
public override uint Signature { get { return 0; } }
|
||||
|
||||
public TifFormat ()
|
||||
{
|
||||
Extensions = new string[] { "tif", "tiff" };
|
||||
Signatures = new uint[] { 0x002a4949, 0x2a004d4d };
|
||||
}
|
||||
|
||||
public override ImageData Read (Stream file, ImageMetaData info)
|
||||
{
|
||||
var decoder = new TiffBitmapDecoder (file,
|
||||
BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
|
||||
var frame = decoder.Frames[0];
|
||||
frame.Freeze();
|
||||
return new ImageData (frame, info);
|
||||
}
|
||||
|
||||
public override void Write (Stream file, ImageData image)
|
||||
{
|
||||
var encoder = new TiffBitmapEncoder();
|
||||
encoder.Compression = TiffCompressOption.Zip;
|
||||
encoder.Frames.Add (BitmapFrame.Create (image.Bitmap));
|
||||
encoder.Save (file);
|
||||
}
|
||||
|
||||
private delegate uint UInt32Reader();
|
||||
private delegate ushort UInt16Reader();
|
||||
|
||||
enum TIFF
|
||||
{
|
||||
ImageWidth = 0x100,
|
||||
ImageHeight = 0x101,
|
||||
BitsPerSample = 0x102,
|
||||
Compression = 0x103,
|
||||
SamplesPerPixel = 0x115,
|
||||
XResolution = 0x11a,
|
||||
YResolution = 0x11b,
|
||||
XPosition = 0x11e,
|
||||
YPosition = 0x11f,
|
||||
}
|
||||
enum TagType
|
||||
{
|
||||
Byte = 1,
|
||||
Ascii = 2,
|
||||
Short = 3,
|
||||
Long = 4,
|
||||
Rational = 5,
|
||||
SByte = 6,
|
||||
Undefined = 7,
|
||||
SShort = 8,
|
||||
SLong = 9,
|
||||
SRational = 10,
|
||||
Float = 11,
|
||||
Double = 12,
|
||||
LastKnown = Double,
|
||||
}
|
||||
enum MetaParsed
|
||||
{
|
||||
None = 0,
|
||||
Width = 1,
|
||||
Height = 2,
|
||||
BPP = 4,
|
||||
PosX = 8,
|
||||
PosY = 16,
|
||||
Sufficient = Width|Height|BPP,
|
||||
Complete = Sufficient|PosX|PosY,
|
||||
}
|
||||
|
||||
public override ImageMetaData ReadMetaData (Stream stream)
|
||||
{
|
||||
using (var file = new Parser (stream))
|
||||
return file.ReadMetaData();
|
||||
}
|
||||
|
||||
public class Parser : IDisposable
|
||||
{
|
||||
private BinaryReader m_file;
|
||||
private readonly bool m_is_bigendian;
|
||||
private readonly uint m_first_ifd;
|
||||
private readonly uint[] m_type_size = { 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8 };
|
||||
|
||||
private delegate ushort UInt16Reader ();
|
||||
private delegate uint UInt32Reader ();
|
||||
private delegate ulong UInt64Reader ();
|
||||
|
||||
UInt16Reader ReadUInt16;
|
||||
UInt32Reader ReadUInt32;
|
||||
UInt64Reader ReadUInt64;
|
||||
|
||||
public Parser (Stream file)
|
||||
{
|
||||
m_file = new ArcView.Reader (file);
|
||||
uint signature = m_file.ReadUInt32();
|
||||
m_is_bigendian = 0x2a004d4d == signature;
|
||||
if (m_is_bigendian)
|
||||
{
|
||||
ReadUInt16 = () => Binary.BigEndian (m_file.ReadUInt16());
|
||||
ReadUInt32 = () => Binary.BigEndian (m_file.ReadUInt32());
|
||||
ReadUInt64 = () => Binary.BigEndian (m_file.ReadUInt64());
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadUInt16 = () => m_file.ReadUInt16();
|
||||
ReadUInt32 = () => m_file.ReadUInt32();
|
||||
ReadUInt64 = () => m_file.ReadUInt64();
|
||||
}
|
||||
m_first_ifd = ReadUInt32();
|
||||
}
|
||||
|
||||
public long FindLastIFD ()
|
||||
{
|
||||
uint ifd = m_first_ifd;
|
||||
for (;;)
|
||||
{
|
||||
m_file.BaseStream.Position = ifd;
|
||||
uint tag_count = ReadUInt16();
|
||||
ifd += 2 + tag_count*12;
|
||||
uint ifd_next = ReadUInt32();
|
||||
if (0 == ifd_next)
|
||||
break;
|
||||
if (ifd_next == ifd || ifd_next >= m_file.BaseStream.Length)
|
||||
return -1;
|
||||
ifd = ifd_next;
|
||||
}
|
||||
return ifd;
|
||||
}
|
||||
|
||||
public ImageMetaData ReadMetaData ()
|
||||
{
|
||||
MetaParsed parsed = MetaParsed.None;
|
||||
int width = 0, height = 0, bpp = 0, pos_x = 0, pos_y = 0;
|
||||
uint ifd = m_first_ifd;
|
||||
while (ifd != 0 && parsed != MetaParsed.Complete)
|
||||
{
|
||||
m_file.BaseStream.Position = ifd;
|
||||
uint tag_count = ReadUInt16();
|
||||
ifd += 2;
|
||||
for (uint i = 0; i < tag_count && parsed != MetaParsed.Complete; ++i)
|
||||
{
|
||||
ushort tag = ReadUInt16();
|
||||
TagType type = (TagType)ReadUInt16();
|
||||
uint count = ReadUInt32();
|
||||
if (0 != count && 0 != type && type <= TagType.LastKnown)
|
||||
{
|
||||
switch ((TIFF)tag)
|
||||
{
|
||||
case TIFF.ImageWidth:
|
||||
if (1 == count)
|
||||
if (ReadOffsetValue (type, out width))
|
||||
parsed |= MetaParsed.Width;
|
||||
break;
|
||||
case TIFF.ImageHeight:
|
||||
if (1 == count)
|
||||
if (ReadOffsetValue (type, out height))
|
||||
parsed |= MetaParsed.Height;
|
||||
break;
|
||||
case TIFF.XPosition:
|
||||
if (1 == count)
|
||||
if (ReadOffsetValue (type, out pos_x))
|
||||
parsed |= MetaParsed.PosX;
|
||||
break;
|
||||
case TIFF.YPosition:
|
||||
if (1 == count)
|
||||
if (ReadOffsetValue (type, out pos_y))
|
||||
parsed |= MetaParsed.PosY;
|
||||
break;
|
||||
case TIFF.BitsPerSample:
|
||||
if (count * GetTypeSize (type) > 4)
|
||||
{
|
||||
var bpp_offset = ReadUInt32();
|
||||
m_file.BaseStream.Position = bpp_offset;
|
||||
}
|
||||
bpp = 0;
|
||||
for (uint b = 0; b < count; ++b)
|
||||
{
|
||||
int plane = 0;
|
||||
ReadValue (type, out plane);
|
||||
bpp += plane;
|
||||
}
|
||||
parsed |= MetaParsed.BPP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
ifd += 12;
|
||||
m_file.BaseStream.Position = ifd;
|
||||
}
|
||||
uint ifd_next = ReadUInt32();
|
||||
if (ifd_next == ifd)
|
||||
break;
|
||||
ifd = ifd_next;
|
||||
}
|
||||
if (MetaParsed.Sufficient == (parsed & MetaParsed.Sufficient))
|
||||
return new ImageMetaData() {
|
||||
Width = (uint)width,
|
||||
Height = (uint)height,
|
||||
OffsetX = pos_x,
|
||||
OffsetY = pos_y,
|
||||
BPP = bpp,
|
||||
};
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
uint GetTypeSize (TagType type)
|
||||
{
|
||||
if ((int)type < m_type_size.Length)
|
||||
return m_type_size[(int)type];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ReadOffsetValue (TagType type, out int value)
|
||||
{
|
||||
if (GetTypeSize (type) > 4)
|
||||
m_file.BaseStream.Position = ReadUInt32();
|
||||
return ReadValue (type, out value);
|
||||
}
|
||||
|
||||
bool ReadValue (TagType type, out int value)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TagType.Undefined:
|
||||
case TagType.SByte:
|
||||
case TagType.Byte:
|
||||
value = m_file.ReadByte();
|
||||
break;
|
||||
default:
|
||||
case TagType.Ascii:
|
||||
value = 0;
|
||||
return false;
|
||||
case TagType.SShort:
|
||||
case TagType.Short:
|
||||
value = ReadUInt16();
|
||||
break;
|
||||
case TagType.SLong:
|
||||
case TagType.Long:
|
||||
value = (int)ReadUInt32();
|
||||
break;
|
||||
case TagType.Rational:
|
||||
return ReadRational (out value);
|
||||
case TagType.SRational:
|
||||
return ReadSRational (out value);
|
||||
case TagType.Float:
|
||||
return ReadFloat (out value);
|
||||
case TagType.Double:
|
||||
return ReadDouble (out value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadRational (out int value)
|
||||
{
|
||||
uint numer = ReadUInt32();
|
||||
uint denom = ReadUInt32();
|
||||
if (1 == denom)
|
||||
value = (int)numer;
|
||||
else if (0 == denom)
|
||||
{
|
||||
value = 0;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
value = (int)((double)numer / denom);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadSRational (out int value)
|
||||
{
|
||||
int numer = (int)ReadUInt32();
|
||||
int denom = (int)ReadUInt32();
|
||||
if (1 == denom)
|
||||
value = numer;
|
||||
else if (0 == denom)
|
||||
{
|
||||
value = 0;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
value = (int)((double)numer / denom);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadFloat (out int value)
|
||||
{
|
||||
var convert_buffer = new byte[4];
|
||||
if (4 != m_file.Read (convert_buffer, 0, 4))
|
||||
{
|
||||
value = 0;
|
||||
return false;
|
||||
}
|
||||
if (m_is_bigendian)
|
||||
Array.Reverse (convert_buffer);
|
||||
value = (int)BitConverter.ToSingle (convert_buffer, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadDouble (out int value)
|
||||
{
|
||||
var convert_buffer = new byte[8];
|
||||
if (8 != m_file.Read (convert_buffer, 0, 8))
|
||||
{
|
||||
value = 0;
|
||||
return false;
|
||||
}
|
||||
if (m_is_bigendian)
|
||||
Array.Reverse (convert_buffer);
|
||||
long bits = BitConverter.ToInt64 (convert_buffer, 0);
|
||||
value = (int)BitConverter.Int64BitsToDouble (bits);
|
||||
return true;
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
bool disposed = false;
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
m_file.Dispose();
|
||||
}
|
||||
m_file = null;
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
162
GameRes/MultiDict.cs
Normal file
162
GameRes/MultiDict.cs
Normal file
@ -0,0 +1,162 @@
|
||||
//! \file GameRes.cs
|
||||
//! \date Mon Jun 30 20:12:13 2014
|
||||
//! \brief game resources browser.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GameRes.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension to the normal Dictionary. This class can store more than one value for every key.
|
||||
/// It keeps a HashSet for every Key value. Calling Add with the same Key and multiple values
|
||||
/// will store each value under the same Key in the Dictionary. Obtaining the values for a Key
|
||||
/// will return the HashSet with the Values of the Key.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The type of the key.</typeparam>
|
||||
/// <typeparam name="TValue">The type of the value.</typeparam>
|
||||
public class MultiValueDictionary<TKey, TValue> : Dictionary<TKey, HashSet<TValue>> //, IEnumerable<KeyValuePair<TKey, TValue>>, System.Collections.IEnumerable
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MultiValueDictionary<TKey, TValue>"/> class.
|
||||
/// </summary>
|
||||
public MultiValueDictionary() : base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified value under the specified key
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
public void Add(TKey key, TValue value)
|
||||
{
|
||||
HashSet<TValue> container = null;
|
||||
if(!this.TryGetValue(key, out container))
|
||||
{
|
||||
container = new HashSet<TValue>();
|
||||
base.Add(key, container);
|
||||
}
|
||||
container.Add(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the specified value for the specified key. It will leave the key in the dictionary.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
public void Remove(TKey key, TValue value)
|
||||
{
|
||||
HashSet<TValue> container = null;
|
||||
if(this.TryGetValue(key, out container))
|
||||
{
|
||||
container.Remove(value);
|
||||
if(container.Count <= 0)
|
||||
{
|
||||
this.Remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the values for the key specified. This method is useful if you want to avoid an
|
||||
/// exception for key value retrieval and you can't use TryGetValue (e.g. in lambdas)
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="returnEmptySet">if set to true and the key isn't found, an empty hashset is
|
||||
/// returned, otherwise, if the key isn't found, null is returned</param>
|
||||
/// <returns>
|
||||
/// This method will return null (or an empty set if returnEmptySet is true) if the key
|
||||
/// wasn't found, or the values if key was found.
|
||||
/// </returns>
|
||||
public HashSet<TValue> GetValues(TKey key, bool returnEmptySet)
|
||||
{
|
||||
HashSet<TValue> toReturn = null;
|
||||
if (!base.TryGetValue(key, out toReturn) && returnEmptySet)
|
||||
{
|
||||
toReturn = new HashSet<TValue>();
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
/*
|
||||
// hides Dictionary.GetEnumerator()
|
||||
new public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
Enumerator e = new Enumerator();
|
||||
e.key_enumerator = base.GetEnumerator();
|
||||
e.current_pair = new KeyValuePair<TKey, TValue>();
|
||||
if (e.key_enumerator.MoveNext())
|
||||
e.value_enumerator = e.key_enumerator.Current.Value.GetEnumerator();
|
||||
else
|
||||
e.value_enumerator = null;
|
||||
return e;
|
||||
}
|
||||
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
||||
{
|
||||
return (System.Collections.IEnumerator)GetEnumerator();
|
||||
}
|
||||
|
||||
[SerializableAttribute]
|
||||
new public struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>, IDisposable, System.Collections.IEnumerator
|
||||
{
|
||||
public Dictionary<TKey, HashSet<TValue>>.Enumerator key_enumerator;
|
||||
public HashSet<TValue>.Enumerator? value_enumerator;
|
||||
public KeyValuePair<TKey, TValue> current_pair;
|
||||
|
||||
public KeyValuePair<TKey, TValue> Current { get { return current_pair; } }
|
||||
object System.Collections.IEnumerator.Current { get { return Current; } }
|
||||
|
||||
void IDisposable.Dispose() { }
|
||||
|
||||
void System.Collections.IEnumerator.Reset()
|
||||
{
|
||||
}
|
||||
|
||||
private void SetCurrent ()
|
||||
{
|
||||
current_pair = new KeyValuePair<TKey, TValue>(key_enumerator.Current.Key, value_enumerator.Value.Current);
|
||||
Console.WriteLine("Enumerator.SetCurrent ({0} => {1})", current_pair.Key, current_pair.Value);
|
||||
}
|
||||
|
||||
private void ResetCurrent ()
|
||||
{
|
||||
current_pair = new KeyValuePair<TKey, TValue>(default(TKey), default(TValue));
|
||||
}
|
||||
|
||||
public bool MoveNext ()
|
||||
{
|
||||
if (null == value_enumerator)
|
||||
{
|
||||
ResetCurrent();
|
||||
return false;
|
||||
}
|
||||
if (value_enumerator.Value.MoveNext())
|
||||
{
|
||||
SetCurrent();
|
||||
return true;
|
||||
}
|
||||
if (!key_enumerator.MoveNext())
|
||||
{
|
||||
value_enumerator = null;
|
||||
ResetCurrent();
|
||||
return false;
|
||||
}
|
||||
value_enumerator = key_enumerator.Current.Value.GetEnumerator();
|
||||
if (value_enumerator.Value.MoveNext())
|
||||
{
|
||||
SetCurrent();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_pair = new KeyValuePair<TKey, TValue>(key_enumerator.Current.Key, default(TValue));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
36
GameRes/Properties/AssemblyInfo.cs
Normal file
36
GameRes/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("GameRes")]
|
||||
[assembly: AssemblyDescription("Game Resources class library")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("GameRes")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014 mørkt")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("224080ad-deb6-4d47-a454-903a14c74cb7")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
36
GameRes/ScriptText.cs
Normal file
36
GameRes/ScriptText.cs
Normal file
@ -0,0 +1,36 @@
|
||||
//! \file ScriptText.cs
|
||||
//! \date Thu Jul 10 11:09:32 2014
|
||||
//! \brief Script text resource interface.
|
||||
//
|
||||
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GameRes
|
||||
{
|
||||
public struct ScriptLine
|
||||
{
|
||||
public uint Id;
|
||||
public string Text;
|
||||
}
|
||||
|
||||
public class ScriptData
|
||||
{
|
||||
public ICollection<ScriptLine> TextLines { get { return m_text; } }
|
||||
|
||||
protected List<ScriptLine> m_text = new List<ScriptLine>();
|
||||
/*
|
||||
public abstract void Serialize (Stream output);
|
||||
public abstract void Deserialize (Stream input);
|
||||
*/
|
||||
}
|
||||
|
||||
public abstract class ScriptFormat : IResource
|
||||
{
|
||||
public override string Type { get { return "script"; } }
|
||||
|
||||
public abstract ScriptData Read (string name, Stream file);
|
||||
public abstract void Write (Stream file, ScriptData script);
|
||||
}
|
||||
}
|
90
GameRes/Strings/garStrings.Designer.cs
generated
Normal file
90
GameRes/Strings/garStrings.Designer.cs
generated
Normal file
@ -0,0 +1,90 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.18444
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace GameRes.Strings {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class garStrings {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal garStrings() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GameRes.Strings.garStrings", typeof(garStrings).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Inappropriate encryption scheme.
|
||||
/// </summary>
|
||||
public static string MsgInvalidEncryption {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgInvalidEncryption", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Invalid file format.
|
||||
/// </summary>
|
||||
public static string MsgInvalidFormat {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgInvalidFormat", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unknown encryption scheme.
|
||||
/// </summary>
|
||||
public static string MsgUnknownEncryption {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgUnknownEncryption", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
129
GameRes/Strings/garStrings.resx
Normal file
129
GameRes/Strings/garStrings.resx
Normal file
@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="MsgInvalidEncryption" xml:space="preserve">
|
||||
<value>Inappropriate encryption scheme</value>
|
||||
</data>
|
||||
<data name="MsgInvalidFormat" xml:space="preserve">
|
||||
<value>Invalid file format</value>
|
||||
</data>
|
||||
<data name="MsgUnknownEncryption" xml:space="preserve">
|
||||
<value>Unknown encryption scheme</value>
|
||||
</data>
|
||||
</root>
|
129
GameRes/Strings/garStrings.ru-RU.resx
Normal file
129
GameRes/Strings/garStrings.ru-RU.resx
Normal file
@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="MsgInvalidEncryption" xml:space="preserve">
|
||||
<value>Неподходящий метод шифрования</value>
|
||||
</data>
|
||||
<data name="MsgInvalidFormat" xml:space="preserve">
|
||||
<value>Некорректный формат файла</value>
|
||||
</data>
|
||||
<data name="MsgUnknownEncryption" xml:space="preserve">
|
||||
<value>Неизвестный метод шифрования</value>
|
||||
</data>
|
||||
</root>
|
235
GameRes/Utility.cs
Normal file
235
GameRes/Utility.cs
Normal file
@ -0,0 +1,235 @@
|
||||
//! \file Utility.cs
|
||||
//! \date Sat Jul 05 02:47:33 2014
|
||||
//! \brief utility class for GameRes assembly.
|
||||
//
|
||||
|
||||
namespace GameRes.Utility
|
||||
{
|
||||
public static class Binary
|
||||
{
|
||||
public static uint BigEndian (uint u)
|
||||
{
|
||||
return (u & 0xff) << 24 | (u & 0xff00) << 8 | (u & 0xff0000) >> 8 | (u & 0xff000000) >> 24;
|
||||
}
|
||||
public static int BigEndian (int i)
|
||||
{
|
||||
return (int)BigEndian ((uint)i);
|
||||
}
|
||||
public static ushort BigEndian (ushort u)
|
||||
{
|
||||
return (ushort)((u & 0xff) << 8 | (u & 0xff00) >> 8);
|
||||
}
|
||||
public static short BigEndian (short i)
|
||||
{
|
||||
return (short)BigEndian ((ushort)i);
|
||||
}
|
||||
public static ulong BigEndian (ulong u)
|
||||
{
|
||||
return (ulong)BigEndian((uint)(u & 0xffffffff)) << 32
|
||||
| (ulong)BigEndian((uint)(u >> 32));
|
||||
}
|
||||
public static long BigEndian (long i)
|
||||
{
|
||||
return (long)BigEndian ((ulong)i);
|
||||
}
|
||||
|
||||
public static bool AsciiEqual (byte[] name1, string name2)
|
||||
{
|
||||
return AsciiEqual (name1, 0, name2);
|
||||
}
|
||||
|
||||
public static bool AsciiEqual (byte[] name1, int offset, string name2)
|
||||
{
|
||||
if (name1.Length-offset < name2.Length)
|
||||
return false;
|
||||
for (int i = 0; i < name2.Length; ++i)
|
||||
if ((char)name1[offset+i] != name2[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LittleEndian
|
||||
{
|
||||
public static ushort ToUInt16 (byte[] value, int index)
|
||||
{
|
||||
return (ushort)(value[index] | value[index+1] << 8);
|
||||
}
|
||||
|
||||
public static short ToInt16 (byte[] value, int index)
|
||||
{
|
||||
return (short)(value[index] | value[index+1] << 8);
|
||||
}
|
||||
|
||||
public static uint ToUInt32 (byte[] value, int index)
|
||||
{
|
||||
return (uint)(value[index] | value[index+1] << 8 | value[index+2] << 16 | value[index+3] << 24);
|
||||
}
|
||||
|
||||
public static int ToInt32 (byte[] value, int index)
|
||||
{
|
||||
return (int)ToUInt32 (value, index);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Crc32
|
||||
{
|
||||
/* Table of CRCs of all 8-bit messages. */
|
||||
private static readonly uint[] crc_table = InitializeTable();
|
||||
|
||||
/* Make the table for a fast CRC. */
|
||||
private static uint[] InitializeTable ()
|
||||
{
|
||||
uint[] table = new uint[256];
|
||||
for (uint n = 0; n < 256; n++)
|
||||
{
|
||||
uint c = n;
|
||||
for (int k = 0; k < 8; k++)
|
||||
{
|
||||
if (0 != (c & 1))
|
||||
c = 0xedb88320 ^ (c >> 1);
|
||||
else
|
||||
c = c >> 1;
|
||||
}
|
||||
table[n] = c;
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
/* Update a running CRC with the bytes buf[0..len-1]--the CRC
|
||||
should be initialized to all 1's, and the transmitted value
|
||||
is the 1's complement of the final running CRC (see the
|
||||
crc() routine below)). */
|
||||
static uint UpdateCrc (uint crc, byte[] buf, int pos, int len)
|
||||
{
|
||||
uint c = crc;
|
||||
for (int n = 0; n < len; n++)
|
||||
c = crc_table[(c ^ buf[pos+n]) & 0xff] ^ (c >> 8);
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Return the CRC of the bytes buf[0..len-1]. */
|
||||
public static uint Compute (byte[] buf, int pos, int len)
|
||||
{
|
||||
return UpdateCrc (0xffffffff, buf, pos, len) ^ 0xffffffff;
|
||||
}
|
||||
|
||||
private uint m_crc = 0xffffffff;
|
||||
public uint Value { get { return m_crc^0xffffffff; } }
|
||||
|
||||
public void Update (byte[] buf, int pos, int len)
|
||||
{
|
||||
m_crc = UpdateCrc (m_crc, buf, pos, len);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Adler32
|
||||
{
|
||||
const uint BASE = 65521; /* largest prime smaller than 65536 */
|
||||
const int NMAX = 5552;
|
||||
|
||||
public static uint Compute (byte[] buf, int pos, int len)
|
||||
{
|
||||
return Update (1, buf, pos, len);
|
||||
}
|
||||
|
||||
private static uint Update (uint adler, byte[] buf, int pos, int len)
|
||||
{
|
||||
/* split Adler-32 into component sums */
|
||||
uint sum2 = (adler >> 16) & 0xffff;
|
||||
adler &= 0xffff;
|
||||
|
||||
/* in case user likes doing a byte at a time, keep it fast */
|
||||
if (1 == len) {
|
||||
adler += buf[pos];
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
sum2 += adler;
|
||||
if (sum2 >= BASE)
|
||||
sum2 -= BASE;
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* in case short lengths are provided, keep it somewhat fast */
|
||||
if (len < 16) {
|
||||
while (0 != len--) {
|
||||
adler += buf[pos++];
|
||||
sum2 += adler;
|
||||
}
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
sum2 %= BASE; /* only added so many BASE's */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* do length NMAX blocks -- requires just one modulo operation */
|
||||
while (len >= NMAX) {
|
||||
len -= NMAX;
|
||||
int n = NMAX / 16; /* NMAX is divisible by 16 */
|
||||
do {
|
||||
/* 16 sums unrolled */
|
||||
adler += buf[pos]; sum2 += adler;
|
||||
adler += buf[pos+1]; sum2 += adler;
|
||||
adler += buf[pos+2]; sum2 += adler;
|
||||
adler += buf[pos+3]; sum2 += adler;
|
||||
adler += buf[pos+4]; sum2 += adler;
|
||||
adler += buf[pos+5]; sum2 += adler;
|
||||
adler += buf[pos+6]; sum2 += adler;
|
||||
adler += buf[pos+7]; sum2 += adler;
|
||||
adler += buf[pos+8]; sum2 += adler;
|
||||
adler += buf[pos+9]; sum2 += adler;
|
||||
adler += buf[pos+10]; sum2 += adler;
|
||||
adler += buf[pos+11]; sum2 += adler;
|
||||
adler += buf[pos+12]; sum2 += adler;
|
||||
adler += buf[pos+13]; sum2 += adler;
|
||||
adler += buf[pos+14]; sum2 += adler;
|
||||
adler += buf[pos+15]; sum2 += adler;
|
||||
pos += 16;
|
||||
} while (0 != --n);
|
||||
adler %= BASE;
|
||||
sum2 %= BASE;
|
||||
}
|
||||
|
||||
/* do remaining bytes (less than NMAX, still just one modulo) */
|
||||
if (0 != len) { /* avoid modulos if none remaining */
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
adler += buf[pos]; sum2 += adler;
|
||||
adler += buf[pos+1]; sum2 += adler;
|
||||
adler += buf[pos+2]; sum2 += adler;
|
||||
adler += buf[pos+3]; sum2 += adler;
|
||||
adler += buf[pos+4]; sum2 += adler;
|
||||
adler += buf[pos+5]; sum2 += adler;
|
||||
adler += buf[pos+6]; sum2 += adler;
|
||||
adler += buf[pos+7]; sum2 += adler;
|
||||
adler += buf[pos+8]; sum2 += adler;
|
||||
adler += buf[pos+9]; sum2 += adler;
|
||||
adler += buf[pos+10]; sum2 += adler;
|
||||
adler += buf[pos+11]; sum2 += adler;
|
||||
adler += buf[pos+12]; sum2 += adler;
|
||||
adler += buf[pos+13]; sum2 += adler;
|
||||
adler += buf[pos+14]; sum2 += adler;
|
||||
adler += buf[pos+15]; sum2 += adler;
|
||||
pos += 16;
|
||||
}
|
||||
while (0 != len--) {
|
||||
adler += buf[pos++];
|
||||
sum2 += adler;
|
||||
}
|
||||
adler %= BASE;
|
||||
sum2 %= BASE;
|
||||
}
|
||||
|
||||
/* return recombined sums */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
private uint m_adler = 1;
|
||||
public uint Value { get { return m_adler; } }
|
||||
|
||||
public void Update (byte[] buf, int pos, int len)
|
||||
{
|
||||
m_adler = Update (m_adler, buf, pos, len);
|
||||
}
|
||||
}
|
||||
}
|
109
HistoryStack.cs
Normal file
109
HistoryStack.cs
Normal file
@ -0,0 +1,109 @@
|
||||
//! \file HistoryStack.cs
|
||||
//! \date Sun Aug 21 01:06:53 2011
|
||||
//! \brief action history stack interface (undo/redo).
|
||||
//
|
||||
// Copyright (C) 2011 by poddav
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Rnd.Windows
|
||||
{
|
||||
public class HistoryStack<State>
|
||||
{
|
||||
private List<State> m_back = new List<State>();
|
||||
private Stack<State> m_forward = new Stack<State>();
|
||||
|
||||
public int Limit { get; set; }
|
||||
|
||||
public IEnumerable<State> UndoStack { get { return m_back; } }
|
||||
public IEnumerable<State> RedoStack { get { return m_forward; } }
|
||||
|
||||
public HistoryStack (int limit = 50)
|
||||
{
|
||||
Limit = limit;
|
||||
}
|
||||
|
||||
public State Undo (State current)
|
||||
{
|
||||
if (!CanUndo())
|
||||
return default(State);
|
||||
|
||||
m_forward.Push (current);
|
||||
current = m_back.Last();
|
||||
m_back.RemoveAt (m_back.Count - 1);
|
||||
OnStateChanged();
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
public State Redo (State current)
|
||||
{
|
||||
if (!CanRedo())
|
||||
return default(State);
|
||||
|
||||
m_back.Add (current);
|
||||
current = m_forward.Pop();
|
||||
OnStateChanged();
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
public bool CanUndo ()
|
||||
{
|
||||
return m_back.Any();
|
||||
}
|
||||
|
||||
public bool CanRedo ()
|
||||
{
|
||||
return m_forward.Any();
|
||||
}
|
||||
|
||||
public void Push (State current)
|
||||
{
|
||||
m_back.Add (current);
|
||||
if (m_back.Count > Limit)
|
||||
m_back.RemoveRange (0, m_back.Count - Limit);
|
||||
|
||||
m_forward.Clear();
|
||||
OnStateChanged();
|
||||
}
|
||||
|
||||
public void Clear ()
|
||||
{
|
||||
if (m_back.Any() || m_forward.Any())
|
||||
{
|
||||
m_back.Clear();
|
||||
m_forward.Clear();
|
||||
OnStateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler StateChanged;
|
||||
|
||||
private void OnStateChanged ()
|
||||
{
|
||||
if (StateChanged != null)
|
||||
StateChanged (this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
6
Image.Convert/App.config
Normal file
6
Image.Convert/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/>
|
||||
</startup>
|
||||
</configuration>
|
70
Image.Convert/Image.Convert.csproj
Normal file
70
Image.Convert/Image.Convert.csproj
Normal file
@ -0,0 +1,70 @@
|
||||
<?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>{757EB8B1-F62C-4690-AC3D-DAE4A5576B3E}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Image.Convert</RootNamespace>
|
||||
<AssemblyName>Image.Convert</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</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|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</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>
|
||||
<NoWin32Manifest>true</NoWin32Manifest>
|
||||
</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" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\GameRes\GameRes.csproj">
|
||||
<Project>{453c087f-e416-4ae9-8c03-d8760da0574b}</Project>
|
||||
<Name>GameRes</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>
|
6
Image.Convert/Image.Convert.csproj.user
Normal file
6
Image.Convert/Image.Convert.csproj.user
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||
<StartArguments>-t tga uninstall.hg3</StartArguments>
|
||||
</PropertyGroup>
|
||||
</Project>
|
174
Image.Convert/Program.cs
Normal file
174
Image.Convert/Program.cs
Normal file
@ -0,0 +1,174 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using GameRes;
|
||||
|
||||
namespace GARbro
|
||||
{
|
||||
class ImageConverter
|
||||
{
|
||||
static string ProgramName
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetExecutingAssembly().Location);
|
||||
}
|
||||
}
|
||||
|
||||
void Usage ()
|
||||
{
|
||||
Console.WriteLine("Usage: {0} [OPTIONS] IMAGE", ProgramName);
|
||||
Console.WriteLine(" -l list recognized image FormatCatalog.Instance");
|
||||
Console.WriteLine(" -t FORMAT convert image(s) to specified format");
|
||||
Console.WriteLine("Without options image metadata is displayed.");
|
||||
}
|
||||
|
||||
void ListFormats ()
|
||||
{
|
||||
Console.WriteLine("Supported image formats:");
|
||||
foreach (var impl in FormatCatalog.Instance.ImageFormats)
|
||||
{
|
||||
Console.Write ("{0,-4} ", impl.Tag);
|
||||
if (impl.IsBuiltin) Console.Write ("[builtin] ");
|
||||
Console.WriteLine (impl.Description);
|
||||
}
|
||||
}
|
||||
|
||||
ImageFormat FindFormat (string format)
|
||||
{
|
||||
var range = FormatCatalog.Instance.LookupTag<ImageFormat> (format);
|
||||
return range.FirstOrDefault();
|
||||
}
|
||||
|
||||
Tuple<ImageFormat, ImageMetaData> FindImageFormat (ArcView arc)
|
||||
{
|
||||
uint signature = arc.View.ReadUInt32 (0);
|
||||
using (var stream = arc.CreateStream())
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
var range = FormatCatalog.Instance.LookupSignature<ImageFormat> (signature);
|
||||
foreach (var impl in range)
|
||||
{
|
||||
try
|
||||
{
|
||||
ImageMetaData metadata = impl.ReadMetaData (stream);
|
||||
if (null != metadata)
|
||||
return new Tuple<ImageFormat, ImageMetaData> (impl, metadata);
|
||||
stream.Position = 0;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
if (0 == signature)
|
||||
break;
|
||||
signature = 0;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
ImageData ReadImage (ArcView file)
|
||||
{
|
||||
var format = FindImageFormat (file);
|
||||
if (null == format)
|
||||
return null;
|
||||
using (var stream = file.CreateStream())
|
||||
return format.Item1.Read (stream, format.Item2);
|
||||
}
|
||||
|
||||
void PrintMetaData (string filename)
|
||||
{
|
||||
using (ArcView file = new ArcView (filename))
|
||||
{
|
||||
var format = FindImageFormat (file);
|
||||
if (null == format)
|
||||
{
|
||||
Console.Error.WriteLine ("{0}: file format not recognized", filename);
|
||||
return;
|
||||
}
|
||||
var image = format.Item2;
|
||||
Console.WriteLine ("{0,16} [{4}] {1}x{2} {3}bpp", filename, image.Width, image.Height, image.BPP, format.Item1.Tag);
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertFile (string filename, ImageFormat format)
|
||||
{
|
||||
ImageData image;
|
||||
using (var file = new ArcView (filename))
|
||||
{
|
||||
image = ReadImage (file);
|
||||
if (null == image)
|
||||
{
|
||||
Console.Error.WriteLine ("{0}: Unknown image format", filename);
|
||||
return;
|
||||
}
|
||||
}
|
||||
string target_ext = format.Extensions.First();
|
||||
string outname = Path.GetFileNameWithoutExtension (filename)+'.'+target_ext;
|
||||
Console.WriteLine ("{0} => {1}", filename, outname);
|
||||
using (var outfile = new FileStream (outname, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
format.Write (outfile, image);
|
||||
}
|
||||
}
|
||||
|
||||
void Run (string[] args)
|
||||
{
|
||||
if (args.Length < 1 || args[0] == "/?" || args[0] == "--help")
|
||||
{
|
||||
Usage();
|
||||
}
|
||||
else if (args[0] == "-l")
|
||||
{
|
||||
ListFormats();
|
||||
}
|
||||
else if (args[0] == "-t")
|
||||
{
|
||||
if (args.Length < 3)
|
||||
{
|
||||
Usage();
|
||||
return;
|
||||
}
|
||||
ImageFormat format = FindFormat (args[1]);
|
||||
if (null == format)
|
||||
{
|
||||
Console.Error.WriteLine ("{0}: unknown format specified", args[1]);
|
||||
return;
|
||||
}
|
||||
for (int i = 2; i < args.Length; ++i)
|
||||
{
|
||||
try
|
||||
{
|
||||
ConvertFile (args[i], format);
|
||||
}
|
||||
catch (Exception X)
|
||||
{
|
||||
Console.Error.WriteLine ("{0}: {1}", args[i], X.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var filename in args)
|
||||
{
|
||||
PrintMetaData (filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
var program = new ImageConverter();
|
||||
program.Run (args);
|
||||
}
|
||||
catch (Exception X)
|
||||
{
|
||||
Console.Error.WriteLine ("{0}: {1}", ProgramName, X.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
36
Image.Convert/Properties/AssemblyInfo.cs
Normal file
36
Image.Convert/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Image.Convert")]
|
||||
[assembly: AssemblyDescription("Image Conversion utility")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Image.Convert")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014 mørkt")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("5becba95-6a61-452a-8075-9b523494cc09")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
205
ImagePreview.cs
Normal file
205
ImagePreview.cs
Normal file
@ -0,0 +1,205 @@
|
||||
//! \file ImagePreview.cs
|
||||
//! \date Sun Jul 06 06:34:56 2014
|
||||
//! \brief preview images.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Imaging;
|
||||
using GARbro.GUI.Strings;
|
||||
using GameRes;
|
||||
|
||||
namespace GARbro.GUI
|
||||
{
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private readonly BackgroundWorker m_preview_worker = new BackgroundWorker();
|
||||
private PreviewFile m_current_preview = new PreviewFile();
|
||||
private bool m_preview_pending = false;
|
||||
|
||||
class PreviewFile
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public string Name { get; set; }
|
||||
public Entry Entry { get; set; }
|
||||
public ArcFile Archive { get; set; }
|
||||
|
||||
public bool IsEqual (string path, string name)
|
||||
{
|
||||
return path.Equals (Path) && name.Equals (Name);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitPreviewPane ()
|
||||
{
|
||||
m_preview_worker.DoWork += (s, e) => LoadPreviewImage (e.Argument as PreviewFile);
|
||||
m_preview_worker.RunWorkerCompleted += (s, e) => {
|
||||
if (m_preview_pending)
|
||||
RefreshPreviewPane();
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display entry in preview panel
|
||||
/// </summary>
|
||||
private void PreviewEntry (Entry entry)
|
||||
{
|
||||
if (m_current_preview.IsEqual (ViewModel.Path, entry.Name))
|
||||
return;
|
||||
UpdatePreviewPane (entry);
|
||||
}
|
||||
|
||||
void RefreshPreviewPane ()
|
||||
{
|
||||
m_preview_pending = false;
|
||||
var current = CurrentDirectory.SelectedItem as EntryViewModel;
|
||||
if (null != current)
|
||||
UpdatePreviewPane (current.Source);
|
||||
else
|
||||
PreviewPane.Source = null;
|
||||
}
|
||||
|
||||
void UpdatePreviewPane (Entry entry)
|
||||
{
|
||||
SetStatusText ("");
|
||||
var vm = ViewModel;
|
||||
m_current_preview = new PreviewFile { Path = vm.Path, Name = entry.Name };
|
||||
PreviewPane.Source = null;
|
||||
if (entry.Type != "image")
|
||||
return;
|
||||
if (vm.IsArchive)
|
||||
{
|
||||
m_current_preview.Archive = m_app.CurrentArchive;
|
||||
m_current_preview.Entry = entry;
|
||||
}
|
||||
if (!m_preview_worker.IsBusy)
|
||||
m_preview_worker.RunWorkerAsync (m_current_preview);
|
||||
else
|
||||
m_preview_pending = true;
|
||||
}
|
||||
|
||||
void LoadPreviewImage (PreviewFile preview)
|
||||
{
|
||||
try
|
||||
{
|
||||
Stream file;
|
||||
if (null == preview.Archive)
|
||||
{
|
||||
string filename = Path.Combine (preview.Path, preview.Name);
|
||||
file = new FileStream (filename, FileMode.Open, FileAccess.Read);
|
||||
}
|
||||
else
|
||||
{
|
||||
file = preview.Archive.OpenEntry (preview.Entry);
|
||||
}
|
||||
using (file)
|
||||
{
|
||||
var data = ReadImage (file);
|
||||
if (null != data)
|
||||
SetPreviewImage (preview, data.Bitmap);
|
||||
else
|
||||
Trace.WriteLine ("Cannot parse image format", preview.Name);
|
||||
}
|
||||
}
|
||||
catch (Exception X)
|
||||
{
|
||||
SetStatusText (X.Message);
|
||||
}
|
||||
}
|
||||
|
||||
void SetPreviewImage (PreviewFile preview, BitmapSource bitmap)
|
||||
{
|
||||
if (bitmap.DpiX != Desktop.DpiX || bitmap.DpiY != Desktop.DpiY)
|
||||
{
|
||||
int stride = bitmap.PixelWidth * ((bitmap.Format.BitsPerPixel + 7) / 8);
|
||||
var pixels = new byte[stride*bitmap.PixelHeight];
|
||||
bitmap.CopyPixels (pixels, stride, 0);
|
||||
var fixed_bitmap = BitmapSource.Create (bitmap.PixelWidth, bitmap.PixelHeight,
|
||||
Desktop.DpiX, Desktop.DpiY, bitmap.Format, bitmap.Palette, pixels, stride);
|
||||
bitmap = fixed_bitmap;
|
||||
}
|
||||
if (!bitmap.IsFrozen)
|
||||
bitmap.Freeze();
|
||||
Dispatcher.Invoke (() =>
|
||||
{
|
||||
if (m_current_preview == preview) // compare by reference
|
||||
{
|
||||
PreviewPane.Source = bitmap;
|
||||
SetStatusText (string.Format ("Image {0} x {1} x {2}bpp", bitmap.PixelWidth,
|
||||
bitmap.PixelHeight, bitmap.Format.BitsPerPixel));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ImageData ReadImage (Stream file)
|
||||
{
|
||||
bool need_dispose = false;
|
||||
try
|
||||
{
|
||||
if (!file.CanSeek)
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
file.CopyTo (stream);
|
||||
file = stream;
|
||||
need_dispose = true;
|
||||
}
|
||||
var format = FindImageFormat (file);
|
||||
if (null == format)
|
||||
return null;
|
||||
file.Position = 0;
|
||||
return format.Item1.Read (file, format.Item2);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (need_dispose)
|
||||
file.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
Tuple<ImageFormat, ImageMetaData> FindImageFormat (Stream file)
|
||||
{
|
||||
uint signature = FormatCatalog.ReadSignature (file);
|
||||
for (;;)
|
||||
{
|
||||
var range = FormatCatalog.Instance.LookupSignature<ImageFormat> (signature);
|
||||
foreach (var impl in range)
|
||||
{
|
||||
try
|
||||
{
|
||||
file.Position = 0;
|
||||
ImageMetaData metadata = impl.ReadMetaData (file);
|
||||
if (null != metadata)
|
||||
return new Tuple<ImageFormat, ImageMetaData> (impl, metadata);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
if (0 == signature)
|
||||
break;
|
||||
signature = 0;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void ExtractImage (ArcFile arc, Entry entry, ImageFormat target_format)
|
||||
{
|
||||
using (var file = arc.OpenEntry (entry))
|
||||
{
|
||||
ImageData image = ReadImage (file);
|
||||
if (null == image)
|
||||
throw new InvalidFormatException (string.Format ("{1}: {0}", guiStrings.MsgUnableInterpret, entry.Name));
|
||||
string target_ext = target_format.Extensions.First();
|
||||
string outname = Path.GetFileNameWithoutExtension (entry.Name)+'.'+target_ext;
|
||||
Trace.WriteLine (string.Format ("{0} => {1}", entry.Name, outname), "ExtractFileFromArchive");
|
||||
using (var outfile = File.Create (outname))
|
||||
{
|
||||
target_format.Write (outfile, image);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
BIN
Images/32x32/back button.png
Normal file
BIN
Images/32x32/back button.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
BIN
Images/32x32/forward button.png
Normal file
BIN
Images/32x32/forward button.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
BIN
Images/32x32/help.png
Normal file
BIN
Images/32x32/help.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
BIN
Images/64x64/info.png
Normal file
BIN
Images/64x64/info.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.0 KiB |
BIN
Images/search4files.ico
Normal file
BIN
Images/search4files.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
258
MainWindow.xaml
Normal file
258
MainWindow.xaml
Normal file
@ -0,0 +1,258 @@
|
||||
<Window x:Class="GARbro.GUI.MainWindow" x:Name="AppWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:GARbro.GUI"
|
||||
xmlns:s="clr-namespace:GARbro.GUI.Strings"
|
||||
xmlns:p="clr-namespace:GARbro.GUI.Properties"
|
||||
xmlns:sdk="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit"
|
||||
Title="GARbro" MinHeight="250" ResizeMode="CanResizeWithGrip"
|
||||
Loaded="WindowLoaded"
|
||||
Top="{Binding Source={x:Static p:Settings.Default}, Path=winTop, Mode=TwoWay}"
|
||||
Left="{Binding Source={x:Static p:Settings.Default}, Path=winLeft, Mode=TwoWay}"
|
||||
Height="{Binding Source={x:Static p:Settings.Default}, Path=winHeight, Mode=TwoWay}"
|
||||
Width="{Binding Source={x:Static p:Settings.Default}, Path=winWidth, Mode=TwoWay}"
|
||||
WindowState="{Binding Source={x:Static p:Settings.Default}, Path=winState, Mode=TwoWay}">
|
||||
<Window.Resources>
|
||||
<SolidColorBrush x:Key="AlternateColor1" Color="#f2f5f9" />
|
||||
<SolidColorBrush x:Key="AlternateColor2" Color="White" />
|
||||
<BitmapImage x:Key="Icon32x32Back" UriSource="Images/32x32/back button.png"/>
|
||||
<BitmapImage x:Key="Icon32x32Forward" UriSource="Images/32x32/forward button.png"/>
|
||||
<BitmapImage x:Key="Icon32x32Help" UriSource="Images/32x32/help.png"/>
|
||||
<CollectionViewSource x:Key="ListViewSource" Source="{Binding}"/>
|
||||
<Style x:Key="HeaderLeftAlign" TargetType="{x:Type GridViewColumnHeader}">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Left"></Setter>
|
||||
</Style>
|
||||
<DataTemplate x:Key="SortArrowUp">
|
||||
<DockPanel>
|
||||
<TextBlock Margin="5,0,5,0" Text="{Binding}" />
|
||||
<Path VerticalAlignment="Center" Fill="Gray" Data="M 5,5 15,5 10,0 5,5" />
|
||||
</DockPanel>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="SortArrowDown">
|
||||
<DockPanel>
|
||||
<TextBlock Margin="5,0,5,0" Text="{Binding}" />
|
||||
<Path VerticalAlignment="Center" Fill="Gray" Data="M 5,0 10,5 15,0 5,0" />
|
||||
</DockPanel>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="SortArrowNone">
|
||||
<TextBlock Margin="5,0,5,0" Text="{Binding}"/>
|
||||
</DataTemplate>
|
||||
</Window.Resources>
|
||||
<DockPanel LastChildFill="True">
|
||||
<Menu x:Name="MainMenuBar" DockPanel.Dock="Top" IsMainMenu="True" Visibility="Collapsed"/>
|
||||
<DockPanel Background="{Binding Path=Background, ElementName=MainMenuBar}" x:Name="MainToolBar"
|
||||
HorizontalAlignment="Stretch" DockPanel.Dock="Top">
|
||||
<DockPanel.Resources>
|
||||
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
|
||||
<Setter Property="ToolTipService.ShowOnDisabled" Value="True"/>
|
||||
<Setter Property="Focusable" Value="False"/>
|
||||
<Setter Property="Margin" Value="1,2,1,2"/>
|
||||
</Style>
|
||||
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource {x:Static ToolBar.ToggleButtonStyleKey}}">
|
||||
<Setter Property="ToolTipService.ShowOnDisabled" Value="True"/>
|
||||
<Setter Property="Focusable" Value="False"/>
|
||||
<Setter Property="Margin" Value="2,2,2,2"/>
|
||||
</Style>
|
||||
<Style TargetType="{x:Type Separator}" BasedOn="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}">
|
||||
<Setter Property="Margin" Value="5,0,5,0"/>
|
||||
</Style>
|
||||
<Style TargetType="{x:Type Image}">
|
||||
<Setter Property="UseLayoutRounding" Value="True"/>
|
||||
<Setter Property="SnapsToDevicePixels" Value="True"/>
|
||||
<!--
|
||||
<Setter Property="Width" Value="{Binding RelativeSource={RelativeSource Self}, Path=Source.Width}"/>
|
||||
<Setter Property="Height" Value="{Binding RelativeSource={RelativeSource Self}, Path=Source.Height}"/>
|
||||
<Setter Property="Stretch" Value="None"/>
|
||||
-->
|
||||
<Setter Property="Width" Value="24"/>
|
||||
<Setter Property="Height" Value="24"/>
|
||||
<Setter Property="Stretch" Value="Uniform"/>
|
||||
<!-- hack to make images within disabled toolbar buttons appear 'grayed out'.
|
||||
This doesn't gray them at all, but lowers their opacity so the (usually gray)
|
||||
background of the button shows through. If WPF had a built-in facility for
|
||||
grayscaling images in disabled buttons, this kind of icky kludgery wouldn't be
|
||||
necessary -->
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type Button}, AncestorLevel=1}, Path=IsEnabled}" Value="False">
|
||||
<Setter Property="Opacity" Value="0.33"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</DockPanel.Resources>
|
||||
<Button x:Name="ButtonBack" ToolTip="{x:Static s:guiStrings.TooltipBack}" Margin="5,2,0,2"
|
||||
Command="{x:Static local:Commands.GoBack}">
|
||||
<Image Source="{StaticResource Icon32x32Back}"/>
|
||||
</Button>
|
||||
<Button x:Name="ButtonForward" ToolTip="{x:Static s:guiStrings.TooltipForward}"
|
||||
Command="{x:Static local:Commands.GoForward}">
|
||||
<Image Source="{StaticResource Icon32x32Forward}"/>
|
||||
</Button>
|
||||
<Separator/>
|
||||
<local:ExtAutoCompleteBox x:Name="pathLine" Height="22" Width="100" KeyDown="acb_OnKeyDown"/>
|
||||
<Button ToolTip="{x:Static s:guiStrings.MenuAbout}" DockPanel.Dock="Right" Margin="0,2,10,2" Click="MenuAbout_Click">
|
||||
<Image Source="{StaticResource Icon32x32Help}"/>
|
||||
</Button>
|
||||
<TextBlock Visibility="Hidden"/>
|
||||
</DockPanel>
|
||||
<StatusBar DockPanel.Dock="Bottom">
|
||||
<StatusBarItem>
|
||||
<TextBlock x:Name="appStatusText"/>
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
<Grid x:Name="ContentGrid" DockPanel.Dock="Left" VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch" ShowGridLines="False">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{Binding Source={x:Static p:Settings.Default}, Path=lvPanelWidth, Mode=TwoWay}" MinWidth="200" />
|
||||
<ColumnDefinition Width="1"/>
|
||||
<ColumnDefinition Width="*" MinWidth="100"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<ListView Name="CurrentDirectory" Grid.Column="0"
|
||||
ItemsSource="{Binding Source={StaticResource ListViewSource}}"
|
||||
VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
|
||||
BorderBrush="Transparent" SelectedValuePath="Name"
|
||||
SelectionMode="Extended" Foreground="Black" AlternationCount="2"
|
||||
PreviewTextInput="lv_TextInput" IsSynchronizedWithCurrentItem="True"
|
||||
GridViewColumnHeader.Click="lv_ColumnHeaderClicked">
|
||||
<ListView.Resources>
|
||||
<SolidColorBrush x:Key="ItemInactiveBackground" Color="#ffcbcbcb" />
|
||||
<Style x:Key="DefaultMenuItemStyle" TargetType="{x:Type MenuItem}">
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</Style>
|
||||
<ContextMenu x:Key="lvDirContextMenu">
|
||||
<MenuItem Header="{x:Static s:guiStrings.CtxMenuOpen}" InputGestureText="Enter"
|
||||
Style="{StaticResource DefaultMenuItemStyle}"
|
||||
Command="{x:Static local:Commands.OpenItem}" />
|
||||
<MenuItem Header="{x:Static s:guiStrings.CtxMenuExtract}" InputGestureText="F4"
|
||||
Command="{x:Static local:Commands.ExtractItem}" />
|
||||
<MenuItem Header="{x:Static s:guiStrings.CtxMenuExplorer}" InputGestureText="Ctrl+E"
|
||||
Command="{x:Static local:Commands.ExploreItem}"/>
|
||||
<Separator/>
|
||||
<MenuItem Header="{x:Static s:guiStrings.CtxMenuDelete}" InputGestureText="Del"
|
||||
Command="{x:Static local:Commands.DeleteItem}"/>
|
||||
<Separator/>
|
||||
<!--
|
||||
<MenuItem Header="{x:Static s:guiStrings.CtxMenuRename}" InputGestureText="F2"
|
||||
Command="{x:Static local:Commands.RenameItem}"/>
|
||||
-->
|
||||
<MenuItem Header="{x:Static s:guiStrings.CtxMenuRefresh}" InputGestureText="F5"
|
||||
Command="{x:Static local:Commands.Refresh}"/>
|
||||
<!-- Sort-by submenu
|
||||
<MenuItem Header="{x:Static s:guiStrings.CtxMenuSortBy}">
|
||||
<MenuItem Header="{x:Static s:guiStrings.CtxMenuSortByName}" IsCheckable="True"
|
||||
IsChecked="{Binding ElementName=AppWindow, Path=IsSortByName, Mode=OneWay}"
|
||||
Command="{x:Static local:Commands.SortBy}" CommandParameter="Name"/>
|
||||
<MenuItem Header="{x:Static s:guiStrings.CtxMenuSortByType}" IsCheckable="True"
|
||||
IsChecked="{Binding ElementName=AppWindow, Path=IsSortByType, Mode=OneWay}"
|
||||
Command="{x:Static local:Commands.SortBy}" CommandParameter="Type"/>
|
||||
<MenuItem Header="{x:Static s:guiStrings.CtxMenuSortBySize}" IsCheckable="True"
|
||||
IsChecked="{Binding ElementName=AppWindow, Path=IsSortBySize, Mode=OneWay}"
|
||||
Command="{x:Static local:Commands.SortBy}" CommandParameter="Size"/>
|
||||
<MenuItem Header="{x:Static s:guiStrings.CtxMenuUnsorted}" IsCheckable="True"
|
||||
IsChecked="{Binding ElementName=AppWindow, Path=IsUnsorted, Mode=OneWay}"
|
||||
Command="{x:Static local:Commands.SortBy}"/>
|
||||
</MenuItem>
|
||||
-->
|
||||
</ContextMenu>
|
||||
</ListView.Resources>
|
||||
<ListView.InputBindings>
|
||||
<KeyBinding Key="Enter" Command="{x:Static local:Commands.OpenItem}"/>
|
||||
<KeyBinding Gesture="Ctrl+E" Command="{x:Static local:Commands.ExploreItem}"/>
|
||||
<KeyBinding Gesture="F2" Command="{x:Static local:Commands.RenameItem}"/>
|
||||
<KeyBinding Gesture="F4" Command="{x:Static local:Commands.ExtractItem}"/>
|
||||
<KeyBinding Gesture="F5" Command="{x:Static local:Commands.Refresh}"/>
|
||||
<KeyBinding Gesture="Delete" Command="{x:Static local:Commands.DeleteItem}"/>
|
||||
<KeyBinding Gesture="Backspace" Command="{x:Static local:Commands.GoBack}"/>
|
||||
<MouseBinding Gesture="LeftDoubleClick" Command="{x:Static local:Commands.OpenItem}" />
|
||||
</ListView.InputBindings>
|
||||
<ListView.ItemContainerStyle>
|
||||
<Style TargetType="ListViewItem">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="ContextMenu" Value="{StaticResource lvDirContextMenu}"/>
|
||||
<EventSetter Event="Selected" Handler="lvi_Selected"/>
|
||||
<EventSetter Event="ListViewItem.MouseDoubleClick" Handler="lvi_DoubleClick" />
|
||||
<Style.Triggers>
|
||||
<!-- BEGIN alternate row color -->
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsSelected" Value="False" />
|
||||
<Condition Property="IsMouseOver" Value="False" />
|
||||
<Condition Property="ItemsControl.AlternationIndex" Value="0"/>
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter Property="Background" Value="{StaticResource AlternateColor1}"/>
|
||||
</MultiTrigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsSelected" Value="False" />
|
||||
<Condition Property="IsMouseOver" Value="False" />
|
||||
<Condition Property="ItemsControl.AlternationIndex" Value="1"/>
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter Property="Background" Value="{StaticResource AlternateColor2}"/>
|
||||
</MultiTrigger>
|
||||
<!-- END alternate row color -->
|
||||
<!-- BEGIN context menu trigger -->
|
||||
<!--
|
||||
<DataTrigger Binding="{Binding Path=IsArchive}" Value="True">
|
||||
<Setter Property="ContextMenu" Value="{StaticResource lvArcContextMenu}"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Path=IsArchive}" Value="False">
|
||||
<Setter Property="ContextMenu" Value="{StaticResource lvDirContextMenu}"/>
|
||||
</DataTrigger>
|
||||
-->
|
||||
<!-- END context menu trigger -->
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ListView.ItemContainerStyle>
|
||||
<ListView.View>
|
||||
<GridView AllowsColumnReorder="False">
|
||||
<GridViewColumn HeaderContainerStyle="{StaticResource HeaderLeftAlign}" Width="{Binding Source={x:Static p:Settings.Default}, Path=lvNameColumnWidth, Mode=TwoWay}" HeaderTemplate="{StaticResource SortArrowNone}">
|
||||
<GridViewColumn.Header>
|
||||
<GridViewColumnHeader Tag="Name" Content="{x:Static s:guiStrings.HeaderName}"/>
|
||||
</GridViewColumn.Header>
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate><TextBlock x:Name="item_Name" Text="{Binding Path=Name}"/></DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn HeaderContainerStyle="{StaticResource HeaderLeftAlign}" Width="{Binding Source={x:Static p:Settings.Default}, Path=lvTypeColumnWidth, Mode=TwoWay}" HeaderTemplate="{StaticResource SortArrowNone}" DisplayMemberBinding="{Binding Path=Type}">
|
||||
<GridViewColumn.Header>
|
||||
<GridViewColumnHeader Tag="Type" Content="{x:Static s:guiStrings.HeaderType}"/>
|
||||
</GridViewColumn.Header>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn HeaderContainerStyle="{StaticResource HeaderLeftAlign}" Width="{Binding Source={x:Static p:Settings.Default}, Path=lvSizeColumnWidth, Mode=TwoWay}" HeaderTemplate="{StaticResource SortArrowNone}">
|
||||
<GridViewColumn.Header>
|
||||
<GridViewColumnHeader Tag="Size" Content="{x:Static s:guiStrings.HeaderSize}"/>
|
||||
</GridViewColumn.Header>
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate><TextBlock Text="{Binding Path=Size}" TextAlignment="Right"/></DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
<ScrollViewer Grid.Column="2" Background="LightGray"
|
||||
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
|
||||
<Image Name="PreviewPane" Stretch="None" UseLayoutRounding="False" SnapsToDevicePixels="True"
|
||||
local:TouchScrolling.IsEnabled="True"/>
|
||||
</ScrollViewer>
|
||||
<!-- Margin and BorderThickness help to react early on mouse pointer -->
|
||||
<GridSplitter Grid.Column="1" Background="Black" ShowsPreview="False" Focusable="False"
|
||||
Margin="-3,0" BorderThickness="3,0" BorderBrush="Transparent"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Stretch" />
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
<Window.InputBindings>
|
||||
<KeyBinding Gesture="Ctrl+Q" Command="{x:Static local:Commands.Exit}"/>
|
||||
<KeyBinding Gesture="Backspace" Command="{x:Static local:Commands.GoBack}"/>
|
||||
</Window.InputBindings>
|
||||
<Window.CommandBindings>
|
||||
<CommandBinding Command="{x:Static local:Commands.OpenItem}" Executed="OpenItemExec" CanExecute="CanExecuteOnSelected"/>
|
||||
<CommandBinding Command="{x:Static local:Commands.ExtractItem}" Executed="ExtractItemExec" CanExecute="CanExecuteOnSelected"/>
|
||||
<CommandBinding Command="{x:Static local:Commands.DeleteItem}" Executed="DeleteItemExec" CanExecute="CanExecuteDelete" />
|
||||
<CommandBinding Command="{x:Static local:Commands.RenameItem}" Executed="RenameItemExec" CanExecute="CanExecuteInDirectory" />
|
||||
<CommandBinding Command="{x:Static local:Commands.ExploreItem}" Executed="ExploreItemExec" CanExecute="CanExecuteInDirectory" />
|
||||
<CommandBinding Command="{x:Static local:Commands.SortBy}" Executed="SortByExec" CanExecute="CanExecuteAlways"/>
|
||||
<CommandBinding Command="{x:Static local:Commands.GoBack}" Executed="GoBackExec" CanExecute="CanExecuteGoBack"/>
|
||||
<CommandBinding Command="{x:Static local:Commands.GoForward}" Executed="GoForwardExec" CanExecute="CanExecuteGoForward"/>
|
||||
<CommandBinding Command="{x:Static local:Commands.Refresh}" Executed="RefreshExec" CanExecute="CanExecuteAlways"/>
|
||||
<CommandBinding Command="{x:Static local:Commands.Exit}" Executed="ExitExec" CanExecute="CanExecuteAlways"/>
|
||||
</Window.CommandBindings>
|
||||
</Window>
|
1094
MainWindow.xaml.cs
Normal file
1094
MainWindow.xaml.cs
Normal file
File diff suppressed because it is too large
Load Diff
20
Makefile
Normal file
20
Makefile
Normal file
@ -0,0 +1,20 @@
|
||||
MSCS = D:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/csc //nologo
|
||||
|
||||
.SUFFIXES: .cs .exe
|
||||
|
||||
all: GARbro
|
||||
|
||||
adler32: adler32.cs
|
||||
$(MSCS) $(MSCSFLAGS) //out:$@.exe $^
|
||||
|
||||
inflate: inflate.cs
|
||||
$(MSCS) $(MSCSFLAGS) //out:$@.exe $^ //r:zlib\\zlibnet.dll
|
||||
|
||||
deflate: deflate.cs
|
||||
$(MSCS) $(MSCSFLAGS) //out:$@.exe $^ //r:zlib\\zlibnet.dll
|
||||
|
||||
GARbro: Program.cs GameRes.cs ArcXFL.cs
|
||||
$(MSCS) $(MSCSFLAGS) //out:$@.exe $^ //r:System.ComponentModel.Composition.dll //r:System.ComponentModel.DataAnnotations.dll
|
||||
|
||||
tags:
|
||||
ctags *.cs
|
88
ModalWindow.cs
Normal file
88
ModalWindow.cs
Normal file
@ -0,0 +1,88 @@
|
||||
//! \file ModalWindow.cs
|
||||
//! \date Tue Aug 02 10:20:50 2011
|
||||
//! \brief Window without an icon.
|
||||
//
|
||||
// Copyright (C) 2011 by poddav
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Rnd.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// Window without an icon.
|
||||
/// </summary>
|
||||
public class ModalWindow : Window
|
||||
{
|
||||
protected override void OnSourceInitialized(EventArgs e)
|
||||
{
|
||||
base.OnSourceInitialized(e);
|
||||
|
||||
HideIcon (this);
|
||||
}
|
||||
|
||||
internal class NativeMethods
|
||||
{
|
||||
[DllImport ("user32.dll")]
|
||||
internal static extern int GetWindowLong (IntPtr hwnd, int index);
|
||||
|
||||
[DllImport ("user32.dll")]
|
||||
internal static extern int SetWindowLong (IntPtr hwnd, int index, int newStyle);
|
||||
|
||||
[DllImport ("user32.dll")]
|
||||
internal static extern bool SetWindowPos (IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);
|
||||
|
||||
[DllImport ("user32.dll")]
|
||||
internal static extern IntPtr SendMessage (IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam);
|
||||
}
|
||||
|
||||
const int GWL_EXSTYLE = -20;
|
||||
const int WS_EX_DLGMODALFRAME = 0x0001;
|
||||
|
||||
const int SWP_NOSIZE = 0x0001;
|
||||
const int SWP_NOMOVE = 0x0002;
|
||||
const int SWP_NOZORDER = 0x0004;
|
||||
const int SWP_FRAMECHANGED = 0x0020;
|
||||
const uint WM_SETICON = 0x0080;
|
||||
|
||||
/// <summary>
|
||||
/// Win32 mumbo-jumbo to hide window icon and its menu.
|
||||
/// </summary>
|
||||
|
||||
public static void HideIcon (Window window)
|
||||
{
|
||||
// Get this window's handle
|
||||
IntPtr hwnd = new WindowInteropHelper (window).Handle;
|
||||
|
||||
// Change the extended window style to not show a window icon
|
||||
int extendedStyle = NativeMethods.GetWindowLong (hwnd, GWL_EXSTYLE);
|
||||
NativeMethods.SetWindowLong (hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);
|
||||
NativeMethods.SendMessage (hwnd, WM_SETICON, IntPtr.Zero, IntPtr.Zero);
|
||||
NativeMethods.SendMessage (hwnd, WM_SETICON, new IntPtr (1), IntPtr.Zero);
|
||||
|
||||
// Update the window's non-client area to reflect the changes
|
||||
NativeMethods.SetWindowPos (hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
}
|
||||
}
|
||||
}
|
55
Properties/AssemblyInfo.cs
Normal file
55
Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Game Resource browser")]
|
||||
[assembly: AssemblyDescription("Game Resource browser")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("GARbro.GUI")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014 mørkt")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//In order to begin building localizable applications, set
|
||||
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||
//inside a <PropertyGroup>. For example, if you are using US english
|
||||
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||
//the line below to match the UICulture setting in the project file.
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
63
Properties/Resources.Designer.cs
generated
Normal file
63
Properties/Resources.Designer.cs
generated
Normal file
@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.18444
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace GARbro.GUI.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GARbro.GUI.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
Properties/Resources.resx
Normal file
117
Properties/Resources.resx
Normal file
@ -0,0 +1,117 @@
|
||||
<?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.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: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" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</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" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</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=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
230
Properties/Settings.Designer.cs
generated
Normal file
230
Properties/Settings.Designer.cs
generated
Normal file
@ -0,0 +1,230 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.18444
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace GARbro.GUI.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||
public bool UpgradeRequired {
|
||||
get {
|
||||
return ((bool)(this["UpgradeRequired"]));
|
||||
}
|
||||
set {
|
||||
this["UpgradeRequired"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("NaN")]
|
||||
public double winTop {
|
||||
get {
|
||||
return ((double)(this["winTop"]));
|
||||
}
|
||||
set {
|
||||
this["winTop"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("NaN")]
|
||||
public double winLeft {
|
||||
get {
|
||||
return ((double)(this["winLeft"]));
|
||||
}
|
||||
set {
|
||||
this["winLeft"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("1024")]
|
||||
public double winWidth {
|
||||
get {
|
||||
return ((double)(this["winWidth"]));
|
||||
}
|
||||
set {
|
||||
this["winWidth"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("560")]
|
||||
public double winHeight {
|
||||
get {
|
||||
return ((double)(this["winHeight"]));
|
||||
}
|
||||
set {
|
||||
this["winHeight"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("Normal")]
|
||||
public global::System.Windows.WindowState winState {
|
||||
get {
|
||||
return ((global::System.Windows.WindowState)(this["winState"]));
|
||||
}
|
||||
set {
|
||||
this["winState"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("265")]
|
||||
public double lvNameColumnWidth {
|
||||
get {
|
||||
return ((double)(this["lvNameColumnWidth"]));
|
||||
}
|
||||
set {
|
||||
this["lvNameColumnWidth"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("75")]
|
||||
public double lvTypeColumnWidth {
|
||||
get {
|
||||
return ((double)(this["lvTypeColumnWidth"]));
|
||||
}
|
||||
set {
|
||||
this["lvTypeColumnWidth"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("75")]
|
||||
public double lvSizeColumnWidth {
|
||||
get {
|
||||
return ((double)(this["lvSizeColumnWidth"]));
|
||||
}
|
||||
set {
|
||||
this["lvSizeColumnWidth"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("Name")]
|
||||
public string lvSortColumn {
|
||||
get {
|
||||
return ((string)(this["lvSortColumn"]));
|
||||
}
|
||||
set {
|
||||
this["lvSortColumn"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("Ascending")]
|
||||
public global::System.ComponentModel.ListSortDirection lvSortDirection {
|
||||
get {
|
||||
return ((global::System.ComponentModel.ListSortDirection)(this["lvSortDirection"]));
|
||||
}
|
||||
set {
|
||||
this["lvSortDirection"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("448")]
|
||||
public global::System.Windows.GridLength lvPanelWidth {
|
||||
get {
|
||||
return ((global::System.Windows.GridLength)(this["lvPanelWidth"]));
|
||||
}
|
||||
set {
|
||||
this["lvPanelWidth"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||
public bool appExtractImages {
|
||||
get {
|
||||
return ((bool)(this["appExtractImages"]));
|
||||
}
|
||||
set {
|
||||
this["appExtractImages"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||
public bool appExtractText {
|
||||
get {
|
||||
return ((bool)(this["appExtractText"]));
|
||||
}
|
||||
set {
|
||||
this["appExtractText"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string appImageFormat {
|
||||
get {
|
||||
return ((string)(this["appImageFormat"]));
|
||||
}
|
||||
set {
|
||||
this["appImageFormat"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("UTF-8")]
|
||||
public string appTextEncoding {
|
||||
get {
|
||||
return ((string)(this["appTextEncoding"]));
|
||||
}
|
||||
set {
|
||||
this["appTextEncoding"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string appLastDirectory {
|
||||
get {
|
||||
return ((string)(this["appLastDirectory"]));
|
||||
}
|
||||
set {
|
||||
this["appLastDirectory"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
57
Properties/Settings.settings
Normal file
57
Properties/Settings.settings
Normal file
@ -0,0 +1,57 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="GARbro.GUI.Properties" GeneratedClassName="Settings">
|
||||
<Profiles />
|
||||
<Settings>
|
||||
<Setting Name="UpgradeRequired" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
<Setting Name="winTop" Type="System.Double" Scope="User">
|
||||
<Value Profile="(Default)">NaN</Value>
|
||||
</Setting>
|
||||
<Setting Name="winLeft" Type="System.Double" Scope="User">
|
||||
<Value Profile="(Default)">NaN</Value>
|
||||
</Setting>
|
||||
<Setting Name="winWidth" Type="System.Double" Scope="User">
|
||||
<Value Profile="(Default)">1024</Value>
|
||||
</Setting>
|
||||
<Setting Name="winHeight" Type="System.Double" Scope="User">
|
||||
<Value Profile="(Default)">560</Value>
|
||||
</Setting>
|
||||
<Setting Name="winState" Type="System.Windows.WindowState" Scope="User">
|
||||
<Value Profile="(Default)">Normal</Value>
|
||||
</Setting>
|
||||
<Setting Name="lvNameColumnWidth" Type="System.Double" Scope="User">
|
||||
<Value Profile="(Default)">265</Value>
|
||||
</Setting>
|
||||
<Setting Name="lvTypeColumnWidth" Type="System.Double" Scope="User">
|
||||
<Value Profile="(Default)">75</Value>
|
||||
</Setting>
|
||||
<Setting Name="lvSizeColumnWidth" Type="System.Double" Scope="User">
|
||||
<Value Profile="(Default)">75</Value>
|
||||
</Setting>
|
||||
<Setting Name="lvSortColumn" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)">Name</Value>
|
||||
</Setting>
|
||||
<Setting Name="lvSortDirection" Type="System.ComponentModel.ListSortDirection" Scope="User">
|
||||
<Value Profile="(Default)">Ascending</Value>
|
||||
</Setting>
|
||||
<Setting Name="lvPanelWidth" Type="System.Windows.GridLength" Scope="User">
|
||||
<Value Profile="(Default)">448</Value>
|
||||
</Setting>
|
||||
<Setting Name="appExtractImages" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
<Setting Name="appExtractText" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
<Setting Name="appImageFormat" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
<Setting Name="appTextEncoding" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)">UTF-8</Value>
|
||||
</Setting>
|
||||
<Setting Name="appLastDirectory" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
54
Properties/app.manifest
Normal file
54
Properties/app.manifest
Normal file
@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<!-- UAC Manifest Options
|
||||
If you want to change the Windows User Account Control level replace the
|
||||
requestedExecutionLevel node with one of the following.
|
||||
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
|
||||
|
||||
Specifying requestedExecutionLevel node will disable file and registry virtualization.
|
||||
If you want to utilize File and Registry Virtualization for backward
|
||||
compatibility then delete the requestedExecutionLevel node.
|
||||
-->
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
<applicationRequestMinimum>
|
||||
<defaultAssemblyRequest permissionSetReference="Custom" />
|
||||
<PermissionSet class="System.Security.PermissionSet" version="1" ID="Custom" SameSite="site" Unrestricted="true" />
|
||||
</applicationRequestMinimum>
|
||||
</security>
|
||||
</trustInfo>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- A list of all Windows versions that this application is designed to work with.
|
||||
Windows will automatically select the most compatible environment.-->
|
||||
<!-- If your application is designed to work with Windows Vista, uncomment the following supportedOS node-->
|
||||
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>-->
|
||||
<!-- If your application is designed to work with Windows 7, uncomment the following supportedOS node-->
|
||||
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>-->
|
||||
<!-- If your application is designed to work with Windows 8, uncomment the following supportedOS node-->
|
||||
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>-->
|
||||
<!-- If your application is designed to work with Windows 8.1, uncomment the following supportedOS node-->
|
||||
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>-->
|
||||
</application>
|
||||
</compatibility>
|
||||
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
|
||||
<!-- <dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>-->
|
||||
</asmv1:assembly>
|
43
Settings.cs
Normal file
43
Settings.cs
Normal file
@ -0,0 +1,43 @@
|
||||
namespace GARbro.GUI.Properties {
|
||||
|
||||
|
||||
// This class allows you to handle specific events on the settings class:
|
||||
// The SettingChanging event is raised before a setting's value is changed.
|
||||
// The PropertyChanged event is raised after a setting's value is changed.
|
||||
// The SettingsLoaded event is raised after the setting values are loaded.
|
||||
// The SettingsSaving event is raised before the setting values are saved.
|
||||
internal sealed partial class Settings {
|
||||
|
||||
public Settings() {
|
||||
// // To add event handlers for saving and changing settings, uncomment the lines below:
|
||||
//
|
||||
// this.SettingChanging += this.SettingChangingEventHandler;
|
||||
//
|
||||
// this.SettingsSaving += this.SettingsSavingEventHandler;
|
||||
//
|
||||
this.SettingsLoaded += OnSettingsLoadedHandler;
|
||||
}
|
||||
|
||||
void OnSettingsLoadedHandler (object sender, System.Configuration.SettingsLoadedEventArgs e)
|
||||
{
|
||||
if (Settings.Default.UpgradeRequired)
|
||||
{
|
||||
Settings.Default.Upgrade();
|
||||
Settings.Default.UpgradeRequired = false;
|
||||
Settings.Default.Save();
|
||||
|
||||
// do not restore in minimized state
|
||||
if (Settings.Default.winState == System.Windows.WindowState.Minimized)
|
||||
Settings.Default.winState = System.Windows.WindowState.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
|
||||
// Add code to handle the SettingChangingEvent event here.
|
||||
}
|
||||
|
||||
private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
|
||||
// Add code to handle the SettingsSaving event here.
|
||||
}
|
||||
}
|
||||
}
|
182
Shell.cs
Normal file
182
Shell.cs
Normal file
@ -0,0 +1,182 @@
|
||||
//! \file Shell.cs
|
||||
//! \date Tue Aug 02 13:48:55 2011
|
||||
//! \brief Win32 shell functions.
|
||||
//
|
||||
// Copyright (C) 2011 by poddav
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Rnd.Shell
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapper around PathCreateFromUrl WINAPI call.
|
||||
/// </summary>
|
||||
class PathConverter
|
||||
{
|
||||
[DllImport("shlwapi.dll", EntryPoint="PathCreateFromUrlW", CharSet=CharSet.Unicode, SetLastError=true)]
|
||||
private static extern Int32 PathCreateFromUrl(
|
||||
string url, StringBuilder path,
|
||||
ref Int32 size, UInt32 flags);
|
||||
|
||||
private StringBuilder buf;
|
||||
private Int32 size;
|
||||
|
||||
public PathConverter (int capacity = 260)
|
||||
{
|
||||
buf = new StringBuilder (capacity);
|
||||
}
|
||||
public string UrlToPath (string url)
|
||||
{
|
||||
size = buf.Capacity;
|
||||
Int32 rc = PathCreateFromUrl (url, buf, ref size, 0);
|
||||
return rc == 0 ? buf.ToString (0, size) : "";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper around SHGetFileInfo WINAPI call.
|
||||
/// </summary>
|
||||
class FileInfo
|
||||
{
|
||||
[DllImport("shell32.dll", CharSet=CharSet.Auto)]
|
||||
public static extern IntPtr SHGetFileInfo(
|
||||
string pszPath, Int32 dwFileAttributes,
|
||||
ref SHFILEINFO psfi, int cbFileInfo, int uFlags);
|
||||
|
||||
[DllImport("User32.dll")]
|
||||
public static extern int DestroyIcon(IntPtr hIcon);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
|
||||
public struct SHFILEINFO
|
||||
{
|
||||
public IntPtr hIcon;
|
||||
public int iIcon;
|
||||
public uint dwAttributes;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
|
||||
public string szDisplayName;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
|
||||
public string szTypeName;
|
||||
|
||||
public SHFILEINFO(bool b)
|
||||
{
|
||||
hIcon = IntPtr.Zero;
|
||||
iIcon = 0;
|
||||
dwAttributes = 0;
|
||||
szDisplayName = "";
|
||||
szTypeName = "";
|
||||
}
|
||||
};
|
||||
|
||||
[Flags]
|
||||
public enum SHGFI : uint
|
||||
{
|
||||
/// <summary>get icon</summary>
|
||||
Icon = 0x000000100,
|
||||
/// <summary>get display name</summary>
|
||||
DisplayName = 0x000000200,
|
||||
/// <summary>get type name</summary>
|
||||
TypeName = 0x000000400,
|
||||
/// <summary>get attributes</summary>
|
||||
Attributes = 0x000000800,
|
||||
/// <summary>get icon location</summary>
|
||||
IconLocation = 0x000001000,
|
||||
/// <summary>return exe type</summary>
|
||||
ExeType = 0x000002000,
|
||||
/// <summary>get system icon index</summary>
|
||||
SysIconIndex = 0x000004000,
|
||||
/// <summary>put a link overlay on icon</summary>
|
||||
LinkOverlay = 0x000008000,
|
||||
/// <summary>show icon in selected state</summary>
|
||||
Selected = 0x000010000,
|
||||
/// <summary>get only specified attributes</summary>
|
||||
Attr_Specified = 0x000020000,
|
||||
/// <summary>get large icon</summary>
|
||||
LargeIcon = 0x000000000,
|
||||
/// <summary>get small icon</summary>
|
||||
SmallIcon = 0x000000001,
|
||||
/// <summary>get open icon</summary>
|
||||
OpenIcon = 0x000000002,
|
||||
/// <summary>get shell size icon</summary>
|
||||
ShellIconSize = 0x000000004,
|
||||
/// <summary>pszPath is a pidl</summary>
|
||||
PIDL = 0x000000008,
|
||||
/// <summary>use passed dwFileAttribute</summary>
|
||||
UseFileAttributes= 0x000000010,
|
||||
/// <summary>apply the appropriate overlays</summary>
|
||||
AddOverlays = 0x000000020,
|
||||
/// <summary>Get the index of the overlay in the upper 8 bits of the iIcon</summary>
|
||||
OverlayIndex = 0x000000040,
|
||||
}
|
||||
|
||||
public static string GetTypeName (string filename)
|
||||
{
|
||||
SHFILEINFO info = new SHFILEINFO(true);
|
||||
int szInfo = Marshal.SizeOf (info);
|
||||
int result = (int)SHGetFileInfo (filename, 0, ref info, szInfo, (int)SHGFI.TypeName);
|
||||
|
||||
// If uFlags does not contain SHGFI_EXETYPE or SHGFI_SYSICONINDEX,
|
||||
// the return value is nonzero if successful, or zero otherwise.
|
||||
if (result != 0)
|
||||
return info.szTypeName;
|
||||
else
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public static SHFILEINFO? GetInfo (string filename, SHGFI flags)
|
||||
{
|
||||
SHFILEINFO info = new SHFILEINFO(true);
|
||||
int szInfo = Marshal.SizeOf (info);
|
||||
int result = (int)SHGetFileInfo (filename, 0, ref info, szInfo, (int)flags);
|
||||
|
||||
return result != 0? new Nullable<SHFILEINFO> (info): null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper around MoveFileEx WINAPI call.
|
||||
/// </summary>
|
||||
class File
|
||||
{
|
||||
[DllImport("kernel32.dll", EntryPoint="MoveFileExW", SetLastError=true, CharSet=CharSet.Unicode)]
|
||||
public static extern bool MoveFileEx (string lpExistingFileName, string lpNewFileName, MoveFileFlags dwFlags);
|
||||
|
||||
[Flags]
|
||||
public enum MoveFileFlags : uint
|
||||
{
|
||||
ReplaceExisting = 0x00000001,
|
||||
CopyAllowed = 0x00000002,
|
||||
DelayUntilReboot = 0x00000004,
|
||||
WriteThrough = 0x00000008,
|
||||
CreateHardlink = 0x00000010,
|
||||
FailIfNotTrackable = 0x00000020
|
||||
}
|
||||
|
||||
public static bool Rename (string szFrom, string szTo)
|
||||
{
|
||||
return MoveFileEx (szFrom, szTo, MoveFileFlags.ReplaceExisting);
|
||||
}
|
||||
}
|
||||
}
|
594
Strings/guiStrings.Designer.cs
generated
Normal file
594
Strings/guiStrings.Designer.cs
generated
Normal file
@ -0,0 +1,594 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.18444
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace GARbro.GUI.Strings {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class guiStrings {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal guiStrings() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GARbro.GUI.Strings.guiStrings", typeof(guiStrings).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cancel.
|
||||
/// </summary>
|
||||
public static string ButtonCancel {
|
||||
get {
|
||||
return ResourceManager.GetString("ButtonCancel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Extract.
|
||||
/// </summary>
|
||||
public static string ButtonExtract {
|
||||
get {
|
||||
return ResourceManager.GetString("ButtonExtract", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OK.
|
||||
/// </summary>
|
||||
public static string ButtonOK {
|
||||
get {
|
||||
return ResourceManager.GetString("ButtonOK", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to _Close.
|
||||
/// </summary>
|
||||
public static string CtxMenuClose {
|
||||
get {
|
||||
return ResourceManager.GetString("CtxMenuClose", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Copy.
|
||||
/// </summary>
|
||||
public static string CtxMenuCopy {
|
||||
get {
|
||||
return ResourceManager.GetString("CtxMenuCopy", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cut.
|
||||
/// </summary>
|
||||
public static string CtxMenuCut {
|
||||
get {
|
||||
return ResourceManager.GetString("CtxMenuCut", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to _Delete.
|
||||
/// </summary>
|
||||
public static string CtxMenuDelete {
|
||||
get {
|
||||
return ResourceManager.GetString("CtxMenuDelete", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Browse in _Explorer.
|
||||
/// </summary>
|
||||
public static string CtxMenuExplorer {
|
||||
get {
|
||||
return ResourceManager.GetString("CtxMenuExplorer", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Extract.
|
||||
/// </summary>
|
||||
public static string CtxMenuExtract {
|
||||
get {
|
||||
return ResourceManager.GetString("CtxMenuExtract", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Open.
|
||||
/// </summary>
|
||||
public static string CtxMenuOpen {
|
||||
get {
|
||||
return ResourceManager.GetString("CtxMenuOpen", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Paste.
|
||||
/// </summary>
|
||||
public static string CtxMenuPaste {
|
||||
get {
|
||||
return ResourceManager.GetString("CtxMenuPaste", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Refresh.
|
||||
/// </summary>
|
||||
public static string CtxMenuRefresh {
|
||||
get {
|
||||
return ResourceManager.GetString("CtxMenuRefresh", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to _Rename.
|
||||
/// </summary>
|
||||
public static string CtxMenuRename {
|
||||
get {
|
||||
return ResourceManager.GetString("CtxMenuRename", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Sort by.
|
||||
/// </summary>
|
||||
public static string CtxMenuSortBy {
|
||||
get {
|
||||
return ResourceManager.GetString("CtxMenuSortBy", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Name.
|
||||
/// </summary>
|
||||
public static string CtxMenuSortByName {
|
||||
get {
|
||||
return ResourceManager.GetString("CtxMenuSortByName", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Size.
|
||||
/// </summary>
|
||||
public static string CtxMenuSortBySize {
|
||||
get {
|
||||
return ResourceManager.GetString("CtxMenuSortBySize", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Type.
|
||||
/// </summary>
|
||||
public static string CtxMenuSortByType {
|
||||
get {
|
||||
return ResourceManager.GetString("CtxMenuSortByType", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unsorted.
|
||||
/// </summary>
|
||||
public static string CtxMenuUnsorted {
|
||||
get {
|
||||
return ResourceManager.GetString("CtxMenuUnsorted", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Name.
|
||||
/// </summary>
|
||||
public static string HeaderName {
|
||||
get {
|
||||
return ResourceManager.GetString("HeaderName", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Size.
|
||||
/// </summary>
|
||||
public static string HeaderSize {
|
||||
get {
|
||||
return ResourceManager.GetString("HeaderSize", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Type.
|
||||
/// </summary>
|
||||
public static string HeaderType {
|
||||
get {
|
||||
return ResourceManager.GetString("HeaderType", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to file.
|
||||
/// </summary>
|
||||
public static string LPfile1 {
|
||||
get {
|
||||
return ResourceManager.GetString("LPfile1", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to files.
|
||||
/// </summary>
|
||||
public static string LPfile2 {
|
||||
get {
|
||||
return ResourceManager.GetString("LPfile2", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to About.
|
||||
/// </summary>
|
||||
public static string MenuAbout {
|
||||
get {
|
||||
return ResourceManager.GetString("MenuAbout", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Deleted {0}.
|
||||
/// </summary>
|
||||
public static string MsgDeletedItem {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgDeletedItem", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to directory not found.
|
||||
/// </summary>
|
||||
public static string MsgDirectoryNotFound {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgDirectoryNotFound", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to archive is empty.
|
||||
/// </summary>
|
||||
public static string MsgEmptyArchive {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgEmptyArchive", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error extracting file.
|
||||
/// </summary>
|
||||
public static string MsgErrorExtracting {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgErrorExtracting", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error opening file.
|
||||
/// </summary>
|
||||
public static string MsgErrorOpening {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgErrorOpening", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Extracted {0} into {1}.
|
||||
/// </summary>
|
||||
public static string MsgExtractComplete {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgExtractComplete", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Extracted {0} {1}.
|
||||
/// </summary>
|
||||
public static string MsgExtractCompletePlural {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgExtractCompletePlural", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Extracting files from {0}.
|
||||
/// </summary>
|
||||
public static string MsgExtractingArchive {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgExtractingArchive", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Extracting file from {0}.
|
||||
/// </summary>
|
||||
public static string MsgExtractingFile {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgExtractingFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Extracting files from {0} to {1}.
|
||||
/// </summary>
|
||||
public static string MsgExtractingTo {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgExtractingTo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Image {0} x {1} pixels.
|
||||
/// </summary>
|
||||
public static string MsgImageSize {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgImageSize", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to no files to extract.
|
||||
/// </summary>
|
||||
public static string MsgNoFiles {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgNoFiles", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Ready.
|
||||
/// </summary>
|
||||
public static string MsgReady {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgReady", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to unable to interpret image format.
|
||||
/// </summary>
|
||||
public static string MsgUnableInterpret {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgUnableInterpret", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to file could not be opened as resource archive.
|
||||
/// </summary>
|
||||
public static string MsgUnknownFormat {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgUnknownFormat", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version {0}.
|
||||
/// </summary>
|
||||
public static string MsgVersion {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgVersion", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to [builtin].
|
||||
/// </summary>
|
||||
public static string TextAboutBuiltin {
|
||||
get {
|
||||
return ResourceManager.GetString("TextAboutBuiltin", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Supported archives:.
|
||||
/// </summary>
|
||||
public static string TextAboutSupportedArchives {
|
||||
get {
|
||||
return ResourceManager.GetString("TextAboutSupportedArchives", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Supported image formats:.
|
||||
/// </summary>
|
||||
public static string TextAboutSupportedImages {
|
||||
get {
|
||||
return ResourceManager.GetString("TextAboutSupportedImages", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to About Game Resource browser.
|
||||
/// </summary>
|
||||
public static string TextAboutTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("TextAboutTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to as is.
|
||||
/// </summary>
|
||||
public static string TextAsIs {
|
||||
get {
|
||||
return ResourceManager.GetString("TextAsIs", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Choose destination directory.
|
||||
/// </summary>
|
||||
public static string TextChooseDestDir {
|
||||
get {
|
||||
return ResourceManager.GetString("TextChooseDestDir", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to <DIR>.
|
||||
/// </summary>
|
||||
public static string TextDirType {
|
||||
get {
|
||||
return ResourceManager.GetString("TextDirType", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Text encoding.
|
||||
/// </summary>
|
||||
public static string TextEncoding {
|
||||
get {
|
||||
return ResourceManager.GetString("TextEncoding", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Extract all files from {0} to.
|
||||
/// </summary>
|
||||
public static string TextExtractAllTo {
|
||||
get {
|
||||
return ResourceManager.GetString("TextExtractAllTo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Extract {0} to.
|
||||
/// </summary>
|
||||
public static string TextExtractFileTo {
|
||||
get {
|
||||
return ResourceManager.GetString("TextExtractFileTo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Extract images.
|
||||
/// </summary>
|
||||
public static string TextExtractImages {
|
||||
get {
|
||||
return ResourceManager.GetString("TextExtractImages", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Extract text.
|
||||
/// </summary>
|
||||
public static string TextExtractText {
|
||||
get {
|
||||
return ResourceManager.GetString("TextExtractText", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Extract from archive.
|
||||
/// </summary>
|
||||
public static string TextExtractTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("TextExtractTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Archive parameters.
|
||||
/// </summary>
|
||||
public static string TextParametersTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("TextParametersTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Save as.
|
||||
/// </summary>
|
||||
public static string TextSaveAs {
|
||||
get {
|
||||
return ResourceManager.GetString("TextSaveAs", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Save images as.
|
||||
/// </summary>
|
||||
public static string TextSaveImagesAs {
|
||||
get {
|
||||
return ResourceManager.GetString("TextSaveImagesAs", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Game Resource browser.
|
||||
/// </summary>
|
||||
public static string TextTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("TextTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Back.
|
||||
/// </summary>
|
||||
public static string TooltipBack {
|
||||
get {
|
||||
return ResourceManager.GetString("TooltipBack", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Forward.
|
||||
/// </summary>
|
||||
public static string TooltipForward {
|
||||
get {
|
||||
return ResourceManager.GetString("TooltipForward", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
297
Strings/guiStrings.resx
Normal file
297
Strings/guiStrings.resx
Normal file
@ -0,0 +1,297 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ButtonCancel" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="ButtonExtract" xml:space="preserve">
|
||||
<value>Extract</value>
|
||||
</data>
|
||||
<data name="ButtonOK" xml:space="preserve">
|
||||
<value>OK</value>
|
||||
</data>
|
||||
<data name="CtxMenuClose" xml:space="preserve">
|
||||
<value>_Close</value>
|
||||
</data>
|
||||
<data name="CtxMenuCopy" xml:space="preserve">
|
||||
<value>Copy</value>
|
||||
</data>
|
||||
<data name="CtxMenuCut" xml:space="preserve">
|
||||
<value>Cut</value>
|
||||
</data>
|
||||
<data name="CtxMenuDelete" xml:space="preserve">
|
||||
<value>_Delete</value>
|
||||
</data>
|
||||
<data name="CtxMenuExplorer" xml:space="preserve">
|
||||
<value>Browse in _Explorer</value>
|
||||
</data>
|
||||
<data name="CtxMenuExtract" xml:space="preserve">
|
||||
<value>Extract</value>
|
||||
</data>
|
||||
<data name="CtxMenuOpen" xml:space="preserve">
|
||||
<value>Open</value>
|
||||
</data>
|
||||
<data name="CtxMenuPaste" xml:space="preserve">
|
||||
<value>Paste</value>
|
||||
</data>
|
||||
<data name="CtxMenuRefresh" xml:space="preserve">
|
||||
<value>Refresh</value>
|
||||
</data>
|
||||
<data name="CtxMenuRename" xml:space="preserve">
|
||||
<value>_Rename</value>
|
||||
</data>
|
||||
<data name="CtxMenuSortBy" xml:space="preserve">
|
||||
<value>Sort by</value>
|
||||
</data>
|
||||
<data name="CtxMenuSortByName" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
</data>
|
||||
<data name="CtxMenuSortBySize" xml:space="preserve">
|
||||
<value>Size</value>
|
||||
</data>
|
||||
<data name="CtxMenuSortByType" xml:space="preserve">
|
||||
<value>Type</value>
|
||||
</data>
|
||||
<data name="CtxMenuUnsorted" xml:space="preserve">
|
||||
<value>Unsorted</value>
|
||||
</data>
|
||||
<data name="HeaderName" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
</data>
|
||||
<data name="HeaderSize" xml:space="preserve">
|
||||
<value>Size</value>
|
||||
</data>
|
||||
<data name="HeaderType" xml:space="preserve">
|
||||
<value>Type</value>
|
||||
</data>
|
||||
<data name="LPfile1" xml:space="preserve">
|
||||
<value>file</value>
|
||||
</data>
|
||||
<data name="LPfile2" xml:space="preserve">
|
||||
<value>files</value>
|
||||
</data>
|
||||
<data name="MenuAbout" xml:space="preserve">
|
||||
<value>About</value>
|
||||
</data>
|
||||
<data name="MsgDeletedItem" xml:space="preserve">
|
||||
<value>Deleted {0}</value>
|
||||
</data>
|
||||
<data name="MsgDirectoryNotFound" xml:space="preserve">
|
||||
<value>directory not found</value>
|
||||
</data>
|
||||
<data name="MsgEmptyArchive" xml:space="preserve">
|
||||
<value>archive is empty</value>
|
||||
</data>
|
||||
<data name="MsgErrorExtracting" xml:space="preserve">
|
||||
<value>Error extracting file</value>
|
||||
</data>
|
||||
<data name="MsgErrorOpening" xml:space="preserve">
|
||||
<value>Error opening file</value>
|
||||
</data>
|
||||
<data name="MsgExtractComplete" xml:space="preserve">
|
||||
<value>Extracted {0} into {1}</value>
|
||||
</data>
|
||||
<data name="MsgExtractCompletePlural" xml:space="preserve">
|
||||
<value>Extracted {0} {1}</value>
|
||||
</data>
|
||||
<data name="MsgExtractingArchive" xml:space="preserve">
|
||||
<value>Extracting files from {0}</value>
|
||||
</data>
|
||||
<data name="MsgExtractingFile" xml:space="preserve">
|
||||
<value>Extracting file from {0}</value>
|
||||
</data>
|
||||
<data name="MsgExtractingTo" xml:space="preserve">
|
||||
<value>Extracting files from {0} to {1}</value>
|
||||
</data>
|
||||
<data name="MsgImageSize" xml:space="preserve">
|
||||
<value>Image {0} x {1} pixels</value>
|
||||
</data>
|
||||
<data name="MsgNoFiles" xml:space="preserve">
|
||||
<value>no files to extract</value>
|
||||
</data>
|
||||
<data name="MsgReady" xml:space="preserve">
|
||||
<value>Ready</value>
|
||||
</data>
|
||||
<data name="MsgUnableInterpret" xml:space="preserve">
|
||||
<value>unable to interpret image format</value>
|
||||
</data>
|
||||
<data name="MsgUnknownFormat" xml:space="preserve">
|
||||
<value>file could not be opened as resource archive</value>
|
||||
</data>
|
||||
<data name="MsgVersion" xml:space="preserve">
|
||||
<value>Version {0}</value>
|
||||
</data>
|
||||
<data name="TextAboutBuiltin" xml:space="preserve">
|
||||
<value>[builtin]</value>
|
||||
</data>
|
||||
<data name="TextAboutSupportedArchives" xml:space="preserve">
|
||||
<value>Supported archives:</value>
|
||||
</data>
|
||||
<data name="TextAboutSupportedImages" xml:space="preserve">
|
||||
<value>Supported image formats:</value>
|
||||
</data>
|
||||
<data name="TextAboutTitle" xml:space="preserve">
|
||||
<value>About Game Resource browser</value>
|
||||
</data>
|
||||
<data name="TextAsIs" xml:space="preserve">
|
||||
<value>as is</value>
|
||||
</data>
|
||||
<data name="TextChooseDestDir" xml:space="preserve">
|
||||
<value>Choose destination directory</value>
|
||||
</data>
|
||||
<data name="TextDirType" xml:space="preserve">
|
||||
<value><DIR></value>
|
||||
</data>
|
||||
<data name="TextEncoding" xml:space="preserve">
|
||||
<value>Text encoding</value>
|
||||
</data>
|
||||
<data name="TextExtractAllTo" xml:space="preserve">
|
||||
<value>Extract all files from {0} to</value>
|
||||
</data>
|
||||
<data name="TextExtractFileTo" xml:space="preserve">
|
||||
<value>Extract {0} to</value>
|
||||
</data>
|
||||
<data name="TextExtractImages" xml:space="preserve">
|
||||
<value>Extract images</value>
|
||||
</data>
|
||||
<data name="TextExtractText" xml:space="preserve">
|
||||
<value>Extract text</value>
|
||||
</data>
|
||||
<data name="TextExtractTitle" xml:space="preserve">
|
||||
<value>Extract from archive</value>
|
||||
</data>
|
||||
<data name="TextParametersTitle" xml:space="preserve">
|
||||
<value>Archive parameters</value>
|
||||
</data>
|
||||
<data name="TextSaveAs" xml:space="preserve">
|
||||
<value>Save as</value>
|
||||
</data>
|
||||
<data name="TextSaveImagesAs" xml:space="preserve">
|
||||
<value>Save images as</value>
|
||||
</data>
|
||||
<data name="TextTitle" xml:space="preserve">
|
||||
<value>Game Resource browser</value>
|
||||
</data>
|
||||
<data name="TooltipBack" xml:space="preserve">
|
||||
<value>Back</value>
|
||||
</data>
|
||||
<data name="TooltipForward" xml:space="preserve">
|
||||
<value>Forward</value>
|
||||
</data>
|
||||
</root>
|
300
Strings/guiStrings.ru-RU.resx
Normal file
300
Strings/guiStrings.ru-RU.resx
Normal file
@ -0,0 +1,300 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ButtonCancel" xml:space="preserve">
|
||||
<value>Отмена</value>
|
||||
</data>
|
||||
<data name="ButtonExtract" xml:space="preserve">
|
||||
<value>Извлечь</value>
|
||||
</data>
|
||||
<data name="CtxMenuClose" xml:space="preserve">
|
||||
<value>_Закрыть</value>
|
||||
</data>
|
||||
<data name="CtxMenuCopy" xml:space="preserve">
|
||||
<value>Копировать</value>
|
||||
</data>
|
||||
<data name="CtxMenuCut" xml:space="preserve">
|
||||
<value>Вырезать</value>
|
||||
</data>
|
||||
<data name="CtxMenuDelete" xml:space="preserve">
|
||||
<value>Удалить</value>
|
||||
</data>
|
||||
<data name="CtxMenuExplorer" xml:space="preserve">
|
||||
<value>Просмотр в Explorer</value>
|
||||
</data>
|
||||
<data name="CtxMenuExtract" xml:space="preserve">
|
||||
<value>Извлечь</value>
|
||||
</data>
|
||||
<data name="CtxMenuOpen" xml:space="preserve">
|
||||
<value>Открыть</value>
|
||||
</data>
|
||||
<data name="CtxMenuPaste" xml:space="preserve">
|
||||
<value>Вставить</value>
|
||||
</data>
|
||||
<data name="CtxMenuRefresh" xml:space="preserve">
|
||||
<value>Обновить</value>
|
||||
</data>
|
||||
<data name="CtxMenuRename" xml:space="preserve">
|
||||
<value>Переименовать</value>
|
||||
</data>
|
||||
<data name="CtxMenuSortBy" xml:space="preserve">
|
||||
<value>Сортировка</value>
|
||||
</data>
|
||||
<data name="CtxMenuSortByName" xml:space="preserve">
|
||||
<value>по имени</value>
|
||||
</data>
|
||||
<data name="CtxMenuSortBySize" xml:space="preserve">
|
||||
<value>по размеру</value>
|
||||
</data>
|
||||
<data name="CtxMenuSortByType" xml:space="preserve">
|
||||
<value>по типу</value>
|
||||
</data>
|
||||
<data name="CtxMenuUnsorted" xml:space="preserve">
|
||||
<value>не сортировать</value>
|
||||
</data>
|
||||
<data name="HeaderName" xml:space="preserve">
|
||||
<value>Имя</value>
|
||||
</data>
|
||||
<data name="HeaderSize" xml:space="preserve">
|
||||
<value>Размер</value>
|
||||
</data>
|
||||
<data name="HeaderType" xml:space="preserve">
|
||||
<value>Тип</value>
|
||||
</data>
|
||||
<data name="LPfile1" xml:space="preserve">
|
||||
<value>файл</value>
|
||||
</data>
|
||||
<data name="LPfile2" xml:space="preserve">
|
||||
<value>файла</value>
|
||||
</data>
|
||||
<data name="LPfile3" xml:space="preserve">
|
||||
<value>файлов</value>
|
||||
</data>
|
||||
<data name="MenuAbout" xml:space="preserve">
|
||||
<value>О программе</value>
|
||||
</data>
|
||||
<data name="MsgDeletedItem" xml:space="preserve">
|
||||
<value>Удалён файл {0}</value>
|
||||
</data>
|
||||
<data name="MsgDirectoryNotFound" xml:space="preserve">
|
||||
<value>каталог не найден</value>
|
||||
</data>
|
||||
<data name="MsgEmptyArchive" xml:space="preserve">
|
||||
<value>архив пуст</value>
|
||||
</data>
|
||||
<data name="MsgErrorExtracting" xml:space="preserve">
|
||||
<value>Ошибка извлечения файла</value>
|
||||
</data>
|
||||
<data name="MsgErrorOpening" xml:space="preserve">
|
||||
<value>Ошибка открытия файла</value>
|
||||
</data>
|
||||
<data name="MsgExtractComplete" xml:space="preserve">
|
||||
<value>{0} извлечён в {1}</value>
|
||||
</data>
|
||||
<data name="MsgExtractCompletePlural" xml:space="preserve">
|
||||
<value>Извлечено {0} {1}</value>
|
||||
</data>
|
||||
<data name="MsgExtractingArchive" xml:space="preserve">
|
||||
<value>Извлекаются файлы из {0}</value>
|
||||
</data>
|
||||
<data name="MsgExtractingFile" xml:space="preserve">
|
||||
<value>Файл извлекается из {0}</value>
|
||||
</data>
|
||||
<data name="MsgExtractingTo" xml:space="preserve">
|
||||
<value>Извлекаются файлы из {0} в {1}</value>
|
||||
</data>
|
||||
<data name="MsgImageSize" xml:space="preserve">
|
||||
<value>Изображение {0} x {1} пикселей</value>
|
||||
</data>
|
||||
<data name="MsgNoFiles" xml:space="preserve">
|
||||
<value>отсутствуют файлы, удовлетворяющие выбранным критериям</value>
|
||||
</data>
|
||||
<data name="MsgReady" xml:space="preserve">
|
||||
<value>Готов</value>
|
||||
</data>
|
||||
<data name="MsgUnableInterpret" xml:space="preserve">
|
||||
<value>не удалось интерпретировать формат изображения</value>
|
||||
</data>
|
||||
<data name="MsgUnknownFormat" xml:space="preserve">
|
||||
<value>файл не может быть открыт как архив ресурсов</value>
|
||||
</data>
|
||||
<data name="MsgVersion" xml:space="preserve">
|
||||
<value>Версия {0}</value>
|
||||
</data>
|
||||
<data name="TextAboutBuiltin" xml:space="preserve">
|
||||
<value>[встроен]</value>
|
||||
</data>
|
||||
<data name="TextAboutSupportedArchives" xml:space="preserve">
|
||||
<value>Поддерживаемые архивы:</value>
|
||||
</data>
|
||||
<data name="TextAboutSupportedImages" xml:space="preserve">
|
||||
<value>Поддерживаемые форматы изображений:</value>
|
||||
</data>
|
||||
<data name="TextAboutTitle" xml:space="preserve">
|
||||
<value>Об обозревателе игровых ресурсов</value>
|
||||
</data>
|
||||
<data name="TextAsIs" xml:space="preserve">
|
||||
<value>исходном</value>
|
||||
</data>
|
||||
<data name="TextChooseDestDir" xml:space="preserve">
|
||||
<value>Выберите место извлечения</value>
|
||||
</data>
|
||||
<data name="TextDirType" xml:space="preserve">
|
||||
<value><DIR></value>
|
||||
</data>
|
||||
<data name="TextEncoding" xml:space="preserve">
|
||||
<value>Кодировка текста</value>
|
||||
</data>
|
||||
<data name="TextExtractAllTo" xml:space="preserve">
|
||||
<value>Извлечь все файлы из {0} в</value>
|
||||
</data>
|
||||
<data name="TextExtractFileTo" xml:space="preserve">
|
||||
<value>Извлечь {0} в</value>
|
||||
</data>
|
||||
<data name="TextExtractImages" xml:space="preserve">
|
||||
<value>Извлекать изображения</value>
|
||||
</data>
|
||||
<data name="TextExtractText" xml:space="preserve">
|
||||
<value>Извлекать текст</value>
|
||||
</data>
|
||||
<data name="TextExtractTitle" xml:space="preserve">
|
||||
<value>Извлечь из архива</value>
|
||||
</data>
|
||||
<data name="TextOK" xml:space="preserve">
|
||||
<value>OK</value>
|
||||
</data>
|
||||
<data name="TextParametersTitle" xml:space="preserve">
|
||||
<value>Параметры архива</value>
|
||||
</data>
|
||||
<data name="TextSaveAs" xml:space="preserve">
|
||||
<value>Сохранить в формате</value>
|
||||
</data>
|
||||
<data name="TextSaveImagesAs" xml:space="preserve">
|
||||
<value>Сохранить в формате</value>
|
||||
</data>
|
||||
<data name="TextTitle" xml:space="preserve">
|
||||
<value>Обозреватель игровых ресурсов</value>
|
||||
</data>
|
||||
<data name="TooltipBack" xml:space="preserve">
|
||||
<value>Назад</value>
|
||||
</data>
|
||||
<data name="TooltipForward" xml:space="preserve">
|
||||
<value>Вперёд</value>
|
||||
</data>
|
||||
</root>
|
117
Utility.cs
Normal file
117
Utility.cs
Normal file
@ -0,0 +1,117 @@
|
||||
//! \file Utility.cs
|
||||
//! \date Sun Jul 06 07:40:34 2014
|
||||
//! \brief utility classes.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Input;
|
||||
using GARbro.GUI.Strings;
|
||||
|
||||
namespace GARbro.GUI
|
||||
{
|
||||
internal class NativeMethods
|
||||
{
|
||||
[DllImport ("shlwapi.dll", CharSet = CharSet.Unicode)]
|
||||
internal static extern int StrCmpLogicalW (string psz1, string psz2);
|
||||
|
||||
[DllImport ("gdi32.dll")]
|
||||
internal static extern int GetDeviceCaps (IntPtr hDc, int nIndex);
|
||||
|
||||
[DllImport ("user32.dll")]
|
||||
internal static extern IntPtr GetDC (IntPtr hWnd);
|
||||
|
||||
[DllImport ("user32.dll")]
|
||||
internal static extern int ReleaseDC (IntPtr hWnd, IntPtr hDc);
|
||||
}
|
||||
|
||||
public static class Desktop
|
||||
{
|
||||
public static int DpiX { get { return dpi_x; } }
|
||||
public static int DpiY { get { return dpi_y; } }
|
||||
|
||||
public const int LOGPIXELSX = 88;
|
||||
public const int LOGPIXELSY = 90;
|
||||
|
||||
private static int dpi_x = GetCaps (LOGPIXELSX);
|
||||
private static int dpi_y = GetCaps (LOGPIXELSY);
|
||||
|
||||
public static int GetCaps (int cap)
|
||||
{
|
||||
IntPtr hdc = NativeMethods.GetDC (IntPtr.Zero);
|
||||
if (hdc == IntPtr.Zero)
|
||||
return 96;
|
||||
int dpi = NativeMethods.GetDeviceCaps (hdc, cap);
|
||||
NativeMethods.ReleaseDC (IntPtr.Zero, hdc);
|
||||
return dpi;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class NumericStringComparer : IComparer<string>
|
||||
{
|
||||
public int Compare (string a, string b)
|
||||
{
|
||||
return NativeMethods.StrCmpLogicalW (a, b);
|
||||
}
|
||||
}
|
||||
|
||||
public class WaitCursor : IDisposable
|
||||
{
|
||||
private Cursor m_previousCursor;
|
||||
|
||||
public WaitCursor()
|
||||
{
|
||||
m_previousCursor = Mouse.OverrideCursor;
|
||||
Mouse.OverrideCursor = Cursors.Wait;
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
bool disposed = false;
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
Mouse.OverrideCursor = m_previousCursor;
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class Localization
|
||||
{
|
||||
public static string Plural (int n, string en_singular)
|
||||
{
|
||||
string suffix;
|
||||
if (CultureInfo.CurrentUICulture.Name == "ru-RU")
|
||||
{
|
||||
suffix = (n%10==1 && n%100!=11 ? "1" : n%10>=2 && n% 10<=4 && (n%100<10 || n%100>=20) ? "2" : "3");
|
||||
}
|
||||
else // assume en-EN
|
||||
{
|
||||
suffix = 1 == n ? "1" : "2";
|
||||
}
|
||||
try
|
||||
{
|
||||
var res = guiStrings.ResourceManager.GetString ("LP"+en_singular+suffix);
|
||||
return res ?? en_singular;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return en_singular;
|
||||
}
|
||||
}
|
||||
|
||||
// Localization.Format ("{0:file:files} copied", count);
|
||||
// public static string Format (string format, params object[] args);
|
||||
}
|
||||
}
|
296
ViewModel.cs
Normal file
296
ViewModel.cs
Normal file
@ -0,0 +1,296 @@
|
||||
//! \file ViewModel.cs
|
||||
//! \date Wed Jul 02 07:29:11 2014
|
||||
//! \brief GARbro directory list.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Globalization;
|
||||
using GameRes;
|
||||
using GARbro.GUI.Strings;
|
||||
|
||||
namespace GARbro.GUI
|
||||
{
|
||||
public class SubDirEntry : GameRes.Entry
|
||||
{
|
||||
public override string Type { get { return guiStrings.TextDirType; } }
|
||||
|
||||
public SubDirEntry (string name)
|
||||
{
|
||||
Name = name;
|
||||
Size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public class DirectoryViewModel : ObservableCollection<EntryViewModel>
|
||||
{
|
||||
public string Path { get; private set; }
|
||||
public ICollection<Entry> Source { get; private set; }
|
||||
public virtual bool IsArchive { get { return false; } }
|
||||
|
||||
public DirectoryViewModel (string path, ICollection<Entry> filelist)
|
||||
{
|
||||
Path = path;
|
||||
Source = filelist;
|
||||
ImportFromSource();
|
||||
}
|
||||
|
||||
protected virtual void ImportFromSource ()
|
||||
{
|
||||
if (!string.IsNullOrEmpty (Path) && null != Directory.GetParent (Path))
|
||||
{
|
||||
Add (new EntryViewModel (new SubDirEntry (".."), -2));
|
||||
}
|
||||
foreach (var entry in Source)
|
||||
{
|
||||
int prio = null == entry as SubDirEntry ? 0 : -1;
|
||||
Add (new EntryViewModel (entry, prio));
|
||||
}
|
||||
}
|
||||
|
||||
public EntryViewModel Find (string name)
|
||||
{
|
||||
return this.FirstOrDefault (e => e.Name.Equals (name, System.StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
public virtual void SetPosition (DirectoryPosition pos)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class ArchiveViewModel : DirectoryViewModel
|
||||
{
|
||||
public override bool IsArchive { get { return true; } }
|
||||
public string SubDir { get; protected set; }
|
||||
|
||||
public ArchiveViewModel (string path, ArcFile arc)
|
||||
: base (path, arc.Dir)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void ImportFromSource ()
|
||||
{
|
||||
UpdateModel ("");
|
||||
}
|
||||
|
||||
private string m_delimiter = "/";
|
||||
private static readonly char[] m_path_delimiters = { '/', '\\' };
|
||||
|
||||
public void ChDir (string subdir)
|
||||
{
|
||||
string new_path;
|
||||
if (".." == subdir)
|
||||
{
|
||||
if (0 == SubDir.Length)
|
||||
return;
|
||||
var path = SubDir.Split (m_path_delimiters);
|
||||
if (path.Length > 1)
|
||||
new_path = string.Join (m_delimiter, path, 0, path.Length-1);
|
||||
else
|
||||
new_path = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
var entry = this.FirstOrDefault (e => e.Name.Equals (subdir, StringComparison.OrdinalIgnoreCase));
|
||||
if (null == entry)
|
||||
throw new DirectoryNotFoundException (string.Format ("{1}: {0}", guiStrings.MsgDirectoryNotFound, subdir));
|
||||
if (SubDir.Length > 0)
|
||||
new_path = SubDir + m_delimiter + entry.Name;
|
||||
else
|
||||
new_path = entry.Name;
|
||||
}
|
||||
UpdateModel (new_path);
|
||||
}
|
||||
|
||||
static readonly Regex path_re = new Regex (@"\G[/\\]?([^/\\]+)([/\\])");
|
||||
|
||||
private void UpdateModel (string root_path)
|
||||
{
|
||||
IEnumerable<Entry> dir = Source;
|
||||
if (!string.IsNullOrEmpty (root_path))
|
||||
dir = from entry in dir
|
||||
where entry.Name.StartsWith (root_path+m_delimiter)
|
||||
select entry;
|
||||
if (!dir.Any())
|
||||
{
|
||||
throw new DirectoryNotFoundException (string.Format ("{1}: {0}", guiStrings.MsgDirectoryNotFound, root_path));
|
||||
}
|
||||
m_suppress_notification = true;
|
||||
try
|
||||
{
|
||||
this.Clear();
|
||||
SubDir = root_path;
|
||||
Add (new EntryViewModel (new SubDirEntry (".."), -2));
|
||||
var subdirs = new HashSet<string>();
|
||||
foreach (var entry in dir)
|
||||
{
|
||||
var match = path_re.Match (entry.Name, root_path.Length);
|
||||
if (match.Success)
|
||||
{
|
||||
string name = match.Groups[1].Value;
|
||||
if (subdirs.Add (name))
|
||||
{
|
||||
m_delimiter = match.Groups[2].Value;
|
||||
Add (new EntryViewModel (new SubDirEntry (name), -1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Add (new EntryViewModel (entry, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_suppress_notification = false;
|
||||
OnCollectionChanged (new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetPosition (DirectoryPosition pos)
|
||||
{
|
||||
UpdateModel (pos.ArchivePath);
|
||||
}
|
||||
|
||||
public IEnumerable<Entry> GetFiles (EntryViewModel entry)
|
||||
{
|
||||
if (!entry.IsDirectory)
|
||||
return new Entry[] { entry.Source };
|
||||
|
||||
string path = GetPath (entry.Name);
|
||||
return from file in Source
|
||||
where file.Name.StartsWith (path)
|
||||
select file;
|
||||
}
|
||||
|
||||
string GetPath (string dir)
|
||||
{
|
||||
if (SubDir.Length > 0)
|
||||
return SubDir + m_delimiter + dir + m_delimiter;
|
||||
else
|
||||
return dir + m_delimiter;
|
||||
}
|
||||
|
||||
private bool m_suppress_notification = false;
|
||||
|
||||
protected override void OnCollectionChanged (NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (!m_suppress_notification)
|
||||
base.OnCollectionChanged(e);
|
||||
}
|
||||
}
|
||||
|
||||
public class EntryViewModel
|
||||
{
|
||||
public EntryViewModel (Entry entry, int priority)
|
||||
{
|
||||
Source = entry;
|
||||
Name = Path.GetFileName (entry.Name);
|
||||
Priority = priority;
|
||||
}
|
||||
|
||||
public Entry Source { get; private set; }
|
||||
|
||||
public string Name { get; private set; }
|
||||
public string Type { get { return Source.Type; } }
|
||||
public uint Size { get { return Source.Size; } }
|
||||
public int Priority { get; private set; }
|
||||
public bool IsDirectory { get { return Priority < 0; } }
|
||||
}
|
||||
|
||||
public sealed class FileSystemComparer : IComparer
|
||||
{
|
||||
private string m_property;
|
||||
private int m_direction;
|
||||
private static Comparer s_default_comparer = new Comparer (CultureInfo.CurrentUICulture);
|
||||
|
||||
public FileSystemComparer (string property, ListSortDirection direction)
|
||||
{
|
||||
m_property = property;
|
||||
m_direction = direction == ListSortDirection.Ascending ? 1 : -1;
|
||||
}
|
||||
|
||||
public int Compare (object a, object b)
|
||||
{
|
||||
var v_a = a as EntryViewModel;
|
||||
var v_b = b as EntryViewModel;
|
||||
if (null == v_a || null == v_b)
|
||||
return s_default_comparer.Compare (a, b) * m_direction;
|
||||
|
||||
if (v_a.Priority < v_b.Priority)
|
||||
return -1;
|
||||
if (v_a.Priority > v_b.Priority)
|
||||
return 1;
|
||||
if (string.IsNullOrEmpty (m_property))
|
||||
return 0;
|
||||
int order;
|
||||
if (m_property != "Name")
|
||||
{
|
||||
if ("Type" == m_property)
|
||||
{
|
||||
// empty strings placed in the end
|
||||
if (string.IsNullOrEmpty (v_a.Type))
|
||||
order = string.IsNullOrEmpty (v_b.Type) ? 0 : m_direction;
|
||||
else if (string.IsNullOrEmpty (v_b.Type))
|
||||
order = -m_direction;
|
||||
else
|
||||
order = string.Compare (v_a.Type, v_b.Type, true) * m_direction;
|
||||
}
|
||||
else
|
||||
{
|
||||
var prop_a = a.GetType ().GetProperty (m_property).GetValue (a);
|
||||
var prop_b = b.GetType ().GetProperty (m_property).GetValue (b);
|
||||
order = s_default_comparer.Compare (prop_a, prop_b) * m_direction;
|
||||
}
|
||||
if (0 == order)
|
||||
order = NativeMethods.StrCmpLogicalW (v_a.Name, v_b.Name);
|
||||
}
|
||||
else
|
||||
order = NativeMethods.StrCmpLogicalW (v_a.Name, v_b.Name) * m_direction;
|
||||
return order;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Image format model for formats drop-down list widgets.
|
||||
/// </summary>
|
||||
public class ImageFormatModel
|
||||
{
|
||||
public ImageFormat Source { get; private set; }
|
||||
public string Tag {
|
||||
get { return null != Source ? Source.Tag : guiStrings.TextAsIs; }
|
||||
}
|
||||
|
||||
public ImageFormatModel (ImageFormat impl = null)
|
||||
{
|
||||
Source = impl;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores current position within directory view model.
|
||||
/// </summary>
|
||||
public class DirectoryPosition
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public string ArchivePath { get; set; }
|
||||
public EntryViewModel Item { get; set; }
|
||||
|
||||
public DirectoryPosition (DirectoryViewModel vm, EntryViewModel item)
|
||||
{
|
||||
Path = vm.Path;
|
||||
Item = item;
|
||||
if (vm.IsArchive)
|
||||
ArchivePath = (vm as ArchiveViewModel).SubDir;
|
||||
else
|
||||
ArchivePath = "";
|
||||
}
|
||||
}
|
||||
}
|
6
packages.config
Normal file
6
packages.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Ookii.Dialogs" version="1.0" targetFramework="net45" />
|
||||
<package id="WindowsAPICodePack-Core" version="1.1" targetFramework="net45" />
|
||||
<package id="WindowsAPICodePack-Shell" version="1.1" targetFramework="net45" />
|
||||
</packages>
|
25
zlib/changes.txt
Normal file
25
zlib/changes.txt
Normal file
@ -0,0 +1,25 @@
|
||||
v1.3 june 2013
|
||||
Upgrade zlib to 1.2.8
|
||||
Make custom build v1.2.8.1 where 1 bugs fixed: Incorrect move method was sent to SetFilePointer.
|
||||
Fix bug where utf8 flag was not set correctly.
|
||||
Change UTF8Encoding to default true.
|
||||
Support unicode in filename of zip itself.
|
||||
|
||||
v1.2 6.may 2012
|
||||
-Upgrade zlib to 1.2.7
|
||||
-Change Zip64 option to enum (Yes,No,Auto) where Auto now is default (was No)
|
||||
|
||||
v1.1 6.jan 2011
|
||||
Fixed bug: If Unzipper.ItemList had more than one entry, unzip would not work (exctracted files would try to overwrite themself)
|
||||
|
||||
Update zlib dlls to custom build v1.2.5.1 where 2 bugs fixed:
|
||||
-Adding over 64k number of entries in zip with total size below 4GB created invalid zip
|
||||
-Writing entries over 4GB with zip64=false did not fail but created invalid zip
|
||||
|
||||
Misc:
|
||||
Convert unsafe code to safe code.
|
||||
Wrap CloseCurrentEntry in try/finally block: we must always CloseFile, even if CloseCurrentEntry fails.
|
||||
Zip64 zipping works now.
|
||||
|
||||
v1.0
|
||||
Initial release
|
BIN
zlib/zlib32.dll
Normal file
BIN
zlib/zlib32.dll
Normal file
Binary file not shown.
BIN
zlib/zlib64.dll
Normal file
BIN
zlib/zlib64.dll
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user