U8 Support, Split ADPCM encoder and decoder, more

Added more names to the sarc hashtable.
Fixed firefox bug (was related to using HWND_BROADCAST)
More bugfixes
This commit is contained in:
Gericom 2015-01-28 16:13:44 +01:00
parent 8e64576958
commit 4193ebe25b
15 changed files with 759 additions and 171 deletions

View File

@ -52,6 +52,8 @@
this.menuItem6 = new System.Windows.Forms.MenuItem();
this.menuTools = new System.Windows.Forms.MenuItem();
this.menuCompression = new System.Windows.Forms.MenuItem();
this.menuItem9 = new System.Windows.Forms.MenuItem();
this.menuEFECmd = new System.Windows.Forms.MenuItem();
this.menuItem2 = new System.Windows.Forms.MenuItem();
this.menuItemOptions = new System.Windows.Forms.MenuItem();
this.menuWindow = new System.Windows.Forms.MenuItem();
@ -70,8 +72,6 @@
this.tabPage1 = new System.Windows.Forms.TabPage();
this.treeView1 = new System.Windows.Forms.TreeView();
this.splitter1 = new System.Windows.Forms.Splitter();
this.menuEFECmd = new System.Windows.Forms.MenuItem();
this.menuItem9 = new System.Windows.Forms.MenuItem();
this.panel1.SuspendLayout();
this.toolStrip1.SuspendLayout();
this.panel2.SuspendLayout();
@ -240,6 +240,17 @@
this.menuCompression.Index = 0;
this.menuCompression.Text = "Compression";
//
// menuItem9
//
this.menuItem9.Index = 1;
this.menuItem9.Text = "-";
//
// menuEFECmd
//
this.menuEFECmd.Index = 2;
this.menuEFECmd.Text = "EFE Command Prompt";
this.menuEFECmd.Click += new System.EventHandler(this.menuItem1_Click_1);
//
// menuItem2
//
this.menuItem2.Index = 3;
@ -385,17 +396,6 @@
this.splitter1.TabStop = false;
this.splitter1.Visible = false;
//
// menuEFECmd
//
this.menuEFECmd.Index = 2;
this.menuEFECmd.Text = "EFE Command Prompt";
this.menuEFECmd.Click += new System.EventHandler(this.menuItem1_Click_1);
//
// menuItem9
//
this.menuItem9.Index = 1;
this.menuItem9.Text = "-";
//
// Form1
//
this.AllowDrop = true;

View File

@ -57,7 +57,10 @@ namespace EveryFileExplorer
{
String arg0 = "";
if (Arguments.Length > 0) arg0 = Arguments[0];
Win32Util.SendString((IntPtr)Win32Util.HWND_BROADCAST, arg0);
foreach (var p in System.Diagnostics.Process.GetProcessesByName(System.Diagnostics.Process.GetCurrentProcess().ProcessName))
{
if (p != System.Diagnostics.Process.GetCurrentProcess()) Win32Util.SendString(/*(IntPtr)Win32Util.HWND_BROADCAST*/p.MainWindowHandle, arg0);
}
}
}

View File

@ -54,12 +54,19 @@
<DependentUpon>Resource.resx</DependentUpon>
</Compile>
<Compile Include="TPL.cs" />
<Compile Include="U8.cs" />
<Compile Include="UI\BTIViewer.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="UI\BTIViewer.Designer.cs">
<DependentUpon>BTIViewer.cs</DependentUpon>
</Compile>
<Compile Include="UI\U8Viewer.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="UI\U8Viewer.Designer.cs">
<DependentUpon>U8Viewer.cs</DependentUpon>
</Compile>
<Compile Include="UI\TPLViewer.cs">
<SubType>Form</SubType>
</Compile>
@ -87,6 +94,9 @@
<EmbeddedResource Include="UI\BTIViewer.resx">
<DependentUpon>BTIViewer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UI\U8Viewer.resx">
<DependentUpon>U8Viewer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UI\TPLViewer.resx">
<DependentUpon>TPLViewer.cs</DependentUpon>
</EmbeddedResource>

