mirror of
https://github.com/Gericom/EveryFileExplorer.git
synced 2025-06-19 01:15:36 -04:00
Added ARM9 Decompression and more
ARM9 decompression is done by executing the rom until the point it is decompressed. This means that it should work with all compressed games. - Removed Property Grid from FileBrowser - Added ARM9 extraction and decompression to the NDS Viewer
This commit is contained in:
parent
9e1f095d4d
commit
fec7c83b09
@ -65,16 +65,12 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<EmbeddedResource Include="Form1.resx">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
|
71
EveryFileExplorer/Properties/Resources.Designer.cs
generated
71
EveryFileExplorer/Properties/Resources.Designer.cs
generated
@ -1,71 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.18063
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace EveryFileExplorer.Properties
|
||||
{
|
||||
|
||||
|
||||
/// <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 ((resourceMan == null))
|
||||
{
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EveryFileExplorer.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,6 +117,7 @@
|
||||
<EmbeddedResource Include="Resource.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resource.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="UI\FileBrowser.resx">
|
||||
<DependentUpon>FileBrowser.cs</DependentUpon>
|
||||
|
108
LibEveryFileExplorer/UI/FileBrowser.Designer.cs
generated
108
LibEveryFileExplorer/UI/FileBrowser.Designer.cs
generated
@ -31,10 +31,6 @@
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FileBrowser));
|
||||
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
|
||||
this.treeView1 = new System.Windows.Forms.TreeView();
|
||||
this.splitContainer2 = new System.Windows.Forms.SplitContainer();
|
||||
this.listView1 = new LibEveryFileExplorer.UI.ListViewNF();
|
||||
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
|
||||
this.buttonDirAdd = new System.Windows.Forms.ToolStripButton();
|
||||
this.buttonFileAdd = new System.Windows.Forms.ToolStripButton();
|
||||
@ -42,15 +38,13 @@
|
||||
this.buttonDelete = new System.Windows.Forms.ToolStripButton();
|
||||
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.buttonRename = new System.Windows.Forms.ToolStripButton();
|
||||
this.propertyGrid1 = new System.Windows.Forms.PropertyGrid();
|
||||
this.listView1 = new LibEveryFileExplorer.UI.ListViewNF();
|
||||
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
|
||||
this.splitContainer1.Panel1.SuspendLayout();
|
||||
this.splitContainer1.Panel2.SuspendLayout();
|
||||
this.splitContainer1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit();
|
||||
this.splitContainer2.Panel1.SuspendLayout();
|
||||
this.splitContainer2.Panel2.SuspendLayout();
|
||||
this.splitContainer2.SuspendLayout();
|
||||
this.toolStrip1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
@ -67,7 +61,8 @@
|
||||
//
|
||||
// splitContainer1.Panel2
|
||||
//
|
||||
this.splitContainer1.Panel2.Controls.Add(this.splitContainer2);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.listView1);
|
||||
this.splitContainer1.Panel2.Controls.Add(this.toolStrip1);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(700, 391);
|
||||
this.splitContainer1.SplitterDistance = 175;
|
||||
this.splitContainer1.TabIndex = 0;
|
||||
@ -86,51 +81,6 @@
|
||||
this.treeView1.TabIndex = 0;
|
||||
this.treeView1.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterSelect);
|
||||
//
|
||||
// splitContainer2
|
||||
//
|
||||
this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer2.FixedPanel = System.Windows.Forms.FixedPanel.Panel2;
|
||||
this.splitContainer2.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer2.Name = "splitContainer2";
|
||||
//
|
||||
// splitContainer2.Panel1
|
||||
//
|
||||
this.splitContainer2.Panel1.Controls.Add(this.listView1);
|
||||
this.splitContainer2.Panel1.Controls.Add(this.toolStrip1);
|
||||
//
|
||||
// splitContainer2.Panel2
|
||||
//
|
||||
this.splitContainer2.Panel2.Controls.Add(this.propertyGrid1);
|
||||
this.splitContainer2.Size = new System.Drawing.Size(521, 391);
|
||||
this.splitContainer2.SplitterDistance = 346;
|
||||
this.splitContainer2.TabIndex = 0;
|
||||
//
|
||||
// listView1
|
||||
//
|
||||
this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||
this.columnHeader1,
|
||||
this.columnHeader2});
|
||||
this.listView1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.listView1.Location = new System.Drawing.Point(0, 25);
|
||||
this.listView1.MultiSelect = false;
|
||||
this.listView1.Name = "listView1";
|
||||
this.listView1.Size = new System.Drawing.Size(346, 366);
|
||||
this.listView1.TabIndex = 0;
|
||||
this.listView1.TileSize = new System.Drawing.Size(168, 36);
|
||||
this.listView1.UseCompatibleStateImageBehavior = false;
|
||||
this.listView1.View = System.Windows.Forms.View.Tile;
|
||||
this.listView1.ItemActivate += new System.EventHandler(this.listView1_ItemActivate);
|
||||
this.listView1.SelectedIndexChanged += new System.EventHandler(this.listView1_SelectedIndexChanged);
|
||||
this.listView1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.listView1_MouseClick);
|
||||
//
|
||||
// columnHeader1
|
||||
//
|
||||
this.columnHeader1.Text = "Name";
|
||||
//
|
||||
// columnHeader2
|
||||
//
|
||||
this.columnHeader2.Text = "Size";
|
||||
//
|
||||
// toolStrip1
|
||||
//
|
||||
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
@ -142,7 +92,7 @@
|
||||
this.buttonRename});
|
||||
this.toolStrip1.Location = new System.Drawing.Point(0, 0);
|
||||
this.toolStrip1.Name = "toolStrip1";
|
||||
this.toolStrip1.Size = new System.Drawing.Size(346, 25);
|
||||
this.toolStrip1.Size = new System.Drawing.Size(521, 25);
|
||||
this.toolStrip1.TabIndex = 1;
|
||||
this.toolStrip1.Text = "toolStrip1";
|
||||
//
|
||||
@ -196,13 +146,31 @@
|
||||
this.buttonRename.Text = "Rename";
|
||||
this.buttonRename.Click += new System.EventHandler(this.buttonRename_Click);
|
||||
//
|
||||
// propertyGrid1
|
||||
// listView1
|
||||
//
|
||||
this.propertyGrid1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.propertyGrid1.Location = new System.Drawing.Point(0, 0);
|
||||
this.propertyGrid1.Name = "propertyGrid1";
|
||||
this.propertyGrid1.Size = new System.Drawing.Size(171, 391);
|
||||
this.propertyGrid1.TabIndex = 0;
|
||||
this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||
this.columnHeader1,
|
||||
this.columnHeader2});
|
||||
this.listView1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.listView1.Location = new System.Drawing.Point(0, 25);
|
||||
this.listView1.MultiSelect = false;
|
||||
this.listView1.Name = "listView1";
|
||||
this.listView1.Size = new System.Drawing.Size(521, 366);
|
||||
this.listView1.TabIndex = 0;
|
||||
this.listView1.TileSize = new System.Drawing.Size(168, 36);
|
||||
this.listView1.UseCompatibleStateImageBehavior = false;
|
||||
this.listView1.View = System.Windows.Forms.View.Tile;
|
||||
this.listView1.ItemActivate += new System.EventHandler(this.listView1_ItemActivate);
|
||||
this.listView1.SelectedIndexChanged += new System.EventHandler(this.listView1_SelectedIndexChanged);
|
||||
this.listView1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.listView1_MouseClick);
|
||||
//
|
||||
// columnHeader1
|
||||
//
|
||||
this.columnHeader1.Text = "Name";
|
||||
//
|
||||
// columnHeader2
|
||||
//
|
||||
this.columnHeader2.Text = "Size";
|
||||
//
|
||||
// FileBrowser
|
||||
//
|
||||
@ -214,13 +182,9 @@
|
||||
this.Load += new System.EventHandler(this.FileBrowser_Load);
|
||||
this.splitContainer1.Panel1.ResumeLayout(false);
|
||||
this.splitContainer1.Panel2.ResumeLayout(false);
|
||||
this.splitContainer1.Panel2.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
|
||||
this.splitContainer1.ResumeLayout(false);
|
||||
this.splitContainer2.Panel1.ResumeLayout(false);
|
||||
this.splitContainer2.Panel1.PerformLayout();
|
||||
this.splitContainer2.Panel2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit();
|
||||
this.splitContainer2.ResumeLayout(false);
|
||||
this.toolStrip1.ResumeLayout(false);
|
||||
this.toolStrip1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
@ -231,17 +195,15 @@
|
||||
|
||||
private System.Windows.Forms.SplitContainer splitContainer1;
|
||||
private System.Windows.Forms.TreeView treeView1;
|
||||
private System.Windows.Forms.SplitContainer splitContainer2;
|
||||
private ListViewNF listView1;
|
||||
private System.Windows.Forms.PropertyGrid propertyGrid1;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader1;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader2;
|
||||
private System.Windows.Forms.ToolStrip toolStrip1;
|
||||
private System.Windows.Forms.ToolStripButton buttonDirAdd;
|
||||
private System.Windows.Forms.ToolStripButton buttonFileAdd;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
|
||||
private System.Windows.Forms.ToolStripButton buttonDelete;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
|
||||
private System.Windows.Forms.ToolStripButton buttonRename;
|
||||
private System.Windows.Forms.ToolStripButton buttonDelete;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader1;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader2;
|
||||
}
|
||||
}
|
||||
|
433
NDS/CPU/ARM9.cs
Normal file
433
NDS/CPU/ARM9.cs
Normal file
@ -0,0 +1,433 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using LibEveryFileExplorer.IO;
|
||||
|
||||
namespace NDS.CPU
|
||||
{
|
||||
public class ARM9
|
||||
{
|
||||
public static byte[] Decompress(byte[] Compressed, uint RamAddress, uint EntryAddress, uint AutoloadDone)
|
||||
{
|
||||
ARM9Context c = new ARM9Context();
|
||||
c.Registers[15] = EntryAddress;
|
||||
Array.Copy(Compressed, 0, c.Memory, RamAddress, Compressed.Length);
|
||||
uint stopaddress;
|
||||
while (true)
|
||||
{
|
||||
ExecuteInstruction(c);
|
||||
if (c.Registers[15] == AutoloadDone)
|
||||
{
|
||||
//Now we know the address of do_autoload + 4, which is MIi_UncompressBackward + 8
|
||||
stopaddress = c.Registers[14] - 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
c = new ARM9Context();
|
||||
c.Registers[15] = EntryAddress;
|
||||
Array.Copy(Compressed, 0, c.Memory, RamAddress, Compressed.Length);
|
||||
uint length = 0;
|
||||
uint compoffsaddr = 0;
|
||||
while (true)
|
||||
{
|
||||
ExecuteInstruction(c);
|
||||
if (c.Registers[15] == stopaddress - 4)
|
||||
{
|
||||
//look if the file is compressed (R0 = 0 means the data is not compressed!)
|
||||
if (c.Registers[0] == 0) return Compressed;
|
||||
length = c.Registers[0] + IOUtil.ReadU32LE(c.Memory, (int)c.Registers[0] - 4) - RamAddress;
|
||||
compoffsaddr = c.Registers[1] + 0x14 - RamAddress;
|
||||
}
|
||||
//we're done decompressing!
|
||||
if (c.Registers[15] == stopaddress) break;
|
||||
}
|
||||
byte[] result = new byte[length];
|
||||
Array.Copy(c.Memory, RamAddress, result, 0, length);
|
||||
IOUtil.WriteU32LE(result, (int)compoffsaddr, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
private class ARM9Context
|
||||
{
|
||||
public uint[] Registers = new uint[16];
|
||||
public byte[] Memory = new byte[0x8000000];
|
||||
public bool C;
|
||||
public bool N;
|
||||
public bool V;
|
||||
public bool Z;
|
||||
}
|
||||
|
||||
private static void ExecuteInstruction(ARM9Context c)
|
||||
{
|
||||
uint inst = IOUtil.ReadU32LE(c.Memory, (int)c.Registers[15]);
|
||||
uint condition = inst >> 28;
|
||||
if (EvaluateCondition(c, condition))
|
||||
{
|
||||
switch ((inst >> 25) & 7)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
DataProc(c, inst);
|
||||
c.Registers[15] += 4;
|
||||
break;
|
||||
case 0x2:
|
||||
case 0x3:
|
||||
SingleDataTrans(c, inst);
|
||||
c.Registers[15] += 4;
|
||||
break;
|
||||
case 0x4:
|
||||
BlockDataTrans(c, inst);
|
||||
c.Registers[15] += 4;
|
||||
break;
|
||||
case 0x5://101
|
||||
Branch(c, inst);
|
||||
break;
|
||||
case 0x7:
|
||||
c.Registers[15] += 4;
|
||||
break;//ignore mcr, mrc and that kind of crap
|
||||
default:
|
||||
c.Registers[15] += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else c.Registers[15] += 4;
|
||||
}
|
||||
|
||||
private static UInt32 Shift(UInt32 ShiftType, UInt32 Value, UInt32 NrBits, ref bool Carry)
|
||||
{
|
||||
switch (ShiftType)
|
||||
{
|
||||
case 0:
|
||||
if (NrBits > 0) Carry = ((Value >> (32 - (int)NrBits)) & 1) == 1;
|
||||
return Value << (int)NrBits;
|
||||
case 1:
|
||||
if (NrBits > 0) Carry = ((Value >> ((int)NrBits - 1)) & 1) == 1;
|
||||
else Carry = ((Value >> 31) & 1) == 1;
|
||||
return Value >> (int)NrBits;
|
||||
case 2:
|
||||
if (NrBits > 0)
|
||||
{
|
||||
Carry = ((Value >> ((int)NrBits - 1)) & 1) == 1;
|
||||
return (uint)(((int)Value) >> (int)NrBits);
|
||||
}
|
||||
else
|
||||
{
|
||||
Carry = ((Value >> 31) & 1) == 1;
|
||||
return ((Value >> 31) & 1) * 0xFFFFFFFF;
|
||||
}
|
||||
case 3:
|
||||
if (NrBits > 0)
|
||||
{
|
||||
Carry = ((Value >> ((int)NrBits - 1)) & 1) == 1;
|
||||
return (Value >> (int)NrBits) | (Value << (32 - (int)NrBits));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint tmp = ((Carry ? 1u : 0u) << 31) | (Value >> 1);
|
||||
Carry = (Value & 1) == 1;
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
private static void DataProc(ARM9Context c, uint Instruction)
|
||||
{
|
||||
uint result = 0;
|
||||
uint Rn;
|
||||
if ((Instruction & 0x0FFFFF00) == 0x12FFF00)//bx, blx
|
||||
{
|
||||
uint op = (Instruction >> 4) & 0xF;
|
||||
Rn = Instruction & 0xF;
|
||||
if (op == 1)
|
||||
{
|
||||
c.Registers[15] = c.Registers[Rn] - 4;
|
||||
}
|
||||
else if (op == 3)
|
||||
{
|
||||
c.Registers[14] = c.Registers[15] + 4;
|
||||
c.Registers[15] = c.Registers[Rn] - 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
//shouldn't happen!
|
||||
}
|
||||
return;
|
||||
}
|
||||
bool Shift_C = c.C;
|
||||
|
||||
bool I = ((Instruction >> 25) & 1) == 1;
|
||||
uint Opcode = (Instruction >> 21) & 0xF;
|
||||
bool S = ((Instruction >> 20) & 1) == 1;
|
||||
Rn = (Instruction >> 16) & 0xF;
|
||||
uint Rd = (Instruction >> 12) & 0xF;
|
||||
uint Op2 = 0;
|
||||
if (I)
|
||||
{
|
||||
uint Is = (Instruction >> 8) & 0xF;
|
||||
uint nn = Instruction & 0xFF;
|
||||
|
||||
Op2 = (nn >> (int)(Is * 2)) | (nn << (32 - (int)(Is * 2)));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint ShiftType = (Instruction >> 5) & 0x3;
|
||||
bool R = ((Instruction >> 4) & 1) == 1;
|
||||
uint Rm = Instruction & 0xF;
|
||||
|
||||
if (!R)
|
||||
{
|
||||
uint Is = (Instruction >> 7) & 0x1F;
|
||||
Op2 = Shift(ShiftType, c.Registers[Rm], Is, ref Shift_C);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint Rs = (Instruction >> 8) & 0xF;
|
||||
uint Reserved = (Instruction >> 7) & 1;
|
||||
Op2 = Shift(ShiftType, c.Registers[Rm], c.Registers[Rs] & 0xFF, ref Shift_C);
|
||||
}
|
||||
}
|
||||
|
||||
switch (Opcode)
|
||||
{
|
||||
case 0x2://sub
|
||||
result = c.Registers[Rd] = c.Registers[Rn] - Op2;
|
||||
break;
|
||||
case 0x4://add
|
||||
result = c.Registers[Rd] = c.Registers[Rn] + Op2;
|
||||
break;
|
||||
case 0x8:
|
||||
if (S == false)//MRS
|
||||
{
|
||||
break;
|
||||
}
|
||||
else//TST
|
||||
{
|
||||
result = c.Registers[Rn] & Op2;
|
||||
}
|
||||
break;
|
||||
case 0x9:
|
||||
if (S == false)//MSR
|
||||
{
|
||||
break;
|
||||
}
|
||||
else//TEQ
|
||||
{
|
||||
result = c.Registers[Rn] ^ Op2;
|
||||
}
|
||||
break;
|
||||
case 0xA://compare
|
||||
result = c.Registers[Rn] - Op2;
|
||||
break;
|
||||
case 0xC://OR logical
|
||||
result = c.Registers[Rd] = c.Registers[Rn] | Op2;
|
||||
break;
|
||||
case 0xD://move
|
||||
result = c.Registers[Rd] = Op2;
|
||||
break;
|
||||
case 0xE://bit clear
|
||||
result = c.Registers[Rd] = c.Registers[Rn] & ~Op2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (S)
|
||||
{
|
||||
bool V = c.V;//tmp
|
||||
bool C = c.C;//tmp
|
||||
bool Z = result == 0;
|
||||
bool N = (result >> 31) == 1;
|
||||
if (Rd != 15)
|
||||
{
|
||||
switch (Opcode)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 8:
|
||||
case 9:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
C = Shift_C;
|
||||
break;
|
||||
//case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
//case 10:
|
||||
case 11:
|
||||
C = !(Op2 > c.Registers[Rn]);
|
||||
break;
|
||||
case 0x2:
|
||||
case 0xA:
|
||||
C = !(Op2 > c.Registers[Rn]);
|
||||
V = ((c.Registers[Rn] < 0 && Op2 >= 0) || (c.Registers[Rn] >= 0 && Op2 < 0)) && ((c.Registers[Rn] < 0 && result >= 0) || (c.Registers[Rn] >= 0 && result < 0));
|
||||
break;
|
||||
}
|
||||
c.C = C;
|
||||
c.N = N;
|
||||
c.V = V;
|
||||
c.Z = Z;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void SingleDataTrans(ARM9Context c, UInt32 Instruction)
|
||||
{
|
||||
bool I = ((Instruction >> 25) & 1) == 1;
|
||||
bool P = ((Instruction >> 24) & 1) == 1;
|
||||
bool U = ((Instruction >> 23) & 1) == 1;
|
||||
bool B = ((Instruction >> 22) & 1) == 1;
|
||||
|
||||
bool T = false;
|
||||
bool W = false;
|
||||
|
||||
if (P) W = ((Instruction >> 21) & 1) == 1;
|
||||
else T = ((Instruction >> 21) & 1) == 1;
|
||||
|
||||
bool L = ((Instruction >> 20) & 1) == 1;
|
||||
|
||||
uint Rn = (Instruction >> 16) & 0xF;
|
||||
uint Rd = (Instruction >> 12) & 0xF;
|
||||
|
||||
uint Offset;
|
||||
if (I)
|
||||
{
|
||||
uint Is = (Instruction >> 7) & 0x1F;
|
||||
uint ShiftType = (Instruction >> 5) & 0x3;
|
||||
uint Reserved = (Instruction >> 4) & 1;
|
||||
uint Rm = Instruction & 0xF;
|
||||
bool Shift_C = c.C;
|
||||
Offset = Shift(ShiftType, c.Registers[Rm], Is, ref Shift_C);
|
||||
}
|
||||
else
|
||||
{
|
||||
Offset = Instruction & 0xFFF;
|
||||
}
|
||||
|
||||
uint MemoryOffset = c.Registers[Rn];
|
||||
if (Rn == 15) MemoryOffset += 8;
|
||||
if (P)
|
||||
{
|
||||
if (U) MemoryOffset += Offset;
|
||||
else MemoryOffset -= Offset;
|
||||
if (W) c.Registers[Rn] = MemoryOffset;
|
||||
}
|
||||
if (L)
|
||||
{
|
||||
if (B)
|
||||
{
|
||||
try
|
||||
{
|
||||
c.Registers[Rd] = c.Memory[MemoryOffset];
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
else c.Registers[Rd] = IOUtil.ReadU32LE(c.Memory, (int)MemoryOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Rd == 15)
|
||||
{
|
||||
if (B) c.Memory[MemoryOffset] = (byte)((c.Registers[Rd] + 12) & 0xFF);
|
||||
else Array.Copy(BitConverter.GetBytes(c.Registers[Rd] + 12), 0, c.Memory, MemoryOffset, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (B) c.Memory[MemoryOffset] = (byte)(c.Registers[Rd] & 0xFF);
|
||||
else Array.Copy(BitConverter.GetBytes(c.Registers[Rd]), 0, c.Memory, MemoryOffset, 4);
|
||||
}
|
||||
}
|
||||
if (!P)
|
||||
{
|
||||
if (U) MemoryOffset += Offset;
|
||||
else MemoryOffset -= Offset;
|
||||
c.Registers[Rn] = MemoryOffset;
|
||||
}
|
||||
}
|
||||
|
||||
private static void BlockDataTrans(ARM9Context c, UInt32 Instruction)
|
||||
{
|
||||
bool P = ((Instruction >> 24) & 1) == 1;
|
||||
bool U = ((Instruction >> 23) & 1) == 1;
|
||||
bool S = ((Instruction >> 22) & 1) == 1;
|
||||
bool W = ((Instruction >> 21) & 1) == 1;
|
||||
bool L = ((Instruction >> 20) & 1) == 1;
|
||||
uint Rn = (Instruction >> 16) & 0xF;
|
||||
uint RList = Instruction & 0xFFFF;
|
||||
|
||||
if (!U && ((RList >> 15) & 1) == 1)
|
||||
{
|
||||
//TODO!
|
||||
}
|
||||
|
||||
uint offs = c.Registers[Rn];
|
||||
for (int i = 0; i < 15; i++)
|
||||
{
|
||||
int reg;
|
||||
if (U) reg = i;
|
||||
else reg = 14 - i;
|
||||
if (((RList >> reg) & 1) == 1)
|
||||
{
|
||||
if (P)
|
||||
{
|
||||
if (U) offs += 4;
|
||||
else offs -= 4;
|
||||
}
|
||||
if (L) c.Registers[reg] = IOUtil.ReadU32LE(c.Memory, (int)offs);
|
||||
else IOUtil.WriteU32LE(c.Memory, (int)offs, c.Registers[reg]);
|
||||
if (!P)
|
||||
{
|
||||
if (U) offs += 4;
|
||||
else offs -= 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (U && ((RList >> 15) & 1) == 1)
|
||||
{
|
||||
//TODO!
|
||||
}
|
||||
if (W) c.Registers[Rn] = offs;
|
||||
}
|
||||
|
||||
private static void Branch(ARM9Context c, UInt32 Instruction)
|
||||
{
|
||||
uint Opcode = (Instruction >> 24) & 1;
|
||||
int nn = (int)((Instruction & 0xFFFFFF) << 8) >> 8;
|
||||
if (Opcode == 1)
|
||||
c.Registers[14] = c.Registers[15] + 4;
|
||||
c.Registers[15] = (uint)((int)c.Registers[15] + 8 + nn * 4);
|
||||
}
|
||||
|
||||
private static bool EvaluateCondition(ARM9Context c, uint condition)
|
||||
{
|
||||
switch (condition)
|
||||
{
|
||||
case 0x0: return c.Z == true;
|
||||
case 0x1: return c.Z == false;
|
||||
case 0x2: return c.C == true;
|
||||
case 0x3: return c.C == false;
|
||||
case 0x4: return c.N == true;
|
||||
case 0x5: return c.N == false;
|
||||
case 0x6: return c.V == true;
|
||||
case 0x7: return c.V == false;
|
||||
case 0x8: return c.C == true && c.Z == false;
|
||||
case 0x9: return c.C == false || c.Z == true;
|
||||
case 0xA: return c.N == c.V;
|
||||
case 0xB: return c.N != c.V;
|
||||
case 0xC: return c.Z == false && c.N == c.V;
|
||||
case 0xD: return c.Z == true || c.N != c.V;
|
||||
case 0xE: return true;
|
||||
case 0xF: return false;
|
||||
}
|
||||
//shouldn't happen!
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
109
NDS/CPU/ASMHackInfo.cs
Normal file
109
NDS/CPU/ASMHackInfo.cs
Normal file
@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
using System.IO;
|
||||
|
||||
namespace NDS.CPU
|
||||
{
|
||||
[Serializable]
|
||||
[XmlRoot("ASMHack")]
|
||||
public class ASMHackInfo
|
||||
{
|
||||
public ASMHackInfo() { }
|
||||
public ASMHackInfo(NDS Rom, UInt32 AreaLo)
|
||||
{
|
||||
AddressInfo.RamAddress = Rom.Header.MainRamAddress;
|
||||
AddressInfo.EntryAddress = Rom.Header.MainEntryAddress;
|
||||
AddressInfo.AutoloadDoneAddress = Rom.Header.MainAutoloadDone;
|
||||
AddressInfo.ArenaLo = AreaLo;
|
||||
//Default:
|
||||
InPath = "arm9.bin";
|
||||
OutPath = "arm9_new.bin";
|
||||
}
|
||||
|
||||
[XmlElement("Addresses")]
|
||||
public Addresses AddressInfo = new Addresses();
|
||||
public class Addresses : IXmlSerializable
|
||||
{
|
||||
public UInt32 RamAddress;
|
||||
public UInt32 EntryAddress;
|
||||
public UInt32 AutoloadDoneAddress;
|
||||
public UInt32 ArenaLo;
|
||||
|
||||
public System.Xml.Schema.XmlSchema GetSchema()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void ReadXml(System.Xml.XmlReader reader)
|
||||
{
|
||||
reader.ReadStartElement("RamAddress");
|
||||
{
|
||||
RamAddress = uint.Parse(reader.ReadString().Replace("0x", ""), System.Globalization.NumberStyles.HexNumber);
|
||||
}
|
||||
reader.ReadEndElement();
|
||||
reader.ReadStartElement("EntryAddress");
|
||||
{
|
||||
EntryAddress = uint.Parse(reader.ReadString().Replace("0x", ""), System.Globalization.NumberStyles.HexNumber);
|
||||
}
|
||||
reader.ReadEndElement();
|
||||
reader.ReadStartElement("AutoloadDoneAddress");
|
||||
{
|
||||
AutoloadDoneAddress = uint.Parse(reader.ReadString().Replace("0x", ""), System.Globalization.NumberStyles.HexNumber);
|
||||
}
|
||||
reader.ReadEndElement();
|
||||
reader.ReadStartElement("ArenaLo");
|
||||
{
|
||||
ArenaLo = uint.Parse(reader.ReadString().Replace("0x", ""), System.Globalization.NumberStyles.HexNumber);
|
||||
}
|
||||
reader.ReadEndElement();
|
||||
}
|
||||
|
||||
public void WriteXml(System.Xml.XmlWriter writer)
|
||||
{
|
||||
writer.WriteStartElement("RamAddress");
|
||||
{
|
||||
writer.WriteString("0x" + RamAddress.ToString("X8"));
|
||||
}
|
||||
writer.WriteEndElement();
|
||||
writer.WriteStartElement("EntryAddress");
|
||||
{
|
||||
writer.WriteString("0x" + EntryAddress.ToString("X8"));
|
||||
}
|
||||
writer.WriteEndElement();
|
||||
writer.WriteStartElement("AutoloadDoneAddress");
|
||||
{
|
||||
writer.WriteString("0x" + AutoloadDoneAddress.ToString("X8"));
|
||||
}
|
||||
writer.WriteEndElement();
|
||||
writer.WriteStartElement("ArenaLo");
|
||||
{
|
||||
writer.WriteString("0x" + ArenaLo.ToString("X8"));
|
||||
}
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
}
|
||||
public String InPath;
|
||||
public String OutPath;
|
||||
|
||||
public static ASMHackInfo FromByteArray(byte[] Data)
|
||||
{
|
||||
XmlSerializer s = new XmlSerializer(typeof(ASMHackInfo));
|
||||
return (ASMHackInfo)s.Deserialize(new MemoryStream(Data));
|
||||
}
|
||||
|
||||
public byte[] Write()
|
||||
{
|
||||
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
|
||||
ns.Add("", "");
|
||||
XmlSerializer s = new XmlSerializer(typeof(ASMHackInfo));
|
||||
MemoryStream m = new MemoryStream();
|
||||
s.Serialize(m, this, ns);
|
||||
byte[] data = m.ToArray();
|
||||
m.Close();
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
363
NDS/NDS.cs
363
NDS/NDS.cs
@ -8,6 +8,7 @@ using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using LibEveryFileExplorer.Files.SimpleFileSystem;
|
||||
using NDS.UI;
|
||||
using NDS.CPU;
|
||||
|
||||
namespace NDS
|
||||
{
|
||||
@ -16,39 +17,38 @@ namespace NDS
|
||||
public NDS(byte[] data)
|
||||
{
|
||||
EndianBinaryReader er = new EndianBinaryReader(new MemoryStream(data), Endianness.LittleEndian);
|
||||
header = new ROM_Header(er);
|
||||
Header = new RomHeader(er);
|
||||
|
||||
er.BaseStream.Position = header.main_rom_offset;
|
||||
main_rom = er.ReadBytes((int)header.main_size);
|
||||
er.BaseStream.Position = Header.MainRomOffset;
|
||||
MainRom = er.ReadBytes((int)Header.MainSize);
|
||||
|
||||
er.BaseStream.Position = header.sub_rom_offset;
|
||||
sub_rom = er.ReadBytes((int)header.sub_size);
|
||||
er.BaseStream.Position = Header.SubRomOffset;
|
||||
SubRom = er.ReadBytes((int)Header.SubSize);
|
||||
|
||||
er.BaseStream.Position = header.fnt_offset;
|
||||
fnt = new ROM_FNT(er);
|
||||
er.BaseStream.Position = Header.FntOffset;
|
||||
Fnt = new RomFNT(er);
|
||||
|
||||
er.BaseStream.Position = header.main_ovt_offset;
|
||||
main_ovt = new ROM_OVT[header.main_ovt_size / 32];
|
||||
for (int i = 0; i < header.main_ovt_size / 32; i++) main_ovt[i] = new ROM_OVT(er);
|
||||
er.BaseStream.Position = Header.MainOvtOffset;
|
||||
MainOvt = new RomOVT[Header.MainOvtSize / 32];
|
||||
for (int i = 0; i < Header.MainOvtSize / 32; i++) MainOvt[i] = new RomOVT(er);
|
||||
|
||||
er.BaseStream.Position = header.sub_ovt_offset;
|
||||
sub_ovt = new ROM_OVT[header.sub_ovt_size / 32];
|
||||
for (int i = 0; i < header.sub_ovt_size / 32; i++) sub_ovt[i] = new ROM_OVT(er);
|
||||
er.BaseStream.Position = Header.SubOvtOffset;
|
||||
SubOvt = new RomOVT[Header.SubOvtSize / 32];
|
||||
for (int i = 0; i < Header.SubOvtSize / 32; i++) SubOvt[i] = new RomOVT(er);
|
||||
|
||||
er.BaseStream.Position = header.fat_offset;
|
||||
fat = new FileAllocationEntry[header.fat_size / 8];
|
||||
for (int i = 0; i < header.fat_size / 8; i++) fat[i] = new FileAllocationEntry(er);
|
||||
er.BaseStream.Position = Header.FatOffset;
|
||||
Fat = new FileAllocationEntry[Header.FatSize / 8];
|
||||
for (int i = 0; i < Header.FatSize / 8; i++) Fat[i] = new FileAllocationEntry(er);
|
||||
|
||||
er.BaseStream.Position = header.banner_offset;
|
||||
banner = new BannerFile(er);
|
||||
er.BaseStream.Position = Header.BannerOffset;
|
||||
Banner = new RomBanner(er);
|
||||
|
||||
FileData = new byte[header.fat_size / 8][];
|
||||
for (int i = 0; i < header.fat_size / 8; i++)
|
||||
FileData = new byte[Header.FatSize / 8][];
|
||||
for (int i = 0; i < Header.FatSize / 8; i++)
|
||||
{
|
||||
er.BaseStream.Position = fat[i].fileTop;
|
||||
FileData[i] = er.ReadBytes((int)fat[i].fileSize);
|
||||
er.BaseStream.Position = Fat[i].fileTop;
|
||||
FileData[i] = er.ReadBytes((int)Fat[i].fileSize);
|
||||
}
|
||||
|
||||
er.Close();
|
||||
}
|
||||
|
||||
@ -57,214 +57,214 @@ namespace NDS
|
||||
return new NDSViewer(this);
|
||||
}
|
||||
|
||||
public ROM_Header header;
|
||||
public class ROM_Header
|
||||
public RomHeader Header;
|
||||
public class RomHeader
|
||||
{
|
||||
public ROM_Header(EndianBinaryReader er)
|
||||
public RomHeader(EndianBinaryReader er)
|
||||
{
|
||||
game_name = er.ReadString(Encoding.ASCII, 12).Replace("\0", "");
|
||||
game_code = er.ReadString(Encoding.ASCII, 4).Replace("\0", "");
|
||||
maker_code = er.ReadString(Encoding.ASCII, 2).Replace("\0", "");
|
||||
product_id = er.ReadByte();
|
||||
device_type = er.ReadByte();
|
||||
device_size = er.ReadByte();
|
||||
reserved_A = er.ReadBytes(9);
|
||||
game_version = er.ReadByte();
|
||||
property = er.ReadByte();
|
||||
GameName = er.ReadString(Encoding.ASCII, 12).Replace("\0", "");
|
||||
GameCode = er.ReadString(Encoding.ASCII, 4).Replace("\0", "");
|
||||
MakerCode = er.ReadString(Encoding.ASCII, 2).Replace("\0", "");
|
||||
ProductId = er.ReadByte();
|
||||
DeviceType = er.ReadByte();
|
||||
DeviceSize = er.ReadByte();
|
||||
ReservedA = er.ReadBytes(9);
|
||||
GameVersion = er.ReadByte();
|
||||
Property = er.ReadByte();
|
||||
|
||||
main_rom_offset = er.ReadUInt32();
|
||||
main_entry_address = er.ReadUInt32();
|
||||
main_ram_address = er.ReadUInt32();
|
||||
main_size = er.ReadUInt32();
|
||||
sub_rom_offset = er.ReadUInt32();
|
||||
sub_entry_address = er.ReadUInt32();
|
||||
sub_ram_address = er.ReadUInt32();
|
||||
sub_size = er.ReadUInt32();
|
||||
MainRomOffset = er.ReadUInt32();
|
||||
MainEntryAddress = er.ReadUInt32();
|
||||
MainRamAddress = er.ReadUInt32();
|
||||
MainSize = er.ReadUInt32();
|
||||
SubRomOffset = er.ReadUInt32();
|
||||
SubEntryAddress = er.ReadUInt32();
|
||||
SubRamAddress = er.ReadUInt32();
|
||||
SubSize = er.ReadUInt32();
|
||||
|
||||
fnt_offset = er.ReadUInt32();
|
||||
fnt_size = er.ReadUInt32();
|
||||
FntOffset = er.ReadUInt32();
|
||||
FntSize = er.ReadUInt32();
|
||||
|
||||
fat_offset = er.ReadUInt32();
|
||||
fat_size = er.ReadUInt32();
|
||||
FatOffset = er.ReadUInt32();
|
||||
FatSize = er.ReadUInt32();
|
||||
|
||||
main_ovt_offset = er.ReadUInt32();
|
||||
main_ovt_size = er.ReadUInt32();
|
||||
MainOvtOffset = er.ReadUInt32();
|
||||
MainOvtSize = er.ReadUInt32();
|
||||
|
||||
sub_ovt_offset = er.ReadUInt32();
|
||||
sub_ovt_size = er.ReadUInt32();
|
||||
SubOvtOffset = er.ReadUInt32();
|
||||
SubOvtSize = er.ReadUInt32();
|
||||
|
||||
rom_param_A = er.ReadBytes(8);
|
||||
banner_offset = er.ReadUInt32();
|
||||
secure_crc = er.ReadUInt16();
|
||||
rom_param_B = er.ReadBytes(2);
|
||||
RomParamA = er.ReadBytes(8);
|
||||
BannerOffset = er.ReadUInt32();
|
||||
SecureCRC = er.ReadUInt16();
|
||||
RomParamB = er.ReadBytes(2);
|
||||
|
||||
main_autoload_done = er.ReadUInt32();
|
||||
sub_autoload_done = er.ReadUInt32();
|
||||
MainAutoloadDone = er.ReadUInt32();
|
||||
SubAutoloadDone = er.ReadUInt32();
|
||||
|
||||
rom_param_C = er.ReadBytes(8);
|
||||
rom_size = er.ReadUInt32();
|
||||
header_size = er.ReadUInt32();
|
||||
reserved_B = er.ReadBytes(0x38);
|
||||
RomParamC = er.ReadBytes(8);
|
||||
RomSize = er.ReadUInt32();
|
||||
HeaderSize = er.ReadUInt32();
|
||||
ReservedB = er.ReadBytes(0x38);
|
||||
|
||||
logo_data = er.ReadBytes(0x9C);
|
||||
logo_crc = er.ReadUInt16();
|
||||
header_crc = er.ReadUInt16();
|
||||
LogoData = er.ReadBytes(0x9C);
|
||||
LogoCRC = er.ReadUInt16();
|
||||
HeaderCRC = er.ReadUInt16();
|
||||
}
|
||||
public String game_name;//12
|
||||
public String game_code;//4
|
||||
public String maker_code;//2
|
||||
public Byte product_id;
|
||||
public Byte device_type;
|
||||
public Byte device_size;
|
||||
public byte[] reserved_A;//9
|
||||
public Byte game_version;
|
||||
public Byte property;
|
||||
public String GameName;//12
|
||||
public String GameCode;//4
|
||||
public String MakerCode;//2
|
||||
public Byte ProductId;
|
||||
public Byte DeviceType;
|
||||
public Byte DeviceSize;
|
||||
public byte[] ReservedA;//9
|
||||
public Byte GameVersion;
|
||||
public Byte Property;
|
||||
|
||||
public UInt32 main_rom_offset;
|
||||
public UInt32 main_entry_address;
|
||||
public UInt32 main_ram_address;
|
||||
public UInt32 main_size;
|
||||
public UInt32 sub_rom_offset;
|
||||
public UInt32 sub_entry_address;
|
||||
public UInt32 sub_ram_address;
|
||||
public UInt32 sub_size;
|
||||
public UInt32 MainRomOffset;
|
||||
public UInt32 MainEntryAddress;
|
||||
public UInt32 MainRamAddress;
|
||||
public UInt32 MainSize;
|
||||
public UInt32 SubRomOffset;
|
||||
public UInt32 SubEntryAddress;
|
||||
public UInt32 SubRamAddress;
|
||||
public UInt32 SubSize;
|
||||
|
||||
public UInt32 fnt_offset;
|
||||
public UInt32 fnt_size;
|
||||
public UInt32 FntOffset;
|
||||
public UInt32 FntSize;
|
||||
|
||||
public UInt32 fat_offset;
|
||||
public UInt32 fat_size;
|
||||
public UInt32 FatOffset;
|
||||
public UInt32 FatSize;
|
||||
|
||||
public UInt32 main_ovt_offset;
|
||||
public UInt32 main_ovt_size;
|
||||
public UInt32 MainOvtOffset;
|
||||
public UInt32 MainOvtSize;
|
||||
|
||||
public UInt32 sub_ovt_offset;
|
||||
public UInt32 sub_ovt_size;
|
||||
public UInt32 SubOvtOffset;
|
||||
public UInt32 SubOvtSize;
|
||||
|
||||
public byte[] rom_param_A;//8
|
||||
public UInt32 banner_offset;
|
||||
public UInt16 secure_crc;
|
||||
public byte[] rom_param_B;//2
|
||||
public byte[] RomParamA;//8
|
||||
public UInt32 BannerOffset;
|
||||
public UInt16 SecureCRC;
|
||||
public byte[] RomParamB;//2
|
||||
|
||||
public UInt32 main_autoload_done;
|
||||
public UInt32 sub_autoload_done;
|
||||
public UInt32 MainAutoloadDone;
|
||||
public UInt32 SubAutoloadDone;
|
||||
|
||||
public byte[] rom_param_C;//8
|
||||
public UInt32 rom_size;
|
||||
public UInt32 header_size;
|
||||
public byte[] reserved_B;//0x38
|
||||
public byte[] RomParamC;//8
|
||||
public UInt32 RomSize;
|
||||
public UInt32 HeaderSize;
|
||||
public byte[] ReservedB;//0x38
|
||||
|
||||
public byte[] logo_data;//0x9C
|
||||
public UInt16 logo_crc;
|
||||
public UInt16 header_crc;
|
||||
public byte[] LogoData;//0x9C
|
||||
public UInt16 LogoCRC;
|
||||
public UInt16 HeaderCRC;
|
||||
}
|
||||
public Byte[] main_rom;
|
||||
public Byte[] sub_rom;
|
||||
public ROM_FNT fnt;
|
||||
public class ROM_FNT
|
||||
public Byte[] MainRom;
|
||||
public Byte[] SubRom;
|
||||
public RomFNT Fnt;
|
||||
public class RomFNT
|
||||
{
|
||||
public ROM_FNT(EndianBinaryReader er)
|
||||
public RomFNT(EndianBinaryReader er)
|
||||
{
|
||||
directoryTable = new List<DirectoryTableEntry>();
|
||||
directoryTable.Add(new DirectoryTableEntry(er));
|
||||
for (int i = 0; i < directoryTable[0].dirParentID - 1; i++)
|
||||
DirectoryTable = new List<DirectoryTableEntry>();
|
||||
DirectoryTable.Add(new DirectoryTableEntry(er));
|
||||
for (int i = 0; i < DirectoryTable[0].dirParentID - 1; i++)
|
||||
{
|
||||
directoryTable.Add(new DirectoryTableEntry(er));
|
||||
DirectoryTable.Add(new DirectoryTableEntry(er));
|
||||
}
|
||||
entryNameTable = new List<EntryNameTableEntry>();
|
||||
EntryNameTable = new List<EntryNameTableEntry>();
|
||||
int dirend = 0;
|
||||
while (dirend < directoryTable[0].dirParentID)
|
||||
while (dirend < DirectoryTable[0].dirParentID)
|
||||
{
|
||||
byte entryNameLength = er.ReadByte();
|
||||
er.BaseStream.Position--;
|
||||
if (entryNameLength == 0)
|
||||
{
|
||||
entryNameTable.Add(new EntryNameTableEndOfDirectoryEntry(er));
|
||||
EntryNameTable.Add(new EntryNameTableEndOfDirectoryEntry(er));
|
||||
dirend++;
|
||||
}
|
||||
else if (entryNameLength < 0x80) entryNameTable.Add(new EntryNameTableFileEntry(er));
|
||||
else entryNameTable.Add(new EntryNameTableDirectoryEntry(er));
|
||||
else if (entryNameLength < 0x80) EntryNameTable.Add(new EntryNameTableFileEntry(er));
|
||||
else EntryNameTable.Add(new EntryNameTableDirectoryEntry(er));
|
||||
}
|
||||
}
|
||||
public List<DirectoryTableEntry> directoryTable;
|
||||
public List<EntryNameTableEntry> entryNameTable;
|
||||
public List<DirectoryTableEntry> DirectoryTable;
|
||||
public List<EntryNameTableEntry> EntryNameTable;
|
||||
}
|
||||
public ROM_OVT[] main_ovt;
|
||||
public ROM_OVT[] sub_ovt;
|
||||
public class ROM_OVT
|
||||
public RomOVT[] MainOvt;
|
||||
public RomOVT[] SubOvt;
|
||||
public class RomOVT
|
||||
{
|
||||
[Flags]
|
||||
public enum OVT_Flag : byte
|
||||
public enum OVTFlag : byte
|
||||
{
|
||||
Compressed = 1,
|
||||
Authentication_Code = 2
|
||||
AuthenticationCode = 2
|
||||
}
|
||||
public ROM_OVT(EndianBinaryReader er)
|
||||
public RomOVT(EndianBinaryReader er)
|
||||
{
|
||||
id = er.ReadUInt32();
|
||||
ram_address = er.ReadUInt32();
|
||||
ram_size = er.ReadUInt32();
|
||||
bss_size = er.ReadUInt32();
|
||||
sinit_init = er.ReadUInt32();
|
||||
sinit_init_end = er.ReadUInt32();
|
||||
file_id = er.ReadUInt32();
|
||||
Id = er.ReadUInt32();
|
||||
RamAddress = er.ReadUInt32();
|
||||
RamSize = er.ReadUInt32();
|
||||
BssSize = er.ReadUInt32();
|
||||
SinitInit = er.ReadUInt32();
|
||||
SinitInitEnd = er.ReadUInt32();
|
||||
FileId = er.ReadUInt32();
|
||||
UInt32 tmp = er.ReadUInt32();
|
||||
compressed = tmp & 0xFFFFFF;
|
||||
flag = (OVT_Flag)(tmp >> 24);
|
||||
Compressed = tmp & 0xFFFFFF;
|
||||
Flag = (OVTFlag)(tmp >> 24);
|
||||
}
|
||||
public UInt32 id;
|
||||
public UInt32 ram_address;
|
||||
public UInt32 ram_size;
|
||||
public UInt32 bss_size;
|
||||
public UInt32 sinit_init;
|
||||
public UInt32 sinit_init_end;
|
||||
public UInt32 file_id;
|
||||
public UInt32 Id;
|
||||
public UInt32 RamAddress;
|
||||
public UInt32 RamSize;
|
||||
public UInt32 BssSize;
|
||||
public UInt32 SinitInit;
|
||||
public UInt32 SinitInitEnd;
|
||||
public UInt32 FileId;
|
||||
|
||||
public UInt32 compressed;//:24;
|
||||
public OVT_Flag flag;// :8;
|
||||
public UInt32 Compressed;//:24;
|
||||
public OVTFlag Flag;// :8;
|
||||
}
|
||||
public FileAllocationEntry[] fat;
|
||||
public BannerFile banner;
|
||||
public class BannerFile
|
||||
public FileAllocationEntry[] Fat;
|
||||
public RomBanner Banner;
|
||||
public class RomBanner
|
||||
{
|
||||
public BannerFile(EndianBinaryReader er)
|
||||
public RomBanner(EndianBinaryReader er)
|
||||
{
|
||||
h = new BannerHeader(er);
|
||||
v1 = new BannerFileV1(er);
|
||||
Header = new BannerHeader(er);
|
||||
Banner = new BannerV1(er);
|
||||
}
|
||||
BannerHeader h;
|
||||
BannerHeader Header;
|
||||
public class BannerHeader
|
||||
{
|
||||
public BannerHeader(EndianBinaryReader er)
|
||||
{
|
||||
version = er.ReadByte();
|
||||
reserved_A = er.ReadByte();
|
||||
crc16_v1 = er.ReadUInt16();
|
||||
reserved_B = er.ReadBytes(28);
|
||||
Version = er.ReadByte();
|
||||
ReservedA = er.ReadByte();
|
||||
CRC16_v1 = er.ReadUInt16();
|
||||
ReservedB = er.ReadBytes(28);
|
||||
}
|
||||
public Byte version;
|
||||
public Byte reserved_A;
|
||||
public UInt16 crc16_v1;
|
||||
public Byte[] reserved_B;//28
|
||||
public Byte Version;
|
||||
public Byte ReservedA;
|
||||
public UInt16 CRC16_v1;
|
||||
public Byte[] ReservedB;//28
|
||||
}
|
||||
BannerFileV1 v1;
|
||||
public class BannerFileV1
|
||||
BannerV1 Banner;
|
||||
public class BannerV1
|
||||
{
|
||||
public BannerFileV1(EndianBinaryReader er)
|
||||
public BannerV1(EndianBinaryReader er)
|
||||
{
|
||||
image = er.ReadBytes(32 * 32 / 2);
|
||||
pltt = er.ReadBytes(16 * 2);
|
||||
gameName = new string[6];
|
||||
gameName[0] = er.ReadString(Encoding.Unicode, 128).Replace("\0", "");
|
||||
gameName[1] = er.ReadString(Encoding.Unicode, 128).Replace("\0", "");
|
||||
gameName[2] = er.ReadString(Encoding.Unicode, 128).Replace("\0", "");
|
||||
gameName[3] = er.ReadString(Encoding.Unicode, 128).Replace("\0", "");
|
||||
gameName[4] = er.ReadString(Encoding.Unicode, 128).Replace("\0", "");
|
||||
gameName[5] = er.ReadString(Encoding.Unicode, 128).Replace("\0", "");
|
||||
Image = er.ReadBytes(32 * 32 / 2);
|
||||
Pltt = er.ReadBytes(16 * 2);
|
||||
GameName = new string[6];
|
||||
GameName[0] = er.ReadString(Encoding.Unicode, 128).Replace("\0", "");
|
||||
GameName[1] = er.ReadString(Encoding.Unicode, 128).Replace("\0", "");
|
||||
GameName[2] = er.ReadString(Encoding.Unicode, 128).Replace("\0", "");
|
||||
GameName[3] = er.ReadString(Encoding.Unicode, 128).Replace("\0", "");
|
||||
GameName[4] = er.ReadString(Encoding.Unicode, 128).Replace("\0", "");
|
||||
GameName[5] = er.ReadString(Encoding.Unicode, 128).Replace("\0", "");
|
||||
}
|
||||
public Byte[] image;//32*32/2
|
||||
public Byte[] pltt;//16*2
|
||||
public String[] gameName;//6, 128 chars (UTF16-LE)
|
||||
public Byte[] Image;//32*32/2
|
||||
public Byte[] Pltt;//16*2
|
||||
public String[] GameName;//6, 128 chars (UTF16-LE)
|
||||
}
|
||||
}
|
||||
public Byte[][] FileData;
|
||||
@ -276,14 +276,14 @@ namespace NDS
|
||||
dirs.Add(new SFSDirectory("/", true));
|
||||
dirs[0].DirectoryID = 0xF000;
|
||||
|
||||
uint nrdirs = fnt.directoryTable[0].dirParentID;
|
||||
uint nrdirs = Fnt.DirectoryTable[0].dirParentID;
|
||||
for (int i = 1; i < nrdirs; i++)
|
||||
{
|
||||
dirs.Add(new SFSDirectory((ushort)(0xF000 + i)));
|
||||
}
|
||||
for (int i = 1; i < nrdirs; i++)
|
||||
{
|
||||
if (fnt.directoryTable[i].dirParentID - 0xF000 == i)
|
||||
if (Fnt.DirectoryTable[i].dirParentID - 0xF000 == i)
|
||||
{
|
||||
treereconstruct = true;
|
||||
foreach (var v in dirs)
|
||||
@ -292,7 +292,7 @@ namespace NDS
|
||||
}
|
||||
break;
|
||||
}
|
||||
dirs[i].Parent = dirs[fnt.directoryTable[i].dirParentID - 0xF000];
|
||||
dirs[i].Parent = dirs[Fnt.DirectoryTable[i].dirParentID - 0xF000];
|
||||
}
|
||||
if (!treereconstruct)
|
||||
{
|
||||
@ -308,13 +308,13 @@ namespace NDS
|
||||
}
|
||||
}
|
||||
uint offset = nrdirs * 8;
|
||||
ushort fileid = fnt.directoryTable[0].dirEntryFileID;
|
||||
ushort fileid = Fnt.DirectoryTable[0].dirEntryFileID;
|
||||
SFSDirectory curdir = null;
|
||||
foreach (EntryNameTableEntry e in fnt.entryNameTable)
|
||||
foreach (EntryNameTableEntry e in Fnt.EntryNameTable)
|
||||
{
|
||||
for (int i = 0; i < nrdirs; i++)
|
||||
{
|
||||
if (offset == fnt.directoryTable[i].dirEntryStart)
|
||||
if (offset == Fnt.DirectoryTable[i].dirEntryStart)
|
||||
{
|
||||
curdir = dirs[i];
|
||||
break;
|
||||
@ -341,7 +341,7 @@ namespace NDS
|
||||
offset += 3u + (e.entryNameLength & 0x7Fu);
|
||||
}
|
||||
}
|
||||
for (int i = (int)(header.main_ovt_size / 32 + header.sub_ovt_size / 32); i < header.fat_size / 8; i++)
|
||||
for (int i = (int)(Header.MainOvtSize / 32 + Header.SubOvtSize / 32); i < Header.FatSize / 8; i++)
|
||||
{
|
||||
//byte[] data = new byte[fat[i].fileSize];
|
||||
//Array.Copy(FileData FIMG.fileImage, fat[i].fileTop, data, 0, data.Length);
|
||||
@ -350,6 +350,11 @@ namespace NDS
|
||||
return dirs[0];
|
||||
}
|
||||
|
||||
public byte[] GetDecompressedARM9()
|
||||
{
|
||||
return ARM9.Decompress(MainRom, Header.MainRamAddress, Header.MainEntryAddress, Header.MainAutoloadDone);
|
||||
}
|
||||
|
||||
public class NDSIdentifier : FileFormatIdentifier
|
||||
{
|
||||
public override string GetCategory()
|
||||
|
@ -52,6 +52,8 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CPU\ARM9.cs" />
|
||||
<Compile Include="CPU\ASMHackInfo.cs" />
|
||||
<Compile Include="GPU\CommandContext.cs" />
|
||||
<Compile Include="GPU\Textures.cs" />
|
||||
<Compile Include="NDS.cs" />
|
||||
|
117
NDS/UI/NDSViewer.Designer.cs
generated
117
NDS/UI/NDSViewer.Designer.cs
generated
@ -53,6 +53,20 @@
|
||||
this.menuItem10 = new System.Windows.Forms.MenuItem();
|
||||
this.menuItem11 = new System.Windows.Forms.MenuItem();
|
||||
this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
|
||||
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
|
||||
this.tabControl1 = new System.Windows.Forms.TabControl();
|
||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||
this.tabPage2 = new System.Windows.Forms.TabPage();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.button1 = new System.Windows.Forms.Button();
|
||||
this.button2 = new System.Windows.Forms.Button();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
|
||||
this.splitContainer1.Panel1.SuspendLayout();
|
||||
this.splitContainer1.Panel2.SuspendLayout();
|
||||
this.splitContainer1.SuspendLayout();
|
||||
this.tabControl1.SuspendLayout();
|
||||
this.tabPage2.SuspendLayout();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// fileBrowser1
|
||||
@ -66,7 +80,7 @@
|
||||
this.fileBrowser1.ShowAddFileButton = false;
|
||||
this.fileBrowser1.ShowDeleteButton = false;
|
||||
this.fileBrowser1.ShowRenameButton = false;
|
||||
this.fileBrowser1.Size = new System.Drawing.Size(652, 338);
|
||||
this.fileBrowser1.Size = new System.Drawing.Size(475, 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);
|
||||
@ -233,17 +247,109 @@
|
||||
//
|
||||
this.saveFileDialog1.Title = "Export...";
|
||||
//
|
||||
// splitContainer1
|
||||
//
|
||||
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel2;
|
||||
this.splitContainer1.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer1.Name = "splitContainer1";
|
||||
//
|
||||
// splitContainer1.Panel1
|
||||
//
|
||||
this.splitContainer1.Panel1.Controls.Add(this.fileBrowser1);
|
||||
//
|
||||
// splitContainer1.Panel2
|
||||
//
|
||||
this.splitContainer1.Panel2.Controls.Add(this.tabControl1);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(652, 338);
|
||||
this.splitContainer1.SplitterDistance = 475;
|
||||
this.splitContainer1.TabIndex = 1;
|
||||
//
|
||||
// tabControl1
|
||||
//
|
||||
this.tabControl1.Controls.Add(this.tabPage1);
|
||||
this.tabControl1.Controls.Add(this.tabPage2);
|
||||
this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tabControl1.Location = new System.Drawing.Point(0, 0);
|
||||
this.tabControl1.Name = "tabControl1";
|
||||
this.tabControl1.SelectedIndex = 0;
|
||||
this.tabControl1.Size = new System.Drawing.Size(173, 338);
|
||||
this.tabControl1.TabIndex = 0;
|
||||
//
|
||||
// tabPage1
|
||||
//
|
||||
this.tabPage1.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage1.Name = "tabPage1";
|
||||
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage1.Size = new System.Drawing.Size(165, 312);
|
||||
this.tabPage1.TabIndex = 0;
|
||||
this.tabPage1.Text = "Banner";
|
||||
this.tabPage1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// tabPage2
|
||||
//
|
||||
this.tabPage2.Controls.Add(this.groupBox1);
|
||||
this.tabPage2.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage2.Name = "tabPage2";
|
||||
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage2.Size = new System.Drawing.Size(165, 312);
|
||||
this.tabPage2.TabIndex = 1;
|
||||
this.tabPage2.Text = "Code";
|
||||
this.tabPage2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Controls.Add(this.button1);
|
||||
this.groupBox1.Controls.Add(this.button2);
|
||||
this.groupBox1.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.groupBox1.Location = new System.Drawing.Point(3, 3);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Padding = new System.Windows.Forms.Padding(3, 3, 3, 6);
|
||||
this.groupBox1.Size = new System.Drawing.Size(159, 68);
|
||||
this.groupBox1.TabIndex = 0;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "ARM9";
|
||||
//
|
||||
// button1
|
||||
//
|
||||
this.button1.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.button1.Location = new System.Drawing.Point(3, 39);
|
||||
this.button1.Name = "button1";
|
||||
this.button1.Size = new System.Drawing.Size(153, 23);
|
||||
this.button1.TabIndex = 0;
|
||||
this.button1.Text = "Export Decompressed...";
|
||||
this.button1.UseVisualStyleBackColor = true;
|
||||
this.button1.Click += new System.EventHandler(this.button1_Click);
|
||||
//
|
||||
// button2
|
||||
//
|
||||
this.button2.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.button2.Location = new System.Drawing.Point(3, 16);
|
||||
this.button2.Name = "button2";
|
||||
this.button2.Size = new System.Drawing.Size(153, 23);
|
||||
this.button2.TabIndex = 1;
|
||||
this.button2.Text = "Export...";
|
||||
this.button2.UseVisualStyleBackColor = true;
|
||||
this.button2.Click += new System.EventHandler(this.button2_Click);
|
||||
//
|
||||
// NDSViewer
|
||||
//
|
||||
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.Controls.Add(this.splitContainer1);
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.Menu = this.mainMenu1;
|
||||
this.Name = "NDSViewer";
|
||||
this.Text = "NARC Viewer";
|
||||
this.Load += new System.EventHandler(this.NARCViewer_Load);
|
||||
this.splitContainer1.Panel1.ResumeLayout(false);
|
||||
this.splitContainer1.Panel2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
|
||||
this.splitContainer1.ResumeLayout(false);
|
||||
this.tabControl1.ResumeLayout(false);
|
||||
this.tabPage2.ResumeLayout(false);
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
@ -273,5 +379,12 @@
|
||||
private System.Windows.Forms.SaveFileDialog saveFileDialog1;
|
||||
private System.Windows.Forms.MenuItem menuReplace;
|
||||
private System.Windows.Forms.MenuItem menuItem14;
|
||||
private System.Windows.Forms.SplitContainer splitContainer1;
|
||||
private System.Windows.Forms.TabControl tabControl1;
|
||||
private System.Windows.Forms.TabPage tabPage1;
|
||||
private System.Windows.Forms.TabPage tabPage2;
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
private System.Windows.Forms.Button button1;
|
||||
private System.Windows.Forms.Button button2;
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ using LibEveryFileExplorer.Files.SimpleFileSystem;
|
||||
using LibEveryFileExplorer;
|
||||
using LibEveryFileExplorer.Files;
|
||||
using NDS.NitroSystem.FND;
|
||||
using System.IO;
|
||||
|
||||
namespace NDS.UI
|
||||
{
|
||||
@ -232,5 +233,29 @@ namespace NDS.UI
|
||||
fileBrowser1.UpdateDirectories(Root.GetTreeNodes(), true);
|
||||
*/
|
||||
}
|
||||
|
||||
private void button1_Click(object sender, EventArgs e)
|
||||
{
|
||||
saveFileDialog1.FileName = "arm9.bin";
|
||||
saveFileDialog1.Filter = "Binary Data (*.bin)|*.bin";
|
||||
if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK
|
||||
&& saveFileDialog1.FileName.Length > 0)
|
||||
{
|
||||
File.Create(saveFileDialog1.FileName).Close();
|
||||
File.WriteAllBytes(saveFileDialog1.FileName, Archive.GetDecompressedARM9());
|
||||
}
|
||||
}
|
||||
|
||||
private void button2_Click(object sender, EventArgs e)
|
||||
{
|
||||
saveFileDialog1.FileName = "arm9.bin";
|
||||
saveFileDialog1.Filter = "Binary Data (*.bin)|*.bin";
|
||||
if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK
|
||||
&& saveFileDialog1.FileName.Length > 0)
|
||||
{
|
||||
File.Create(saveFileDialog1.FileName).Close();
|
||||
File.WriteAllBytes(saveFileDialog1.FileName, Archive.MainRom);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user