145
GCNWii/U8.cs Normal file
View File

@ -0,0 +1,145 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LibEveryFileExplorer.IO.Serialization;
using LibEveryFileExplorer.IO;
using System.IO;
using LibEveryFileExplorer.Files;
using System.Drawing;
using System.Windows.Forms;
using LibEveryFileExplorer.Files.SimpleFileSystem;
using GCNWii.UI;
namespace GCNWii
{
public class U8 : FileFormat<U8.U8Identifier>, IViewable
{
public U8(byte[] Data)
{
EndianBinaryReaderEx er = new EndianBinaryReaderEx(new MemoryStream(Data), Endianness.BigEndian);
try
{
Header = new U8Header(er);
er.BaseStream.Position = Header.FileSystemTableOffset;
FileSystemTableEntry root = new FileSystemTableEntry(er);
FileSystemTable = new FileSystemTableEntry[root.DataLength];
FileSystemTable[0] = root;
for (int i = 1; i < root.DataLength; i++) FileSystemTable[i] = new FileSystemTableEntry(er);
FileNameTable = new Dictionary<uint,string>();
uint offs = 0;
for (int i = 0; i < root.DataLength; i++)
{
String s = er.ReadStringNT(Encoding.ASCII);
FileNameTable.Add(offs, s);
offs += (uint)s.Length + 1;
}
er.BaseStream.Position = Header.FileDataOffset;
this.Data = er.ReadBytes((int)(er.BaseStream.Length - Header.FileDataOffset));
}
finally
{
er.Close();
}
}
public Form GetDialog()
{
return new U8Viewer(this);
}
public U8Header Header;
public class U8Header
{
public U8Header(EndianBinaryReaderEx er)
{
er.ReadObject(this);
}
[BinaryByteArraySignature(0x55, 0xAA, 0x38, 0x2D)]
[BinaryFixedSize(4)]
public byte[] Signature;
public UInt32 FileSystemTableOffset;
public UInt32 FileSystemTableLength;
public UInt32 FileDataOffset;
[BinaryFixedSize(16)]
public Byte[] Padding;
}
public FileSystemTableEntry[] FileSystemTable;
public class FileSystemTableEntry
{
public FileSystemTableEntry(EndianBinaryReader er)
{
NameOffset = er.ReadUInt32();
IsFolder = (NameOffset >> 24) == 1;
NameOffset &= 0xFFFFFF;
DataOffset = er.ReadUInt32();
DataLength = er.ReadUInt32();
}
public UInt32 NameOffset;
public Boolean IsFolder;
public UInt32 DataOffset;//Parent Entry Index if folder
public UInt32 DataLength;//Nr Files if folder
}
public Dictionary<UInt32, String> FileNameTable;
public byte[] Data;
public SFSDirectory ToFileSystem()
{
SFSDirectory[] dirs = new SFSDirectory[FileSystemTable.Length];
dirs[1] = new SFSDirectory("/", true);
var curdir = dirs[1];
for (int i = 2; i < FileSystemTable.Length; i++)
{
if (FileSystemTable[i].IsFolder)
{
var folder = new SFSDirectory(FileNameTable[FileSystemTable[i].NameOffset], false);
dirs[i] = folder;
folder.Parent = dirs[FileSystemTable[i].DataOffset];
dirs[FileSystemTable[i].DataOffset].SubDirectories.Add(folder);
curdir = folder;
}
else
{
var file = new SFSFile(-1, FileNameTable[FileSystemTable[i].NameOffset], curdir);
byte[] data = new byte[FileSystemTable[i].DataLength];
Array.Copy(Data, FileSystemTable[i].DataOffset - Header.FileDataOffset, data, 0, FileSystemTable[i].DataLength);
file.Data = data;
curdir.Files.Add(file);
}
}
return dirs[1];
}
public class U8Identifier : FileFormatIdentifier
{
public override string GetCategory()
{
return Category_Archives;
}
public override string GetFileDescription()
{
return "U8 Archive";
}
public override string GetFileFilter()
{
return "U8 Archive (*.arc, *.szs)|*.arc;*.szs";
}
public override Bitmap GetIcon()
{
return null;
}
public override FormatMatch IsFormat(EFEFile File)
{
if (File.Data.Length > 4 && File.Data[0] == 0x55 && File.Data[1] == 0xAA && File.Data[2] == 0x38 && File.Data[3] == 0x2D) return FormatMatch.Content;
return FormatMatch.No;
}
}
}
}

151
GCNWii/UI/U8Viewer.Designer.cs generated Normal file
View File

@ -0,0 +1,151 @@
namespace GCNWii.UI
{
partial class U8Viewer
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(U8Viewer));
this.mainMenu1 = new LibEveryFileExplorer.UI.MainMenu(this.components);
this.menuItem1 = new System.Windows.Forms.MenuItem();
this.menuExport = new System.Windows.Forms.MenuItem();
this.menuItem2 = new System.Windows.Forms.MenuItem();
this.menuItem3 = new System.Windows.Forms.MenuItem();
this.menuExportDir = new System.Windows.Forms.MenuItem();
this.fileBrowser1 = new LibEveryFileExplorer.UI.FileBrowser();
this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
this.contextMenu1 = new System.Windows.Forms.ContextMenu();
this.menuItem4 = new System.Windows.Forms.MenuItem();
this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog();
this.SuspendLayout();
//
// mainMenu1
//
this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.menuItem1,
this.menuItem2});
//
// menuItem1
//
this.menuItem1.Index = 0;
this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.menuExport});
this.menuItem1.MergeOrder = 1;
this.menuItem1.MergeType = System.Windows.Forms.MenuMerge.MergeItems;
this.menuItem1.Text = "Edit";
//
// menuExport
//
this.menuExport.Enabled = false;
this.menuExport.Index = 0;
this.menuExport.Text = "Export...";
this.menuExport.Click += new System.EventHandler(this.OnExport);
//
// menuItem2
//
this.menuItem2.Index = 1;
this.menuItem2.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.menuItem3,
this.menuExportDir});
this.menuItem2.MergeOrder = 3;
this.menuItem2.MergeType = System.Windows.Forms.MenuMerge.MergeItems;
this.menuItem2.Text = "Tools";
//
// menuItem3
//
this.menuItem3.Index = 0;
this.menuItem3.Text = "-";
//
// menuExportDir
//
this.menuExportDir.Index = 1;
this.menuExportDir.Text = "Export Directory Content...";
this.menuExportDir.Click += new System.EventHandler(this.menuExportDir_Click);
//
// fileBrowser1
//
this.fileBrowser1.DeleteEnabled = true;
this.fileBrowser1.Dock = System.Windows.Forms.DockStyle.Fill;
this.fileBrowser1.Location = new System.Drawing.Point(0, 0);
this.fileBrowser1.Name = "fileBrowser1";
this.fileBrowser1.RenameEnabled = true;
this.fileBrowser1.ShowAddDirectoryButton = false;
this.fileBrowser1.ShowAddFileButton = false;
this.fileBrowser1.ShowDeleteButton = false;
this.fileBrowser1.ShowRenameButton = false;
this.fileBrowser1.Size = new System.Drawing.Size(652, 338);
this.fileBrowser1.TabIndex = 0;
this.fileBrowser1.OnDirectoryChanged += new LibEveryFileExplorer.UI.FileBrowser.OnDirectoryChangedEventHandler(this.fileBrowser1_OnDirectoryChanged);
this.fileBrowser1.OnFileActivated += new LibEveryFileExplorer.UI.FileBrowser.OnFileActivatedEventHandler(this.fileBrowser1_OnFileActivated);
this.fileBrowser1.OnSelectionChanged += new System.EventHandler(this.fileBrowser1_OnSelectionChanged);
this.fileBrowser1.OnRightClick += new LibEveryFileExplorer.UI.FileBrowser.OnRightClickEventHandler(this.fileBrowser1_OnRightClick);
//
// contextMenu1
//
this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.menuItem4});
//
// menuItem4
//
this.menuItem4.Index = 0;
this.menuItem4.Text = "Export...";
this.menuItem4.Click += new System.EventHandler(this.OnExport);
//
// folderBrowserDialog1
//
this.folderBrowserDialog1.Description = "Select the directory to export the content of current directory to.";
//
// DARCViewer
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(652, 338);
this.Controls.Add(this.fileBrowser1);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Menu = this.mainMenu1;
this.Name = "DARCViewer";
this.Text = "DARC Viewer";
this.Load += new System.EventHandler(this.SARCViewer_Load);
this.ResumeLayout(false);
}
#endregion
private LibEveryFileExplorer.UI.MainMenu mainMenu1;
private System.Windows.Forms.MenuItem menuItem1;
private System.Windows.Forms.MenuItem menuItem2;
private LibEveryFileExplorer.UI.FileBrowser fileBrowser1;
private System.Windows.Forms.MenuItem menuExport;
private System.Windows.Forms.SaveFileDialog saveFileDialog1;
private System.Windows.Forms.ContextMenu contextMenu1;
private System.Windows.Forms.MenuItem menuItem4;
private System.Windows.Forms.MenuItem menuItem3;
private System.Windows.Forms.MenuItem menuExportDir;
private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog1;
}
}

85
GCNWii/UI/U8Viewer.cs Normal file
View File

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LibEveryFileExplorer.Files.SimpleFileSystem;
using LibEveryFileExplorer.Files;
using LibEveryFileExplorer;
namespace GCNWii.UI
{
public partial class U8Viewer : Form
{
U8 Archive;
SFSDirectory Root;
public U8Viewer(U8 Archive)
{
Root = Archive.ToFileSystem();
InitializeComponent();
}
private void SARCViewer_Load(object sender, EventArgs e)
{
fileBrowser1.UpdateDirectories(Root.GetTreeNodes());
}
private void fileBrowser1_OnDirectoryChanged(string Path)
{
var d = Root.GetDirectoryByPath(Path);
fileBrowser1.UpdateContent(d.GetContent());
}
private void fileBrowser1_OnFileActivated(string Path)
{
var s = Root.GetFileByPath(Path);
EveryFileExplorerUtil.OpenFile(new EFESFSFile(s), ((ViewableFile)Tag).File);
}
private void OnExport(object sender, EventArgs e)
{
var file = Root.GetFileByPath(fileBrowser1.SelectedPath);
if (file == null) return;
saveFileDialog1.Filter = System.IO.Path.GetExtension(fileBrowser1.SelectedPath).Replace(".", "").ToUpper() + " Files (*" + System.IO.Path.GetExtension(fileBrowser1.SelectedPath).ToLower() + ")|*" + System.IO.Path.GetExtension(fileBrowser1.SelectedPath).ToLower() + "|All Files (*.*)|*.*";
saveFileDialog1.FileName = System.IO.Path.GetFileName(fileBrowser1.SelectedPath);
if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK
&& saveFileDialog1.FileName.Length > 0)
{
System.IO.File.Create(saveFileDialog1.FileName).Close();
System.IO.File.WriteAllBytes(saveFileDialog1.FileName, file.Data);
}
}
private void fileBrowser1_OnSelectionChanged(object sender, EventArgs e)
{
menuExport.Enabled = !(fileBrowser1.SelectedPath == fileBrowser1.SelectedFolderPath);
}
private void fileBrowser1_OnRightClick(Point Location)
{
var dir = Root.GetDirectoryByPath(fileBrowser1.SelectedPath);
if (dir != null)
{
}
else
{
//var file = Root.GetFileByPath(fileBrowser1.SelectedPath);
contextMenu1.Show(fileBrowser1, Location);
}
}
private void menuExportDir_Click(object sender, EventArgs e)
{
var dir = Root.GetDirectoryByPath(fileBrowser1.SelectedFolderPath);
if (folderBrowserDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK
&& folderBrowserDialog1.SelectedPath.Length > 0)
{
dir.Export(folderBrowserDialog1.SelectedPath);
}
}
}
}

157
GCNWii/UI/U8Viewer.resx Normal file
View File

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="mainMenu1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="saveFileDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>134, 17</value>
</metadata>
<metadata name="contextMenu1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>270, 17</value>
</metadata>
<metadata name="folderBrowserDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>400, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAADwAAABcAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAA
ABoAAAAXAAAADwAAAB4BM2aeAUSHxQFEh8UBRIfFAUSHxQFEh8UBRIfFAUSHxQFEh8UBRIfFAUSHxQFE
h8UBRIfFATNmngAAAB4AAAAAAUqUuHuu4P96rd//eq3f/3qt3/96rd//eq3f/3qt3/96rd//eq3f/3qt
3/96rd//e67g/wFKlLgAAAAAAAAAAAJRoKuBtOT/fbDh/32w4f99sOH/fbDh/2yf0P9ajb//Wo2//1qN
v/9ajb//Wo2//3Cj0/8CUaCrAAAAAAAAAAACVKSmiLvq/4K15f+CteX/grXl/4K15f9jlsf/4uLR/+Li
0f/i4tH/4uLR/+Li0f9pnMv/AlSkpgAAAAAAAAAAA1aoo4/C7v+Huun/h7rp/4e66f+Huun/cKPT/+zs
2/+6uqn/0NC//83NvP/s7Nv/eKvY/wNWqKMAAAAAAAAAAANYrJ+WyfL/jL/s/4y/7P+Mv+z/RHeq/0J1
qP/19eT/9fXk//X15P/19eT/9fXk/4i75f8DWKyfAAAAAAAAAAADWrCbm872/5HE8P+RxPD/kcTw/1WI
u/9Uh7r//8tD//zFPf/4vTX/87Ut//CuJv+WyfL/A1qwmwAAAAAAAAAAA1uzmJ/S+f+VyPP/lcjz/5XI
8/9ViLv/VYi7/1WIu/9NgLP/lcjz/5XI8/+VyPP/n9L5/wNbs5gAAAAAAAAAAANdtpWn2/79qt3//6rd
//+q3f//d6rd/3eq3f93qt3/ZpnM/6rd//+q3f//qt3//6fb/v0DXbaVAAAAAAAAAAAEX7lta6bf4ICz
5v+As+b/gLPm/06BtP9OgbT/ToG0/0h7rv+As+b/gLPm/4Cz5v9rpt/gBF+5bQAAAAAAAAAABGC8R02U
2cSJvO//iLvu/4i77v9BdKf/QXSn/0F0p/8+caT/iLvu/4i77v+JvO//TZTZxARgvEcAAAAAAAAAAARh
viMqfMylibzv/4i77v+Iu+7/NWib/zVom/81aJv/NWib/4i77v+Iu+7/ibzv/yp8zKUEYb4jAAAAAAAA
AAAEYr8EBGLAaARiwIsEYsCLBGLAiwBAgMwAQIDMAECAzABAgMwEYsCLBGLAiwRiwIsEYsBoBGK/BAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA//8AAAAAAAAAAAAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIAB
AACAAQAA//8AAA==
</value>
</data>
</root>

View File

@ -41,7 +41,7 @@ namespace LegoPirates.UI
//TODO: Calculate timing based on fps
if ((Video.Header.Flags & 4) == 4)
{
AudioConverter = new ADPCM();
AudioConverter = new IMAADPCMDecoder();
AudioBuffer = new NAudio.Wave.BufferedWaveProvider(new NAudio.Wave.WaveFormat((int)Video.Header.AudioRate, 16, 1));
AudioBuffer.DiscardOnBufferOverflow = true;
AudioBuffer.BufferLength = 8192 * 16;
@ -72,7 +72,7 @@ namespace LegoPirates.UI
backgroundWorker1.RunWorkerAsync();
}
ADPCM AudioConverter = null;
IMAADPCMDecoder AudioConverter = null;
int aa = 0;
int bb = 0;

View File

@ -238,7 +238,7 @@ namespace LibEveryFileExplorer.IO
byte[] bsig = GetAttributeValue<byte[]>(f, typeof(BinaryByteArraySignatureAttribute), null);
if (bsig != null && Result is byte[])
{
if (!bsig.Equals(Result)) throw new SignatureNotCorrectException("{ " + BitConverter.ToString((byte[])Result, 0, ((byte[])Result).Length).Replace("-", ", ") + " }", "{ " + BitConverter.ToString(bsig, 0, bsig.Length).Replace("-", ", ") + " }", BaseStream.Position - ((byte[])Result).Length);
if (!bsig.SequenceEqual((byte[])Result)) throw new SignatureNotCorrectException("{ " + BitConverter.ToString((byte[])Result, 0, ((byte[])Result).Length).Replace("-", ", ") + " }", "{ " + BitConverter.ToString(bsig, 0, bsig.Length).Replace("-", ", ") + " }", BaseStream.Position - ((byte[])Result).Length);
}
else
{

Binary file not shown.

View File

@ -78,7 +78,9 @@
<DesignTime>True</DesignTime>
<DependentUpon>Resource.resx</DependentUpon>
</Compile>
<Compile Include="SND\ADPCM.cs" />
<Compile Include="SND\IMAADPCMDecoder.cs" />
<Compile Include="SND\IMAADPCMConst.cs" />
<Compile Include="SND\IMAADPCMEncoder.cs" />
<Compile Include="UI\NDSProjectDialog.cs">
<SubType>Form</SubType>
</Compile>

View File

@ -1,153 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LibEveryFileExplorer.IO;
using LibEveryFileExplorer.Math;
namespace NDS.SND
{
public class ADPCM
{
private static int[] IndexTable =
{
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
};
private static int[] StepTable =
{
7, 8, 9, 10, 11, 12, 13, 14,
16, 17, 19, 21, 23, 25, 28,
31, 34, 37, 41, 45, 50, 55,
60, 66, 73, 80, 88, 97, 107,
118, 130, 143, 157, 173, 190, 209,
230, 253, 279, 307, 337, 371, 408,
449, 494, 544, 598, 658, 724, 796,
876, 963, 1060, 1166, 1282, 1411, 1552,
1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026,
4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630,
9493, 10442, 11487, 12635, 13899, 15289, 16818,
18500, 20350, 22385, 24623, 27086, 29794, 32767
};
private bool IsInit = false;
private int Last;
private int Index;
public ADPCM() { }
public Int16[] GetWaveData(byte[] Data, int Offset, int Length)
{
List<Int16> DataOut = new List<short>();
if (!IsInit)
{
Last = IOUtil.ReadS16LE(Data, Offset);
Index = IOUtil.ReadS16LE(Data, Offset + 2) & 0x7F;
Offset += 4;
Length -= 4;
DataOut.Add((short)Last);
IsInit = true;
}
int end = Offset + Length;
while (Offset < end)
{
byte sampd = Data[Offset++];
for (int i = 0; i < 2; i++)
{
int val = (sampd >> (i * 4)) & 0xF;
int diff =
StepTable[Index] / 8 +
StepTable[Index] / 4 * ((val >> 0) & 1) +
StepTable[Index] / 2 * ((val >> 1) & 1) +
StepTable[Index] * ((val >> 2) & 1);
int samp = Last + diff * ((((val >> 3) & 1) == 1) ? -1 : 1);
Last = (short)MathUtil.Clamp(samp, short.MinValue, short.MaxValue);
Index = (short)MathUtil.Clamp(Index + IndexTable[val & 7], 0, 88);
DataOut.Add((short)Last);
}
}
return DataOut.ToArray();
}
public static byte[] Encode(Int16[] WaveData)
{
int Last = WaveData[0];
int Index = GetBestTableIndex((WaveData[1] - WaveData[0]) * 8);
int HeaderIndex = Index;
byte[] Nibbles = new byte[WaveData.Length - 1];//nibbles, lets merge it afterwards
for (int i = 1; i < WaveData.Length; i++)
{
int val = GetBestConfig(Index, WaveData[i] - Last);
Nibbles[i - 1] = (byte)val;
int diff =
StepTable[Index] / 8 +
StepTable[Index] / 4 * ((val >> 0) & 1) +
StepTable[Index] / 2 * ((val >> 1) & 1) +
StepTable[Index] * ((val >> 2) & 1);
int samp = Last + diff * ((((val >> 3) & 1) == 1) ? -1 : 1);
Last = (short)MathUtil.Clamp(samp, short.MinValue, short.MaxValue);
Index = (short)MathUtil.Clamp(Index + IndexTable[val & 7], 0, 88);
}
byte[] Result = new byte[WaveData.Length / 2 + 4];
IOUtil.WriteS16LE(Result, 0, WaveData[0]);
IOUtil.WriteS16LE(Result, 2, (short)HeaderIndex);
for (int i = 0; i < Nibbles.Length; i += 2)
{
if (i == Nibbles.Length - 1)
{
Result[i / 2 + 4] = (byte)(Nibbles[i]);//(Nibbles[i + 1] << 4));
}
else Result[i / 2 + 4] = (byte)(Nibbles[i] | (Nibbles[i + 1] << 4));
}
return Result;
}
private static int GetBestTableIndex(int Diff)
{
int LowestDiff = int.MaxValue;
int LowestIdx = -1;
for (int i = 0; i < StepTable.Length; i++)
{
int diff2 = Math.Abs(Math.Abs(Diff) - StepTable[i]);
if (diff2 < LowestDiff)
{
LowestDiff = diff2;
LowestIdx = i;
}
}
return LowestIdx;
}
private static int GetBestConfig(int Index, int Diff)
{
int Result = 0;
if (Diff < 0) Result |= 1 << 3;
Diff = Math.Abs(Diff);
int DiffNew = StepTable[Index] / 8;
if (Math.Abs(DiffNew - Diff) >= StepTable[Index])
{
Result |= 1 << 2;
DiffNew += StepTable[Index];
}
if (Math.Abs(DiffNew - Diff) >= StepTable[Index] / 2)
{
Result |= 1 << 1;
DiffNew += StepTable[Index] / 2;
}
if (Math.Abs(DiffNew - Diff) >= StepTable[Index] / 4)
{
Result |= 1;
DiffNew += StepTable[Index] / 4;
}
return Result;
}
}
}

32
NDS/SND/IMAADPCMConst.cs Normal file
View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NDS.SND
{
public class IMAADPCMConst
{
public static readonly int[] IndexTable =
{
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
};
public static readonly int[] StepTable =
{
7, 8, 9, 10, 11, 12, 13, 14,
16, 17, 19, 21, 23, 25, 28,
31, 34, 37, 41, 45, 50, 55,
60, 66, 73, 80, 88, 97, 107,
118, 130, 143, 157, 173, 190, 209,
230, 253, 279, 307, 337, 371, 408,
449, 494, 544, 598, 658, 724, 796,
876, 963, 1060, 1166, 1282, 1411, 1552,
1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026,
4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630,
9493, 10442, 11487, 12635, 13899, 15289, 16818,
18500, 20350, 22385, 24623, 27086, 29794, 32767
};
}
}

View File

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LibEveryFileExplorer.IO;
using LibEveryFileExplorer.Math;
namespace NDS.SND
{
public class IMAADPCMDecoder
{
private bool IsInit = false;
private int Last;
private int Index;
public IMAADPCMDecoder() { }
public Int16[] GetWaveData(byte[] Data, int Offset, int Length)
{
List<Int16> DataOut = new List<short>();
if (!IsInit)
{
Last = IOUtil.ReadS16LE(Data, Offset);
Index = IOUtil.ReadS16LE(Data, Offset + 2) & 0x7F;
Offset += 4;
Length -= 4;
DataOut.Add((short)Last);
IsInit = true;
}
int end = Offset + Length;
while (Offset < end)
{
byte sampd = Data[Offset++];
for (int i = 0; i < 2; i++)
{
int val = (sampd >> (i * 4)) & 0xF;
int diff =
IMAADPCMConst.StepTable[Index] / 8 +
IMAADPCMConst.StepTable[Index] / 4 * ((val >> 0) & 1) +
IMAADPCMConst.StepTable[Index] / 2 * ((val >> 1) & 1) +
IMAADPCMConst.StepTable[Index] * ((val >> 2) & 1);
int samp = Last + diff * ((((val >> 3) & 1) == 1) ? -1 : 1);
Last = (short)MathUtil.Clamp(samp, short.MinValue, short.MaxValue);
Index = (short)MathUtil.Clamp(Index + IMAADPCMConst.IndexTable[val & 7], 0, 88);
DataOut.Add((short)Last);
}
}
return DataOut.ToArray();
}
}
}

103
NDS/SND/IMAADPCMEncoder.cs Normal file
View File

@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LibEveryFileExplorer.IO;
using LibEveryFileExplorer.Math;
namespace NDS.SND
{
public class IMAADPCMEncoder
{
public IMAADPCMEncoder() { }
private bool IsInit = false;
private int Last;
private int Index;
public byte[] Encode(Int16[] WaveData)
{
List<byte> Result = new List<byte>();
int Offset = 0;
if (!IsInit)
{
Last = WaveData[0];
Index = GetBestTableIndex((WaveData[1] - WaveData[0]) * 8);
byte[] Header = new byte[4];
IOUtil.WriteS16LE(Header, 0, WaveData[0]);
IOUtil.WriteS16LE(Header, 2, (short)Index);
Result.AddRange(Header);
Offset++;
IsInit = true;
}
byte[] Nibbles = new byte[WaveData.Length - Offset];//nibbles, lets merge it afterwards
for (int i = Offset; i < WaveData.Length; i++)
{
int val = GetBestConfig(Index, WaveData[i] - Last);
Nibbles[i - Offset] = (byte)val;
int diff =
IMAADPCMConst.StepTable[Index] / 8 +
IMAADPCMConst.StepTable[Index] / 4 * ((val >> 0) & 1) +
IMAADPCMConst.StepTable[Index] / 2 * ((val >> 1) & 1) +
IMAADPCMConst.StepTable[Index] * ((val >> 2) & 1);
int samp = Last + diff * ((((val >> 3) & 1) == 1) ? -1 : 1);
Last = (short)MathUtil.Clamp(samp, short.MinValue, short.MaxValue);
Index = (short)MathUtil.Clamp(Index + IMAADPCMConst.IndexTable[val & 7], 0, 88);
}
for (int i = 0; i < Nibbles.Length; i += 2)
{
if (i == Nibbles.Length - 1)
{
Result.Add((byte)(Nibbles[i]));
}
else Result.Add((byte)(Nibbles[i] | (Nibbles[i + 1] << 4)));
}
return Result.ToArray();
}
private int GetBestTableIndex(int Diff)
{
int LowestDiff = int.MaxValue;
int LowestIdx = -1;
for (int i = 0; i < IMAADPCMConst.StepTable.Length; i++)
{
int diff2 = Math.Abs(Math.Abs(Diff) - IMAADPCMConst.StepTable[i]);
if (diff2 < LowestDiff)
{
LowestDiff = diff2;
LowestIdx = i;
}
}
return LowestIdx;
}
private int GetBestConfig(int Index, int Diff)
{
int Result = 0;
if (Diff < 0) Result |= 1 << 3;
Diff = Math.Abs(Diff);
int DiffNew = IMAADPCMConst.StepTable[Index] / 8;
if (Math.Abs(DiffNew - Diff) >= IMAADPCMConst.StepTable[Index])
{
Result |= 1 << 2;
DiffNew += IMAADPCMConst.StepTable[Index];
}
if (Math.Abs(DiffNew - Diff) >= IMAADPCMConst.StepTable[Index] / 2)
{
Result |= 1 << 1;
DiffNew += IMAADPCMConst.StepTable[Index] / 2;
}
if (Math.Abs(DiffNew - Diff) >= IMAADPCMConst.StepTable[Index] / 4)
{
Result |= 1;
DiffNew += IMAADPCMConst.StepTable[Index] / 4;
}
return Result;
}
}
}