diff --git a/Plugins/SDAT/SDAT/SWAR.cs b/Plugins/SDAT/SDAT/SWAR.cs
index 24ef6bd6..640f7d93 100644
--- a/Plugins/SDAT/SDAT/SWAR.cs
+++ b/Plugins/SDAT/SDAT/SWAR.cs
@@ -130,7 +130,7 @@ public static void Write(sSWAV[] sounds, string fileout)
for (int i = 0; i < sounds.Length; i++)
{
bw.Write(currOffset);
- currOffset += (uint)sounds[i].data.data.Length + 0x0C;
+ currOffset += (uint)sounds[i].data.data.Length + 0x0A;
}
// Write data
diff --git a/Tinke/Dialog/SaveOptions.Designer.cs b/Tinke/Dialog/SaveOptions.Designer.cs
index 83a2a4c5..d38bfe0a 100644
--- a/Tinke/Dialog/SaveOptions.Designer.cs
+++ b/Tinke/Dialog/SaveOptions.Designer.cs
@@ -32,6 +32,8 @@ private void InitializeComponent()
this.checkBox2 = new System.Windows.Forms.CheckBox();
this.btn_OK = new System.Windows.Forms.Button();
this.btn_Cancel = new System.Windows.Forms.Button();
+ this.checkBox3 = new System.Windows.Forms.CheckBox();
+ this.checkBox4 = new System.Windows.Forms.CheckBox();
this.SuspendLayout();
//
// checkBox1
@@ -39,7 +41,7 @@ private void InitializeComponent()
this.checkBox1.AutoSize = true;
this.checkBox1.Location = new System.Drawing.Point(12, 12);
this.checkBox1.Name = "checkBox1";
- this.checkBox1.Size = new System.Drawing.Size(42, 16);
+ this.checkBox1.Size = new System.Drawing.Size(53, 19);
this.checkBox1.TabIndex = 0;
this.checkBox1.Text = "S1E";
this.checkBox1.UseVisualStyleBackColor = true;
@@ -47,9 +49,9 @@ private void InitializeComponent()
// checkBox2
//
this.checkBox2.AutoSize = true;
- this.checkBox2.Location = new System.Drawing.Point(12, 34);
+ this.checkBox2.Location = new System.Drawing.Point(12, 37);
this.checkBox2.Name = "checkBox2";
- this.checkBox2.Size = new System.Drawing.Size(42, 16);
+ this.checkBox2.Size = new System.Drawing.Size(53, 19);
this.checkBox2.TabIndex = 2;
this.checkBox2.Text = "S1F";
this.checkBox2.UseVisualStyleBackColor = true;
@@ -58,7 +60,7 @@ private void InitializeComponent()
//
this.btn_OK.DialogResult = System.Windows.Forms.DialogResult.OK;
this.btn_OK.Image = global::Tinke.Properties.Resources.accept;
- this.btn_OK.Location = new System.Drawing.Point(12, 56);
+ this.btn_OK.Location = new System.Drawing.Point(12, 112);
this.btn_OK.Name = "btn_OK";
this.btn_OK.Size = new System.Drawing.Size(90, 30);
this.btn_OK.TabIndex = 3;
@@ -71,7 +73,7 @@ private void InitializeComponent()
//
this.btn_Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btn_Cancel.Image = global::Tinke.Properties.Resources.cancel;
- this.btn_Cancel.Location = new System.Drawing.Point(137, 56);
+ this.btn_Cancel.Location = new System.Drawing.Point(137, 112);
this.btn_Cancel.Name = "btn_Cancel";
this.btn_Cancel.Size = new System.Drawing.Size(90, 30);
this.btn_Cancel.TabIndex = 4;
@@ -80,10 +82,34 @@ private void InitializeComponent()
this.btn_Cancel.UseVisualStyleBackColor = true;
this.btn_Cancel.Click += new System.EventHandler(this.btn_Cancel_Click);
//
+ // checkBox3
+ //
+ this.checkBox3.AutoSize = true;
+ this.checkBox3.Location = new System.Drawing.Point(12, 62);
+ this.checkBox3.Name = "checkBox3";
+ this.checkBox3.Size = new System.Drawing.Size(53, 19);
+ this.checkBox3.TabIndex = 5;
+ this.checkBox3.Text = "S20";
+ this.checkBox3.UseVisualStyleBackColor = true;
+ this.checkBox3.CheckedChanged += new System.EventHandler(this.checkBox3_CheckedChanged);
+ //
+ // checkBox4
+ //
+ this.checkBox4.AutoSize = true;
+ this.checkBox4.Enabled = false;
+ this.checkBox4.Location = new System.Drawing.Point(12, 87);
+ this.checkBox4.Name = "checkBox4";
+ this.checkBox4.Size = new System.Drawing.Size(53, 19);
+ this.checkBox4.TabIndex = 6;
+ this.checkBox4.Text = "S21";
+ this.checkBox4.UseVisualStyleBackColor = true;
+ //
// SaveOptions
//
this.BackColor = System.Drawing.SystemColors.GradientInactiveCaption;
- this.ClientSize = new System.Drawing.Size(239, 98);
+ this.ClientSize = new System.Drawing.Size(239, 154);
+ this.Controls.Add(this.checkBox4);
+ this.Controls.Add(this.checkBox3);
this.Controls.Add(this.btn_Cancel);
this.Controls.Add(this.btn_OK);
this.Controls.Add(this.checkBox2);
@@ -107,5 +133,7 @@ private void InitializeComponent()
private System.Windows.Forms.CheckBox checkBox2;
private System.Windows.Forms.Button btn_OK;
private System.Windows.Forms.Button btn_Cancel;
+ private System.Windows.Forms.CheckBox checkBox3;
+ private System.Windows.Forms.CheckBox checkBox4;
}
}
diff --git a/Tinke/Dialog/SaveOptions.cs b/Tinke/Dialog/SaveOptions.cs
index c44c4b5f..d46ca67d 100644
--- a/Tinke/Dialog/SaveOptions.cs
+++ b/Tinke/Dialog/SaveOptions.cs
@@ -22,6 +22,8 @@ private void ReadLanguage()
btn_Cancel.Text = xml.Element("S1C").Value;
checkBox1.Text = xml.Element("S1E").Value;
checkBox2.Text = xml.Element("S1F").Value;
+ checkBox3.Text = xml.Element("S20").Value;
+ checkBox4.Text = xml.Element("S21").Value;
}
catch { throw new NotImplementedException("There was an error reading the language file"); }
}
@@ -36,6 +38,16 @@ public bool IsSafeTrim
get { return checkBox2.Checked; }
}
+ public bool IsReCompress
+ {
+ get { return checkBox3.Checked; }
+ }
+
+ public bool IsBetterCompress
+ {
+ get { return checkBox4.Checked; }
+ }
+
private void btn_OK_Click(object sender, EventArgs e)
{
this.Close();
@@ -45,5 +57,17 @@ private void btn_Cancel_Click(object sender, EventArgs e)
{
this.Close();
}
+
+ private void checkBox3_CheckedChanged(object sender, EventArgs e)
+ {
+ if (checkBox3.Checked)
+ {
+ checkBox4.Enabled = true;
+ } else
+ {
+ checkBox4.Checked = false;
+ checkBox4.Enabled= false;
+ }
+ }
}
}
diff --git a/Tinke/Nitro/TWL.cs b/Tinke/Nitro/TWL.cs
index 2dcd58b6..75ce49ba 100644
--- a/Tinke/Nitro/TWL.cs
+++ b/Tinke/Nitro/TWL.cs
@@ -1,83 +1,83 @@
-// ----------------------------------------------------------------------
-//
-
-// Copyright (C) 2017
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// 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, see .
-//
-//
-
-// MetLob
-// metlob@mail333.com
-// 13/10/2017 18:53:14
-// -----------------------------------------------------------------------
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Tinke.Nitro
-{
- using System.IO;
- using System.Security.Cryptography;
-
- using DSDecmp.Formats;
-
- using Ekona;
-
- using Tinke.Tools;
- using Tinke.Tools.Cryptography;
-
- class TWL
- {
- private static byte[] modcryptCmnKey =
- {
- 0x79, 0x3E, 0x4F, 0x1A, 0x5F, 0x0F, 0x68, 0x2A, 0x58, 0x02, 0x59, 0x29, 0x4E,
- 0xFB, 0xFE, 0xFF
- };
-
- internal static byte[] hmac_sha1_key =
- {
- 0x21,0x06,0xC0,0xDE,0xBA,0x98,0xCE,0x3F,0xA6,0x92,0xE3,0x9D,0x46,0xF2,0xED,0x01,
- 0x76,0xE3,0xCC,0x08,0x56,0x23,0x63,0xFA,0xCA,0xD4,0xEC,0xDF,0x9A,0x62,0x78,0x34,
- 0x8F,0x6D,0x63,0x3C,0xFE,0x22,0xCA,0x92,0x20,0x88,0x97,0x23,0xD2,0xCF,0xAE,0xC2,
- 0x32,0x67,0x8D,0xFE,0xCA,0x83,0x64,0x98,0xAC,0xFD,0x3E,0x37,0x87,0x46,0x58,0x24,
- };
-
- internal static byte[] rsaPublicKey =
- {
- 0x95, 0x6F, 0x79, 0x0D, 0xF0, 0x8B, 0xB8, 0x5A, 0x76, 0xAA, 0xEF, 0xA2, 0x7F, 0xE8, 0x74, 0x75,
- 0x8B, 0xED, 0x9E, 0xDF, 0x9E, 0x9A, 0x67, 0x0C, 0xD8, 0x18, 0xBE, 0xB9, 0xB2, 0x88, 0x52, 0x03,
- 0xB3, 0xFA, 0x11, 0xAE, 0xAA, 0x18, 0x65, 0x13, 0xB5, 0xD6, 0xBB, 0x85, 0xA3, 0x84, 0xD0, 0xD0,
- 0xEF, 0xB3, 0x66, 0xCB, 0xC6, 0x05, 0x1A, 0xAA, 0x86, 0x82, 0x7A, 0xB7, 0x43, 0x11, 0xF5, 0x9C,
- 0x9B, 0xFC, 0x6C, 0x70, 0x79, 0xD5, 0xF1, 0x7B, 0xD0, 0x81, 0x9F, 0x52, 0x20, 0x56, 0x73, 0x8C,
- 0x72, 0x1F, 0x40, 0xCF, 0x23, 0x61, 0x93, 0x25, 0x90, 0xA3, 0xC5, 0xDC, 0x94, 0xCF, 0xD1, 0x7A,
- 0x8C, 0xBC, 0x95, 0x4A, 0x91, 0x8A, 0xA8, 0x58, 0xF4, 0xD8, 0x04, 0xBA, 0xF7, 0xD3, 0xC1, 0xC4,
- 0xD7, 0xB8, 0xF0, 0x77, 0x01, 0x2F, 0xA1, 0x70, 0x26, 0x0B, 0x2C, 0x04, 0x90, 0x56, 0xF3, 0xA5
- };
-
- internal static byte[] rsaSignatureMask =
- {
- 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xCC, 0xCC, 0xCC, 0xCC,
- 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC
- };
-
+// ----------------------------------------------------------------------
+//
+
+// Copyright (C) 2017
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// 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, see .
+//
+//
+
+// MetLob
+// metlob@mail333.com
+// 13/10/2017 18:53:14
+// -----------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tinke.Nitro
+{
+ using System.IO;
+ using System.Security.Cryptography;
+
+ using DSDecmp.Formats;
+
+ using Ekona;
+
+ using Tinke.Tools;
+ using Tinke.Tools.Cryptography;
+
+ class TWL
+ {
+ private static byte[] modcryptCmnKey =
+ {
+ 0x79, 0x3E, 0x4F, 0x1A, 0x5F, 0x0F, 0x68, 0x2A, 0x58, 0x02, 0x59, 0x29, 0x4E,
+ 0xFB, 0xFE, 0xFF
+ };
+
+ internal static byte[] hmac_sha1_key =
+ {
+ 0x21,0x06,0xC0,0xDE,0xBA,0x98,0xCE,0x3F,0xA6,0x92,0xE3,0x9D,0x46,0xF2,0xED,0x01,
+ 0x76,0xE3,0xCC,0x08,0x56,0x23,0x63,0xFA,0xCA,0xD4,0xEC,0xDF,0x9A,0x62,0x78,0x34,
+ 0x8F,0x6D,0x63,0x3C,0xFE,0x22,0xCA,0x92,0x20,0x88,0x97,0x23,0xD2,0xCF,0xAE,0xC2,
+ 0x32,0x67,0x8D,0xFE,0xCA,0x83,0x64,0x98,0xAC,0xFD,0x3E,0x37,0x87,0x46,0x58,0x24,
+ };
+
+ internal static byte[] rsaPublicKey =
+ {
+ 0x95, 0x6F, 0x79, 0x0D, 0xF0, 0x8B, 0xB8, 0x5A, 0x76, 0xAA, 0xEF, 0xA2, 0x7F, 0xE8, 0x74, 0x75,
+ 0x8B, 0xED, 0x9E, 0xDF, 0x9E, 0x9A, 0x67, 0x0C, 0xD8, 0x18, 0xBE, 0xB9, 0xB2, 0x88, 0x52, 0x03,
+ 0xB3, 0xFA, 0x11, 0xAE, 0xAA, 0x18, 0x65, 0x13, 0xB5, 0xD6, 0xBB, 0x85, 0xA3, 0x84, 0xD0, 0xD0,
+ 0xEF, 0xB3, 0x66, 0xCB, 0xC6, 0x05, 0x1A, 0xAA, 0x86, 0x82, 0x7A, 0xB7, 0x43, 0x11, 0xF5, 0x9C,
+ 0x9B, 0xFC, 0x6C, 0x70, 0x79, 0xD5, 0xF1, 0x7B, 0xD0, 0x81, 0x9F, 0x52, 0x20, 0x56, 0x73, 0x8C,
+ 0x72, 0x1F, 0x40, 0xCF, 0x23, 0x61, 0x93, 0x25, 0x90, 0xA3, 0xC5, 0xDC, 0x94, 0xCF, 0xD1, 0x7A,
+ 0x8C, 0xBC, 0x95, 0x4A, 0x91, 0x8A, 0xA8, 0x58, 0xF4, 0xD8, 0x04, 0xBA, 0xF7, 0xD3, 0xC1, 0xC4,
+ 0xD7, 0xB8, 0xF0, 0x77, 0x01, 0x2F, 0xA1, 0x70, 0x26, 0x0B, 0x2C, 0x04, 0x90, 0x56, 0xF3, 0xA5
+ };
+
+ internal static byte[] rsaSignatureMask =
+ {
+ 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xCC, 0xCC, 0xCC, 0xCC,
+ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC
+ };
+
internal static byte[] rsaFontKey =
{
0x9F, 0x80, 0xBC, 0x5F, 0xB6, 0xB6, 0x1D, 0x2A, 0x46, 0x02, 0x52, 0x64, 0xB2, 0xA3, 0x86, 0xCE,
@@ -88,392 +88,392 @@ class TWL
0x4E, 0x82, 0xF7, 0xB3, 0xE2, 0x9C, 0xE4, 0x72, 0xE3, 0xDC, 0x60, 0xAF, 0xCC, 0x18, 0xE2, 0xD4,
0xEF, 0xD2, 0x76, 0x47, 0x31, 0xE6, 0x14, 0x0E, 0x1D, 0x26, 0xB5, 0x85, 0x97, 0xBC, 0xC6, 0xB6,
0xD8, 0xE7, 0x69, 0x2D, 0x2C, 0x26, 0xFB, 0x5F, 0x70, 0x9E, 0x19, 0x9C, 0x6B, 0x02, 0x6D, 0x97
- };
-
- private uint firstDSiHashOffset;
- private uint dsiHashSize;
- bool twlEncrypted;
-
- public byte[][] Overlays9Sha1Hmac { get; private set; }
- public byte[][] Header2Data { get; private set; }
- public byte[] DSi9Data { get; private set; }
- public byte[] DSi7Data { get; private set; }
- public byte[] Hashtable1Data { get; private set; }
- public byte[] Hashtable2Data { get; private set; }
-
- public TWL(string file, Estructuras.ROMHeader hdr, Estructuras.sFAT[] fat)
- {
- sFile[] overlays = Overlay.ReadBasicOverlays(file, hdr.ARM9overlayOffset, hdr.ARM9overlaySize, true, fat);
- this.firstDSiHashOffset = hdr.digest_ntr_size / hdr.digest_sector_size * 0x14;
- this.dsiHashSize = hdr.digest_twl_size / hdr.digest_sector_size * 0x14;
-
- // Read data
- BinaryReader br = new BinaryReader(File.OpenRead(file));
- br.BaseStream.Position = hdr.sector_hashtable_start;
- this.Hashtable1Data = br.ReadBytes((int)hdr.sector_hashtable_size);
- br.BaseStream.Position = hdr.block_hashtable_start;
- this.Hashtable2Data = br.ReadBytes((int)hdr.block_hashtable_size);
- br.BaseStream.Position = hdr.dsi9_rom_offset;
- this.DSi9Data = br.ReadBytes(Math.Max((int)hdr.modcrypt1_size, (int)hdr.dsi9_size));
- br.BaseStream.Position = hdr.dsi7_rom_offset;
- this.DSi7Data = br.ReadBytes(Math.Max((int)hdr.modcrypt2_size, (int)hdr.dsi7_size));
- if (!hdr.trimmedRom)
- {
- //br.BaseStream.Position = hdr.digest_twl_start - 0x3000;
- //this.Header2Data = br.ReadBytes(0x3000);
+ };
+
+ private uint firstDSiHashOffset;
+ private uint dsiHashSize;
+ bool twlEncrypted;
+
+ public byte[][] Overlays9Sha1Hmac { get; private set; }
+ public byte[][] Header2Data { get; private set; }
+ public byte[] DSi9Data { get; private set; }
+ public byte[] DSi7Data { get; private set; }
+ public byte[] Hashtable1Data { get; private set; }
+ public byte[] Hashtable2Data { get; private set; }
+
+ public TWL(string file, Estructuras.ROMHeader hdr, Estructuras.sFAT[] fat)
+ {
+ sFile[] overlays = Overlay.ReadBasicOverlays(file, hdr.ARM9overlayOffset, hdr.ARM9overlaySize, true, fat);
+ this.firstDSiHashOffset = hdr.digest_ntr_size / hdr.digest_sector_size * 0x14;
+ this.dsiHashSize = hdr.digest_twl_size / hdr.digest_sector_size * 0x14;
+
+ // Read data
+ BinaryReader br = new BinaryReader(File.OpenRead(file));
+ br.BaseStream.Position = hdr.sector_hashtable_start;
+ this.Hashtable1Data = br.ReadBytes((int)hdr.sector_hashtable_size);
+ br.BaseStream.Position = hdr.block_hashtable_start;
+ this.Hashtable2Data = br.ReadBytes((int)hdr.block_hashtable_size);
+ br.BaseStream.Position = hdr.dsi9_rom_offset;
+ this.DSi9Data = br.ReadBytes(Math.Max((int)hdr.modcrypt1_size, (int)hdr.dsi9_size));
+ br.BaseStream.Position = hdr.dsi7_rom_offset;
+ this.DSi7Data = br.ReadBytes(Math.Max((int)hdr.modcrypt2_size, (int)hdr.dsi7_size));
+ if (!hdr.trimmedRom)
+ {
+ //br.BaseStream.Position = hdr.digest_twl_start - 0x3000;
+ //this.Header2Data = br.ReadBytes(0x3000);
this.Header2Data = new byte[3][];
for (int i = 0; i < 3; i++)
- {
- br.BaseStream.Position = hdr.digest_ntr_start + 0x4000;
+ {
+ br.BaseStream.Position = hdr.digest_ntr_start + 0x4000;
this.Header2Data[i] = br.ReadBytes(0x1000);
- }
- }
-
- // Calc SHA1-HMAC of overlays9
- HMACSHA1 hmac = new HMACSHA1(TWL.hmac_sha1_key);
- this.Overlays9Sha1Hmac = new byte[overlays.Length][];
- for (int i = 0; i < overlays.Length; i++)
- {
- br.BaseStream.Position = overlays[i].offset;
- byte[] ovlData = br.ReadBytes((int)overlays[i].size);
- this.Overlays9Sha1Hmac[i] = hmac.ComputeHash(ovlData, 0, ovlData.Length);
- }
-
- // Check for encryption modcrypt section
- this.twlEncrypted = false; // (hdr.twlInternalFlags & 2) > 0;
- if (hdr.modcrypt1_start >= hdr.digest_twl_start && hdr.modcrypt1_start < 0xFFFFFFFF)
- {
- uint modcryptHashedSectorIndex = (hdr.modcrypt1_start - hdr.digest_twl_start) / hdr.digest_sector_size;
- uint modcryptHashedSectorOff = modcryptHashedSectorIndex * hdr.digest_sector_size;
- uint hashOff = modcryptHashedSectorIndex * 0x14;
-
- br.BaseStream.Position = hdr.digest_twl_start + modcryptHashedSectorOff;
- byte[] firstModcryptBlock = br.ReadBytes((int)hdr.digest_sector_size);
- byte[] hash = hmac.ComputeHash(firstModcryptBlock, 0, (int)hdr.digest_sector_size);
- for (int i = 0; i < 20 && !twlEncrypted; i++) twlEncrypted = hash[i] != Hashtable1Data[this.firstDSiHashOffset + hashOff + i];
- }
- br.Close();
-
- // Decrypt modcrypt sections
- if (this.twlEncrypted)
- {
- byte[] key = AES128KeyGenerate(hdr);
- byte[] counter = new byte[16];
- if (hdr.modcrypt1_size > 0 && hdr.modcrypt1_size < 0xFFFFFFFF)
- {
- Array.Copy(hdr.hmac_arm9, 0, counter, 0, 16);
- uint offset = hdr.modcrypt1_start - hdr.dsi9_rom_offset;
- byte[] decrypted = AES128CTRCrypt(key, counter, this.DSi9Data, offset, hdr.modcrypt1_size);
- if (offset == 0 && decrypted.Length == this.DSi9Data.Length) this.DSi9Data = decrypted;
- else Array.Copy(decrypted, 0, this.DSi9Data, offset, decrypted.Length);
- }
-
- if (hdr.modcrypt2_size > 0 && hdr.modcrypt2_size < 0xFFFFFFFF)
- {
- Array.Copy(hdr.hmac_arm7, 0, counter, 0, 16);
- uint offset = hdr.modcrypt2_start - hdr.dsi7_rom_offset;
- byte[] decrypted = AES128CTRCrypt(key, counter, this.DSi7Data, offset, hdr.modcrypt2_size);
- if (offset == 0 && decrypted.Length == this.DSi7Data.Length) this.DSi7Data = decrypted;
- else Array.Copy(decrypted, 0, this.DSi7Data, offset, decrypted.Length);
- }
- }
-
- hmac.Clear();
- hmac.Dispose();
- this.twlEncrypted = (hdr.twlInternalFlags & 2) > 0;
- }
-
- public void UpdateOverlays9Sha1Hmac(ref sFile arm9, Estructuras.ROMHeader hdr, List ov9, HMACSHA1 hmac = null)
- {
- if (hmac == null) hmac = new HMACSHA1(hmac_sha1_key);
- byte[][] hashes = new byte[ov9.Count][];
- bool changed = false;
- for (int i = 0; i < ov9.Count; i++)
- {
- Stream str = File.OpenRead(ov9[i].path);
- byte[] buffer = new byte[ov9[i].size];
- str.Position = ov9[i].offset;
- str.Read(buffer, 0, buffer.Length);
- str.Close();
- hashes[i] = hmac.ComputeHash(buffer);
- for (int j = 0; j < hashes[i].Length && !changed; j++) changed |= hashes[i][j] != this.Overlays9Sha1Hmac[i][j];
- }
-
- if (changed)
- {
- // Read arm9
- BinaryReader br = new BinaryReader(File.OpenRead(arm9.path));
- br.BaseStream.Position = arm9.offset;
- byte[] arm9Data = br.ReadBytes((int)arm9.size);
- br.Close();
-
- // Decompress arm9
- hdr.ARM9size = arm9.size;
- uint initptr = BitConverter.ToUInt32(hdr.reserved2, 0) & 0x3FFF;
- uint hdrptr = BitConverter.ToUInt32(arm9Data, (int)initptr + 0x14) - hdr.ARM9ramAddress;
- bool cmparm9 = ARM9BLZ.Decompress(arm9Data, hdr, out arm9Data);
-
- // Get hmac offset
- uint offset = 0;
- uint end = BitConverter.ToUInt32(arm9Data, (int)initptr + 8) - hdr.ARM9ramAddress;
- for (long i = end - 0x14 * ov9.Count; i >= 0 && offset == 0; i--)
- {
- bool cond = arm9Data[i] == this.Overlays9Sha1Hmac[0][0];
- for (int j = 1; j < 20 && cond; j++) cond = arm9Data[i + j] == this.Overlays9Sha1Hmac[0][j];
- if (cond) offset = (uint)i;
- }
-
- // Write new hash
- if (offset > 0)
- {
- for (int i = 0; i < ov9.Count; i++) Array.Copy(hashes[i], 0, arm9Data, offset + i * 0x14, 20);
- if (!cmparm9) arm9Data = ARM9BLZ.Compress(arm9Data, hdr, arm9.size - hdrptr);
-
- string arm9Binary = Path.GetTempFileName();
- File.WriteAllBytes(arm9Binary, arm9Data);
- arm9.path = arm9Binary;
- arm9.offset = 0;
- arm9.size = (uint)arm9Data.Length;
- }
- else Console.WriteLine("Overlays9 has been modified but can't update hashes in ARM9.bin!");
- }
- }
-
- public void ImportArm9iData(string filePath, uint offset, uint size)
- {
- uint sizePad = size;
- if (size % 0x10 != 0) sizePad += 0x10 - size % 0x10;
- this.DSi9Data = new byte[sizePad];
- for (long i = size; i < sizePad; i++) this.DSi9Data[i] = 0xFF;
-
- Stream str = File.OpenRead(filePath);
- str.Position = offset;
- str.Read(this.DSi9Data, 0, (int)size);
- str.Close();
- }
-
- public void ImportArm7iData(string filePath, uint offset, uint size)
- {
- uint sizePad = size;
- if (size % 0x10 != 0) sizePad += 0x10 - size % 0x10;
- this.DSi7Data = new byte[sizePad];
- for (long i = size; i < sizePad; i++) this.DSi7Data[i] = 0xFF;
-
- Stream str = File.OpenRead(filePath);
- str.Position = offset;
- str.Read(this.DSi7Data, 0, (int)size);
- str.Close();
- }
-
- public void Write(ref BinaryWriter bw, Estructuras.ROMHeader hdr, out byte[] digest_master_hash)
- {
- // Write DSi ARM sections and padding
- while (bw.BaseStream.Position < hdr.sector_hashtable_start) bw.Write((byte)0xFF);
- bw.BaseStream.Position = hdr.sector_hashtable_start + hdr.sector_hashtable_size;
- while (bw.BaseStream.Position < hdr.block_hashtable_start) bw.Write((byte)0xFF);
- bw.BaseStream.Position = hdr.block_hashtable_start + hdr.block_hashtable_size;
- while (bw.BaseStream.Position < hdr.dsi9_rom_offset) bw.Write((byte)0xFF);
- if (this.Header2Data != null && !hdr.trimmedRom)
- //if (this.Header2Data != null)
- {
- bw.BaseStream.Position = hdr.digest_twl_start - 0x3000;
- for (int j = 0; j < 3; j++) bw.Write(this.Header2Data[j]);
- }
-
- bw.Write(this.DSi9Data, 0, this.DSi9Data.Length);
- while (bw.BaseStream.Position < hdr.dsi7_rom_offset) bw.Write((byte)0xFF);
- bw.Write(this.DSi7Data, 0, this.DSi7Data.Length);
- while (bw.BaseStream.Position < hdr.total_rom_size) bw.Write((byte)0xFF);
- long pos = bw.BaseStream.Position;
-
- // Compute NTR Secure Area Hashtable
- int i = 0;
- HMACSHA1 hmac = new HMACSHA1(TWL.hmac_sha1_key);
- BinaryReader br = new BinaryReader(bw.BaseStream);
- br.BaseStream.Position = hdr.digest_ntr_start;
- byte[] saData = br.ReadBytes(0x4000);
- uint gameCode = BitConverter.ToUInt32(Encoding.ASCII.GetBytes(hdr.gameCode), 0);
- SAEncryptor.EncryptSecureArea(gameCode, saData);
- while (i < 0x4000 / hdr.digest_sector_size)
- {
- byte[] hash = hmac.ComputeHash(saData, (int)(i * hdr.digest_sector_size), (int)hdr.digest_sector_size);
- bw.BaseStream.Position = hdr.sector_hashtable_start + i * 0x14;
- bw.Write(hash);
- i++;
- }
-
- // Compute NTR Hashtable
- br.BaseStream.Position = hdr.digest_ntr_start + 0x4000;
- while (br.BaseStream.Position < hdr.digest_ntr_start + hdr.digest_ntr_size)
- {
- byte[] hash = hmac.ComputeHash(br.ReadBytes((int)hdr.digest_sector_size));
- long tmp = br.BaseStream.Position;
- bw.BaseStream.Position = hdr.sector_hashtable_start + i * 0x14;
- bw.Write(hash);
- br.BaseStream.Position = tmp;
- i++;
- }
-
- // Compute TWL Hashtable
- br.BaseStream.Position = hdr.digest_twl_start;
- while (br.BaseStream.Position < hdr.digest_twl_start + hdr.digest_twl_size)
- {
- byte[] hash = hmac.ComputeHash(br.ReadBytes((int)hdr.digest_sector_size));
- long tmp = br.BaseStream.Position;
- bw.BaseStream.Position = hdr.sector_hashtable_start + i * 0x14;
- bw.Write(hash);
- br.BaseStream.Position = tmp;
- i++;
- }
-
- // Compute Secondary Hashtable
- i = 0;
- br.BaseStream.Position = hdr.sector_hashtable_start;
- while (br.BaseStream.Position < hdr.sector_hashtable_start + hdr.sector_hashtable_size)
- {
- byte[] hash = hmac.ComputeHash(br.ReadBytes((int)hdr.digest_block_sectorcount * 0x14));
- long tmp = br.BaseStream.Position;
- bw.BaseStream.Position = hdr.block_hashtable_start + i * 0x14;
- bw.Write(hash);
- br.BaseStream.Position = tmp;
- i++;
- }
-
- // Compute Master Hashtable
- br.BaseStream.Position = hdr.block_hashtable_start;
- digest_master_hash = hmac.ComputeHash(br.ReadBytes((int)hdr.block_hashtable_size));
-
- // Encrypt DSi sections
- if (this.twlEncrypted)
- {
- byte[] key = AES128KeyGenerate(hdr);
- byte[] counter9 = new byte[16];
- byte[] counter7 = new byte[16];
- Array.Copy(hdr.hmac_arm9, 0, counter9, 0, 16);
- Array.Copy(hdr.hmac_arm7, 0, counter7, 0, 16);
- bw.BaseStream.Position = hdr.dsi9_rom_offset;
- if (hdr.modcrypt1_size > 0) bw.Write(AES128CTRCrypt(key, counter9, this.DSi9Data, 0, hdr.modcrypt1_size));
- bw.BaseStream.Position = hdr.dsi7_rom_offset;
- if (hdr.modcrypt2_size > 0) bw.Write(AES128CTRCrypt(key, counter7, this.DSi7Data, 0, hdr.modcrypt2_size));
- }
-
- bw.BaseStream.Position = pos;
- }
-
- public static void UpdateHeaderSignatures(
- ref BinaryWriter bw,
- ref Estructuras.ROMHeader header,
- string header_file,
- bool keep_original)
- {
- long pos = bw.BaseStream.Position;
-
- // Update digest master hash
- bw.BaseStream.Position = 0x328;
- bw.Write(header.hmac_digest_master);
-
- // Read signed header data
- BinaryReader br = new BinaryReader(File.OpenRead(header_file));
- byte[] hdrSignedData = br.ReadBytes(0xE00);
- Array.Copy(header.hmac_digest_master, 0, hdrSignedData, 0x328, 0x14);
- br.Close();
-
- // Verify RSA Signature
- RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);
- RSAParameters rsaKey = new RSAParameters();
- rsaKey.Exponent = new byte[] { 1, 0, 1 };
- rsaKey.Modulus = (byte[])TWL.rsaPublicKey.Clone();
- rsaKey.D = null; // In future: here set Private key
- rsa.ImportParameters(rsaKey);
- bool verify = rsa.VerifyData(hdrSignedData, new SHA1CryptoServiceProvider(), header.rsa_signature);
- if (!verify)
- {
- // RSA encrypt signature
- if (rsaKey.D != null)
- {
- header.rsa_signature = rsa.SignData(hdrSignedData, new SHA1CryptoServiceProvider());
- }
- else
- {
- // Calc SHA1 hash
- SHA1 sha1 = new SHA1CryptoServiceProvider();
- byte[] hash = sha1.ComputeHash(hdrSignedData);
- //Array.Reverse(hash);
- sha1.Clear();
- sha1.Dispose();
-
+ }
+ }
+
+ // Calc SHA1-HMAC of overlays9
+ HMACSHA1 hmac = new HMACSHA1(TWL.hmac_sha1_key);
+ this.Overlays9Sha1Hmac = new byte[overlays.Length][];
+ for (int i = 0; i < overlays.Length; i++)
+ {
+ br.BaseStream.Position = overlays[i].offset;
+ byte[] ovlData = br.ReadBytes((int)overlays[i].size);
+ this.Overlays9Sha1Hmac[i] = hmac.ComputeHash(ovlData, 0, ovlData.Length);
+ }
+
+ // Check for encryption modcrypt section
+ this.twlEncrypted = false; // (hdr.twlInternalFlags & 2) > 0;
+ if (hdr.modcrypt1_start >= hdr.digest_twl_start && hdr.modcrypt1_start < 0xFFFFFFFF)
+ {
+ uint modcryptHashedSectorIndex = (hdr.modcrypt1_start - hdr.digest_twl_start) / hdr.digest_sector_size;
+ uint modcryptHashedSectorOff = modcryptHashedSectorIndex * hdr.digest_sector_size;
+ uint hashOff = modcryptHashedSectorIndex * 0x14;
+
+ br.BaseStream.Position = hdr.digest_twl_start + modcryptHashedSectorOff;
+ byte[] firstModcryptBlock = br.ReadBytes((int)hdr.digest_sector_size);
+ byte[] hash = hmac.ComputeHash(firstModcryptBlock, 0, (int)hdr.digest_sector_size);
+ for (int i = 0; i < 20 && !twlEncrypted; i++) twlEncrypted = hash[i] != Hashtable1Data[this.firstDSiHashOffset + hashOff + i];
+ }
+ br.Close();
+
+ // Decrypt modcrypt sections
+ if (this.twlEncrypted)
+ {
+ byte[] key = AES128KeyGenerate(hdr);
+ byte[] counter = new byte[16];
+ if (hdr.modcrypt1_size > 0 && hdr.modcrypt1_size < 0xFFFFFFFF)
+ {
+ Array.Copy(hdr.hmac_arm9, 0, counter, 0, 16);
+ uint offset = hdr.modcrypt1_start - hdr.dsi9_rom_offset;
+ byte[] decrypted = AES128CTRCrypt(key, counter, this.DSi9Data, offset, hdr.modcrypt1_size);
+ if (offset == 0 && decrypted.Length == this.DSi9Data.Length) this.DSi9Data = decrypted;
+ else Array.Copy(decrypted, 0, this.DSi9Data, offset, decrypted.Length);
+ }
+
+ if (hdr.modcrypt2_size > 0 && hdr.modcrypt2_size < 0xFFFFFFFF)
+ {
+ Array.Copy(hdr.hmac_arm7, 0, counter, 0, 16);
+ uint offset = hdr.modcrypt2_start - hdr.dsi7_rom_offset;
+ byte[] decrypted = AES128CTRCrypt(key, counter, this.DSi7Data, offset, hdr.modcrypt2_size);
+ if (offset == 0 && decrypted.Length == this.DSi7Data.Length) this.DSi7Data = decrypted;
+ else Array.Copy(decrypted, 0, this.DSi7Data, offset, decrypted.Length);
+ }
+ }
+
+ hmac.Clear();
+ hmac.Dispose();
+ this.twlEncrypted = (hdr.twlInternalFlags & 2) > 0;
+ }
+
+ public void UpdateOverlays9Sha1Hmac(ref sFile arm9, Estructuras.ROMHeader hdr, List ov9, HMACSHA1 hmac = null)
+ {
+ if (hmac == null) hmac = new HMACSHA1(hmac_sha1_key);
+ byte[][] hashes = new byte[ov9.Count][];
+ bool changed = false;
+ for (int i = 0; i < ov9.Count; i++)
+ {
+ Stream str = File.OpenRead(ov9[i].path);
+ byte[] buffer = new byte[ov9[i].size];
+ str.Position = ov9[i].offset;
+ str.Read(buffer, 0, buffer.Length);
+ str.Close();
+ hashes[i] = hmac.ComputeHash(buffer);
+ for (int j = 0; j < hashes[i].Length && !changed; j++) changed |= hashes[i][j] != this.Overlays9Sha1Hmac[i][j];
+ }
+
+ if (changed)
+ {
+ // Read arm9
+ BinaryReader br = new BinaryReader(File.OpenRead(arm9.path));
+ br.BaseStream.Position = arm9.offset;
+ byte[] arm9Data = br.ReadBytes((int)arm9.size);
+ br.Close();
+
+ // Decompress arm9
+ hdr.ARM9size = arm9.size;
+ uint initptr = BitConverter.ToUInt32(hdr.reserved2, 0) & 0x3FFF;
+ uint hdrptr = BitConverter.ToUInt32(arm9Data, (int)initptr + 0x14) - hdr.ARM9ramAddress;
+ uint cmparm9 = ARM9BLZ.Decompress(arm9Data, hdr, out arm9Data);
+
+ // Get hmac offset
+ uint offset = 0;
+ uint end = BitConverter.ToUInt32(arm9Data, (int)initptr + 8) - hdr.ARM9ramAddress;
+ for (long i = end - 0x14 * ov9.Count; i >= 0 && offset == 0; i--)
+ {
+ bool cond = arm9Data[i] == this.Overlays9Sha1Hmac[0][0];
+ for (int j = 1; j < 20 && cond; j++) cond = arm9Data[i + j] == this.Overlays9Sha1Hmac[0][j];
+ if (cond) offset = (uint)i;
+ }
+
+ // Write new hash
+ if (offset > 0)
+ {
+ for (int i = 0; i < ov9.Count; i++) Array.Copy(hashes[i], 0, arm9Data, offset + i * 0x14, 20);
+ if (cmparm9 == 0) arm9Data = ARM9BLZ.Compress(arm9Data, hdr, arm9.size - hdrptr);
+
+ string arm9Binary = Path.GetTempFileName();
+ File.WriteAllBytes(arm9Binary, arm9Data);
+ arm9.path = arm9Binary;
+ arm9.offset = 0;
+ arm9.size = (uint)arm9Data.Length;
+ }
+ else Console.WriteLine("Overlays9 has been modified but can't update hashes in ARM9.bin!");
+ }
+ }
+
+ public void ImportArm9iData(string filePath, uint offset, uint size)
+ {
+ uint sizePad = size;
+ if (size % 0x10 != 0) sizePad += 0x10 - size % 0x10;
+ this.DSi9Data = new byte[sizePad];
+ for (long i = size; i < sizePad; i++) this.DSi9Data[i] = 0xFF;
+
+ Stream str = File.OpenRead(filePath);
+ str.Position = offset;
+ str.Read(this.DSi9Data, 0, (int)size);
+ str.Close();
+ }
+
+ public void ImportArm7iData(string filePath, uint offset, uint size)
+ {
+ uint sizePad = size;
+ if (size % 0x10 != 0) sizePad += 0x10 - size % 0x10;
+ this.DSi7Data = new byte[sizePad];
+ for (long i = size; i < sizePad; i++) this.DSi7Data[i] = 0xFF;
+
+ Stream str = File.OpenRead(filePath);
+ str.Position = offset;
+ str.Read(this.DSi7Data, 0, (int)size);
+ str.Close();
+ }
+
+ public void Write(ref BinaryWriter bw, Estructuras.ROMHeader hdr, out byte[] digest_master_hash)
+ {
+ // Write DSi ARM sections and padding
+ while (bw.BaseStream.Position < hdr.sector_hashtable_start) bw.Write((byte)0xFF);
+ bw.BaseStream.Position = hdr.sector_hashtable_start + hdr.sector_hashtable_size;
+ while (bw.BaseStream.Position < hdr.block_hashtable_start) bw.Write((byte)0xFF);
+ bw.BaseStream.Position = hdr.block_hashtable_start + hdr.block_hashtable_size;
+ while (bw.BaseStream.Position < hdr.dsi9_rom_offset) bw.Write((byte)0xFF);
+ if (this.Header2Data != null && !hdr.trimmedRom)
+ //if (this.Header2Data != null)
+ {
+ bw.BaseStream.Position = hdr.digest_twl_start - 0x3000;
+ for (int j = 0; j < 3; j++) bw.Write(this.Header2Data[j]);
+ }
+
+ bw.Write(this.DSi9Data, 0, this.DSi9Data.Length);
+ while (bw.BaseStream.Position < hdr.dsi7_rom_offset) bw.Write((byte)0xFF);
+ bw.Write(this.DSi7Data, 0, this.DSi7Data.Length);
+ while (bw.BaseStream.Position < hdr.total_rom_size) bw.Write((byte)0xFF);
+ long pos = bw.BaseStream.Position;
+
+ // Compute NTR Secure Area Hashtable
+ int i = 0;
+ HMACSHA1 hmac = new HMACSHA1(TWL.hmac_sha1_key);
+ BinaryReader br = new BinaryReader(bw.BaseStream);
+ br.BaseStream.Position = hdr.digest_ntr_start;
+ byte[] saData = br.ReadBytes(0x4000);
+ uint gameCode = BitConverter.ToUInt32(Encoding.ASCII.GetBytes(hdr.gameCode), 0);
+ SAEncryptor.EncryptSecureArea(gameCode, saData);
+ while (i < 0x4000 / hdr.digest_sector_size)
+ {
+ byte[] hash = hmac.ComputeHash(saData, (int)(i * hdr.digest_sector_size), (int)hdr.digest_sector_size);
+ bw.BaseStream.Position = hdr.sector_hashtable_start + i * 0x14;
+ bw.Write(hash);
+ i++;
+ }
+
+ // Compute NTR Hashtable
+ br.BaseStream.Position = hdr.digest_ntr_start + 0x4000;
+ while (br.BaseStream.Position < hdr.digest_ntr_start + hdr.digest_ntr_size)
+ {
+ byte[] hash = hmac.ComputeHash(br.ReadBytes((int)hdr.digest_sector_size));
+ long tmp = br.BaseStream.Position;
+ bw.BaseStream.Position = hdr.sector_hashtable_start + i * 0x14;
+ bw.Write(hash);
+ br.BaseStream.Position = tmp;
+ i++;
+ }
+
+ // Compute TWL Hashtable
+ br.BaseStream.Position = hdr.digest_twl_start;
+ while (br.BaseStream.Position < hdr.digest_twl_start + hdr.digest_twl_size)
+ {
+ byte[] hash = hmac.ComputeHash(br.ReadBytes((int)hdr.digest_sector_size));
+ long tmp = br.BaseStream.Position;
+ bw.BaseStream.Position = hdr.sector_hashtable_start + i * 0x14;
+ bw.Write(hash);
+ br.BaseStream.Position = tmp;
+ i++;
+ }
+
+ // Compute Secondary Hashtable
+ i = 0;
+ br.BaseStream.Position = hdr.sector_hashtable_start;
+ while (br.BaseStream.Position < hdr.sector_hashtable_start + hdr.sector_hashtable_size)
+ {
+ byte[] hash = hmac.ComputeHash(br.ReadBytes((int)hdr.digest_block_sectorcount * 0x14));
+ long tmp = br.BaseStream.Position;
+ bw.BaseStream.Position = hdr.block_hashtable_start + i * 0x14;
+ bw.Write(hash);
+ br.BaseStream.Position = tmp;
+ i++;
+ }
+
+ // Compute Master Hashtable
+ br.BaseStream.Position = hdr.block_hashtable_start;
+ digest_master_hash = hmac.ComputeHash(br.ReadBytes((int)hdr.block_hashtable_size));
+
+ // Encrypt DSi sections
+ if (this.twlEncrypted)
+ {
+ byte[] key = AES128KeyGenerate(hdr);
+ byte[] counter9 = new byte[16];
+ byte[] counter7 = new byte[16];
+ Array.Copy(hdr.hmac_arm9, 0, counter9, 0, 16);
+ Array.Copy(hdr.hmac_arm7, 0, counter7, 0, 16);
+ bw.BaseStream.Position = hdr.dsi9_rom_offset;
+ if (hdr.modcrypt1_size > 0) bw.Write(AES128CTRCrypt(key, counter9, this.DSi9Data, 0, hdr.modcrypt1_size));
+ bw.BaseStream.Position = hdr.dsi7_rom_offset;
+ if (hdr.modcrypt2_size > 0) bw.Write(AES128CTRCrypt(key, counter7, this.DSi7Data, 0, hdr.modcrypt2_size));
+ }
+
+ bw.BaseStream.Position = pos;
+ }
+
+ public static void UpdateHeaderSignatures(
+ ref BinaryWriter bw,
+ ref Estructuras.ROMHeader header,
+ string header_file,
+ bool keep_original)
+ {
+ long pos = bw.BaseStream.Position;
+
+ // Update digest master hash
+ bw.BaseStream.Position = 0x328;
+ bw.Write(header.hmac_digest_master);
+
+ // Read signed header data
+ BinaryReader br = new BinaryReader(File.OpenRead(header_file));
+ byte[] hdrSignedData = br.ReadBytes(0xE00);
+ Array.Copy(header.hmac_digest_master, 0, hdrSignedData, 0x328, 0x14);
+ br.Close();
+
+ // Verify RSA Signature
+ RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);
+ RSAParameters rsaKey = new RSAParameters();
+ rsaKey.Exponent = new byte[] { 1, 0, 1 };
+ rsaKey.Modulus = (byte[])TWL.rsaPublicKey.Clone();
+ rsaKey.D = null; // In future: here set Private key
+ rsa.ImportParameters(rsaKey);
+ bool verify = rsa.VerifyData(hdrSignedData, new SHA1CryptoServiceProvider(), header.rsa_signature);
+ if (!verify)
+ {
+ // RSA encrypt signature
+ if (rsaKey.D != null)
+ {
+ header.rsa_signature = rsa.SignData(hdrSignedData, new SHA1CryptoServiceProvider());
+ }
+ else
+ {
+ // Calc SHA1 hash
+ SHA1 sha1 = new SHA1CryptoServiceProvider();
+ byte[] hash = sha1.ComputeHash(hdrSignedData);
+ //Array.Reverse(hash);
+ sha1.Clear();
+ sha1.Dispose();
+
if (!keep_original)
{
// Set unencrypted signature for no$gba compatible
header.rsa_signature = (byte[])TWL.rsaSignatureMask.Clone();
Array.Copy(hash, 0, header.rsa_signature, 0x80 - 0x14, 0x14);
- }
- }
-
- // Write signature
- bw.BaseStream.Position = 0xF80;
- bw.Write(header.rsa_signature, 0, 0x80);
- }
-
- bw.BaseStream.Position = pos;
- }
-
- private static byte[] AES128CTRCrypt(byte[] key, byte[] counter, byte[] data, uint offset, uint size)
- {
- AES128CounterMode aes128 = new AES128CounterMode(counter);
- ICryptoTransform ict = aes128.CreateEncryptor(key, null);
- return ict.TransformFinalBlock(data, (int)offset, (int)size);
- }
-
- private static byte[] AES128KeyGenerate(Estructuras.ROMHeader hdr)
- {
- bool debug = ((hdr.twlInternalFlags & 4) > 0) || ((hdr.appflags[3] & 0x80) > 0);
- if (debug)
- {
- byte[] key = new byte[16];
- Array.Copy(Encoding.ASCII.GetBytes(hdr.gameTitle), 0, key, 0, 12);
- Array.Copy(Encoding.ASCII.GetBytes(hdr.gameCode), 0, key, 12, 4);
- return key;
- }
- else
- {
- byte[] keyX = new byte[16];
- byte[] keyY = new byte[16];
- Array.Copy(Encoding.ASCII.GetBytes("Nintendo"), 0, keyX, 0, 8);
- Array.Copy(Encoding.ASCII.GetBytes(hdr.gameCode), 0, keyX, 8, 4);
- for (int j = 0; j < 4; j++) keyX[12 + j] = (byte)hdr.gameCode[3 - j];
- //Array.Copy(BitConverter.GetBytes(hdr.tid_low), 0, keyX, 12, 4);
- Array.Copy(hdr.hmac_arm9i, 0, keyY, 0, 16);
- return AES128KeyGenerate(keyX, keyY);
- }
- }
-
- private static byte[] AES128KeyGenerate(byte[] keyX, byte[] keyY)
- {
- // Key = ((Key_X XOR Key_Y) + FFFEFB4E295902582A680F5F1A4F3E79h) ROL 42
- byte[] key = new byte[16];
- for (int i = 0; i < 16; i++) key[i] = (byte)(keyX[i] ^ keyY[i]);
-
- UInt64[] tmp = new ulong[2];
- UInt64[] xyKey = new[] { BitConverter.ToUInt64(key, 0), BitConverter.ToUInt64(key, 8) };
- UInt64[] cKey = new[] { BitConverter.ToUInt64(modcryptCmnKey, 0), BitConverter.ToUInt64(modcryptCmnKey, 8) };
- tmp[0] = (cKey[0] >> 1) + (xyKey[0] >> 1) + (cKey[0] & xyKey[0] & 1);
- tmp[0] = tmp[0] >> 63;
- cKey[0] = cKey[0] + xyKey[0];
- cKey[1] = cKey[1] + xyKey[1] + tmp[0];
-
- int shift = 42;
- tmp[0] = cKey[0] << shift;
- tmp[1] = cKey[1] << shift;
- tmp[0] |= (cKey[1] >> (64 - shift));
- tmp[1] |= (cKey[0] >> (64 - shift));
- cKey[0] = tmp[0];
- cKey[1] = tmp[1];
-
- Array.Copy(BitConverter.GetBytes(cKey[0]), 0, key, 0, 8);
- Array.Copy(BitConverter.GetBytes(cKey[1]), 0, key, 8, 8);
-
- return key;
- }
- }
-}
+ }
+ }
+
+ // Write signature
+ bw.BaseStream.Position = 0xF80;
+ bw.Write(header.rsa_signature, 0, 0x80);
+ }
+
+ bw.BaseStream.Position = pos;
+ }
+
+ private static byte[] AES128CTRCrypt(byte[] key, byte[] counter, byte[] data, uint offset, uint size)
+ {
+ AES128CounterMode aes128 = new AES128CounterMode(counter);
+ ICryptoTransform ict = aes128.CreateEncryptor(key, null);
+ return ict.TransformFinalBlock(data, (int)offset, (int)size);
+ }
+
+ private static byte[] AES128KeyGenerate(Estructuras.ROMHeader hdr)
+ {
+ bool debug = ((hdr.twlInternalFlags & 4) > 0) || ((hdr.appflags[3] & 0x80) > 0);
+ if (debug)
+ {
+ byte[] key = new byte[16];
+ Array.Copy(Encoding.ASCII.GetBytes(hdr.gameTitle), 0, key, 0, 12);
+ Array.Copy(Encoding.ASCII.GetBytes(hdr.gameCode), 0, key, 12, 4);
+ return key;
+ }
+ else
+ {
+ byte[] keyX = new byte[16];
+ byte[] keyY = new byte[16];
+ Array.Copy(Encoding.ASCII.GetBytes("Nintendo"), 0, keyX, 0, 8);
+ Array.Copy(Encoding.ASCII.GetBytes(hdr.gameCode), 0, keyX, 8, 4);
+ for (int j = 0; j < 4; j++) keyX[12 + j] = (byte)hdr.gameCode[3 - j];
+ //Array.Copy(BitConverter.GetBytes(hdr.tid_low), 0, keyX, 12, 4);
+ Array.Copy(hdr.hmac_arm9i, 0, keyY, 0, 16);
+ return AES128KeyGenerate(keyX, keyY);
+ }
+ }
+
+ private static byte[] AES128KeyGenerate(byte[] keyX, byte[] keyY)
+ {
+ // Key = ((Key_X XOR Key_Y) + FFFEFB4E295902582A680F5F1A4F3E79h) ROL 42
+ byte[] key = new byte[16];
+ for (int i = 0; i < 16; i++) key[i] = (byte)(keyX[i] ^ keyY[i]);
+
+ UInt64[] tmp = new ulong[2];
+ UInt64[] xyKey = new[] { BitConverter.ToUInt64(key, 0), BitConverter.ToUInt64(key, 8) };
+ UInt64[] cKey = new[] { BitConverter.ToUInt64(modcryptCmnKey, 0), BitConverter.ToUInt64(modcryptCmnKey, 8) };
+ tmp[0] = (cKey[0] >> 1) + (xyKey[0] >> 1) + (cKey[0] & xyKey[0] & 1);
+ tmp[0] = tmp[0] >> 63;
+ cKey[0] = cKey[0] + xyKey[0];
+ cKey[1] = cKey[1] + xyKey[1] + tmp[0];
+
+ int shift = 42;
+ tmp[0] = cKey[0] << shift;
+ tmp[1] = cKey[1] << shift;
+ tmp[0] |= (cKey[1] >> (64 - shift));
+ tmp[1] |= (cKey[0] >> (64 - shift));
+ cKey[0] = tmp[0];
+ cKey[1] = tmp[1];
+
+ Array.Copy(BitConverter.GetBytes(cKey[0]), 0, key, 0, 8);
+ Array.Copy(BitConverter.GetBytes(cKey[1]), 0, key, 8, 8);
+
+ return key;
+ }
+ }
+}
diff --git a/Tinke/Program.cs b/Tinke/Program.cs
index 27ddd51a..59e2963c 100644
--- a/Tinke/Program.cs
+++ b/Tinke/Program.cs
@@ -18,16 +18,20 @@
*
*/
using System;
-//using System.Collections.Generic;
-//using System.Linq;
using System.Windows.Forms;
-//using System.Reflection;
using System.IO;
+using System.Runtime.InteropServices;
namespace Tinke
{
static class Program
{
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern bool AttachConsole(int dwProcessId);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern bool FreeConsole();
+
///
/// Punto de entrada principal para la aplicación.
///
@@ -35,7 +39,7 @@ static class Program
static void Main(string[] args)
{
#region Comprobación de archivos necesarios
- string[] archivos = new string[] { "Ekona.dll", "DSDecmp.dll" };
+ string[] archivos = new string[] { "Ekona.dll", "DSDecmp.dll" , "Be.Windows.Forms.HexBox.dll" };
string faltan = "";
for (int i = 0; i < archivos.Length; i++)
{
@@ -55,5 +59,4 @@ static void Main(string[] args)
Application.Run(new Sistema());
}
}
-
}
diff --git a/Tinke/Sistema.cs b/Tinke/Sistema.cs
index 2cc4f5da..0c06db4c 100644
--- a/Tinke/Sistema.cs
+++ b/Tinke/Sistema.cs
@@ -62,12 +62,31 @@ public Sistema()
// The IE control of the Debug windows doesn't work in Mono
isMono = (Type.GetType("Mono.Runtime") != null);
+ if (Environment.GetCommandLineArgs().Length == 2 && (Environment.GetCommandLineArgs()[1] == "-h" || Environment.GetCommandLineArgs()[1] == "--help"))
+ {
+ Program.AttachConsole(-1);
+ Console.WriteLine("\n" + this.Text);
+ Console.WriteLine("Usage: Tinke.exe rom_name [option]");
+ Console.WriteLine("options:");
+ Console.WriteLine("-x: Extract all files from nds rom");
+ Console.WriteLine("-r: Replace all nitrofs files by dir, need -o to set an output rom path(-o Only allowed after -r)");
+ Console.WriteLine("-h or --help: Show this message, must be the first param...");
+ Program.FreeConsole();
+ SendKeys.SendWait("{ENTER}");
+ }
+
sb = new StringBuilder();
TextWriter tw = new StringWriter(sb);
tw.NewLine = "
";
- if (!isMono)
+ if (!isMono && !(Environment.GetCommandLineArgs().Length >= 3 && (Environment.GetCommandLineArgs()[2] == "-x" || Environment.GetCommandLineArgs()[2] == "-r")))
Console.SetOut(tw);
+ if (Environment.GetCommandLineArgs().Length >= 3 && (Environment.GetCommandLineArgs()[2] == "-x" || Environment.GetCommandLineArgs()[2] == "-r"))
+ {
+ Program.AttachConsole(-1);
+ Console.WriteLine("\n" + this.Text);
+ }
+
#region Language
if (!File.Exists(Application.StartupPath + Path.DirectorySeparatorChar + "Tinke.xml"))
{
@@ -144,11 +163,47 @@ void Sistema_Load(object sender, EventArgs e)
filesToRead[0] = o.SelectedPath;
o.Dispose();
}
+ else if (Environment.GetCommandLineArgs()[1] == "-h" || Environment.GetCommandLineArgs()[1] == "--help")
+ {
+ Application.Exit();
+ return;
+ }
else
filesToRead[0] = Environment.GetCommandLineArgs()[1];
}
else if (Environment.GetCommandLineArgs().Length >= 3)
{
+ if (Environment.GetCommandLineArgs()[2] == "-x")
+ {
+ filesToRead[0] = Environment.GetCommandLineArgs()[1];
+ ReadGame(filesToRead[0]);
+ sFolder folderSelect = accion.Root;
+
+ if (Environment.GetCommandLineArgs().Length > 3 && Environment.GetCommandLineArgs()[3] is string)
+ {
+ Directory.CreateDirectory(Environment.GetCommandLineArgs()[3] + Path.DirectorySeparatorChar + folderSelect.name);
+ RecursivoExtractFolder(folderSelect, Environment.GetCommandLineArgs()[3] + Path.DirectorySeparatorChar + folderSelect.name);
+ Console.WriteLine("Extract all files to " + Environment.GetCommandLineArgs()[3] + Path.DirectorySeparatorChar + folderSelect.name);
+ } else
+ Console.WriteLine("Param error...");
+ Program.FreeConsole();
+ SendKeys.SendWait("{ENTER}");
+ Application.Exit();
+ } else if (Environment.GetCommandLineArgs()[2] == "-r" && Environment.GetCommandLineArgs().Length > 5 && Environment.GetCommandLineArgs()[4] == "-o")
+ {
+ filesToRead[0] = Environment.GetCommandLineArgs()[1];
+ ReadGame(filesToRead[0]);
+ if (Environment.GetCommandLineArgs()[3] is string)
+ {
+ ChangeByDir(Environment.GetCommandLineArgs()[3]);
+ }
+ // parse saving args
+ for(int i = 5; i < Environment.GetCommandLineArgs().Length; i++)
+ {
+
+ }
+ return;
+ }
filesToRead = new String[Environment.GetCommandLineArgs().Length - 1];
Array.Copy(Environment.GetCommandLineArgs(), 1, filesToRead, 0, filesToRead.Length);
}
@@ -1444,6 +1499,8 @@ private void btnSaveROM_Click(object sender, EventArgs e)
* Files...
*/
bool keep_original = false;
+ bool a9_recomp = false;
+ bool a9_bestcomp = false;
Nitro.Estructuras.ROMHeader header = romInfo.Cabecera;
Dialog.SaveOptions dialog = new Dialog.SaveOptions();
@@ -1453,6 +1510,10 @@ private void btnSaveROM_Click(object sender, EventArgs e)
keep_original = true;
if (dialog.IsSafeTrim)
header.trimmedRom = true;
+ if (dialog.IsReCompress)
+ a9_recomp = true;
+ if (dialog.IsBetterCompress)
+ a9_bestcomp = true;
Thread create = new Thread(ThreadEspera)
{
@@ -1533,16 +1594,19 @@ private void btnSaveROM_Click(object sender, EventArgs e)
header.secureCRC16 = SecureArea.CalcCRC(this.secureArea.EncryptedData, gameCode);
}
- bool cmparm9 = true;
+ uint cmparm9 = 0;
if (!ov9Sha1Hmac_updated)
{
uint initptr = BitConverter.ToUInt32(header.reserved2, 0) & 0x3FFF;
uint hdrptr = BitConverter.ToUInt32(arm9Data, (int)initptr + 0x14) - header.ARM9ramAddress;
byte[] arm9Data_dec;
cmparm9 = ARM9BLZ.Decompress(arm9Data, header, out arm9Data_dec);
- if (!cmparm9)
+ if (cmparm9 == 0 && a9_recomp)
+ {
+ arm9Data = ARM9BLZ.Compress(arm9Data, header, 0, a9_bestcomp);
+ } else if (cmparm9 == 1 && a9_recomp)
{
- arm9Data = ARM9BLZ.Compress(arm9Data_dec, header, 0);
+ arm9Data = ARM9BLZ.Compress(arm9Data_dec, header, 0, a9_bestcomp);
}
}
@@ -1551,7 +1615,7 @@ private void btnSaveROM_Click(object sender, EventArgs e)
bw.Flush();
br.Close();
- if (!ov9Sha1Hmac_updated && !cmparm9)
+ if (!ov9Sha1Hmac_updated && a9_recomp)
{
arm9.path = arm9Binary;
arm9.offset = 0;
@@ -1627,7 +1691,6 @@ private void btnSaveROM_Click(object sender, EventArgs e)
Console.WriteLine(Tools.Helper.GetTranslation("Messages", "S09"), new FileInfo(arm9Binary).Length);
-
// Escribismo el ARM7 Binary
string arm7Binary = Path.GetTempFileName();
string overlays7 = Path.GetTempFileName();
@@ -1690,7 +1753,6 @@ private void btnSaveROM_Click(object sender, EventArgs e)
bw.Close();
Console.WriteLine(Tools.Helper.GetTranslation("Messages", "S09"), new FileInfo(arm7Binary).Length);
-
// Escribimos el FNT (File Name Table)
string fileFNT = Path.GetTempFileName();
Console.Write("\tFile Name Table (FNT)...");
@@ -1723,7 +1785,7 @@ private void btnSaveROM_Click(object sender, EventArgs e)
// Escribimos el banner
string banner = Path.GetTempFileName();
header.banner_size = Nitro.NDS.EscribirBanner(banner, romInfo.Banner);
-
+
// Escribimos el FAT (File Allocation Table)
string fileFAT = Path.GetTempFileName();
header.FAToffset = currPos;
@@ -1865,15 +1927,8 @@ private void btnSaveROM_Click(object sender, EventArgs e)
o.DefaultExt = ".nds";
o.Filter = "Nintendo DS ROM (*.nds)|*.nds";
o.OverwritePrompt = true;
- Open_Dialog:
if (o.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
- if (o.FileName == accion.ROMFile)
- {
- MessageBox.Show(Tools.Helper.GetTranslation("Sistema", "S44"));
- goto Open_Dialog;
- }
-
Thread saverom = new Thread(ThreadEspera)
{
IsBackground = true
@@ -1921,7 +1976,7 @@ private void btnSaveROM_Click(object sender, EventArgs e)
}
sb.Length = 0;
}
-
+
// Borramos archivos ya innecesarios
File.Delete(header_file);
File.Delete(arm9Binary);
@@ -1932,10 +1987,6 @@ private void btnSaveROM_Click(object sender, EventArgs e)
File.Delete(fileFAT);
File.Delete(banner);
File.Delete(files);
-
- //if (!isMono)
- //debug.Add_Text(sb.ToString());
- //sb.Length = 0;
}
private void btnImport_Click(object sender, EventArgs e)
{
@@ -2249,11 +2300,7 @@ private void toolStripAbrirFat_Click(object sender, EventArgs e)
if (!isMono)
{
- try
- {
- espera.Close();
- }
- catch { };
+ CloseEspera(wait);
debug.Add_Text(sb.ToString());
}
sb.Length = 0;
@@ -2502,30 +2549,10 @@ private void btnDesplazar_Click(object sender, EventArgs e)
btnDesplazar.Text = ">>>>>";
}
}
- private void btnImport1_Click(object sender, EventArgs e)
+ private void ChangeByDir(string files_path)
{
- Thread matching = new Thread(ThreadEspera)
- {
- IsBackground = true
- };
- if (!isMono)
- matching.Start("S08");
-
- FolderBrowserDialog FBD = new FolderBrowserDialog
- {
- Description = Tools.Helper.GetTranslation("Sistema", "S47"),
- ShowNewFolderButton = false
- };
- if (FBD.ShowDialog() != DialogResult.OK)
- {
- if (!isMono)
- CloseEspera(matching);
- return;
- }
-
- Console.WriteLine(FBD.SelectedPath);
List files = new List();
- files = GetAllSubFiles(FBD.SelectedPath, files);
+ files = GetAllSubFiles(files_path, files);
foreach (string currFile in files)
{
string nstr;
@@ -2569,12 +2596,32 @@ private void btnImport1_Click(object sender, EventArgs e)
accion.Change_File(fileToBeChanged.id, currFile);
Console.WriteLine(currFile);
}
+ }
+ private void btnImport1_Click(object sender, EventArgs e)
+ {
+ Thread matching = new Thread(ThreadEspera)
+ {
+ IsBackground = true
+ };
if (!isMono)
- try
- {
- espera.Close();
- }
- catch { };
+ matching.Start("S08");
+
+ FolderBrowserDialog FBD = new FolderBrowserDialog
+ {
+ Description = Tools.Helper.GetTranslation("Sistema", "S47"),
+ ShowNewFolderButton = false
+ };
+ if (FBD.ShowDialog() != DialogResult.OK)
+ {
+ if (!isMono)
+ CloseEspera(matching);
+ return;
+ }
+
+ Console.WriteLine(FBD.SelectedPath);
+ ChangeByDir(FBD.SelectedPath);
+ if (!isMono)
+ CloseEspera(matching);
}
public static List GetAllSubFiles(string directoryPath, List files)
{
diff --git a/Tinke/Tools/ARM9BLZ.cs b/Tinke/Tools/ARM9BLZ.cs
index c8b7f003..6fb2eed5 100644
--- a/Tinke/Tools/ARM9BLZ.cs
+++ b/Tinke/Tools/ARM9BLZ.cs
@@ -1,89 +1,91 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Tinke.Tools
-{
- using System.IO;
-
- using DSDecmp.Formats;
-
- using Nitro;
-
- class ARM9BLZ
- {
- ///
- /// Decompress ARM9.bin
- ///
- /// Compressed ARM9.bin data
- /// ROM header
- /// Decompressed data
- /// True if the decompression was successful.
- public static bool Decompress(byte[] arm9Data, Estructuras.ROMHeader hdr, out byte[] decompressed)
- {
- decompressed = arm9Data;
- uint nitrocode_length = 0;
- if (arm9Data[arm9Data.Length - 0xC] == 0x21 && arm9Data[arm9Data.Length - 0xB] == 0x06
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tinke.Tools
+{
+ using System.IO;
+
+ using DSDecmp.Formats;
+
+ using Nitro;
+
+ class ARM9BLZ
+ {
+ ///
+ /// Decompress ARM9.bin
+ ///
+ /// Compressed ARM9.bin data
+ /// ROM header
+ /// Decompressed data
+ /// 0 = uncompressed; 1 = compressed
+ public static uint Decompress(byte[] arm9Data, Estructuras.ROMHeader hdr, out byte[] decompressed)
+ {
+ decompressed = arm9Data;
+ uint nitrocode_length = 0;
+ if (arm9Data[arm9Data.Length - 0xC] == 0x21 && arm9Data[arm9Data.Length - 0xB] == 0x06
&& arm9Data[arm9Data.Length - 0xA] == 0xC0 && arm9Data[arm9Data.Length - 0x9] == 0xDE)
{
nitrocode_length = 0x0C; //Nitrocode found.
- }
- uint initptr = BitConverter.ToUInt32(hdr.reserved2, 0) & 0x3FFF;
- uint hdrptr = BitConverter.ToUInt32(arm9Data, (int)initptr + 0x14);
+ }
+ uint initptr = BitConverter.ToUInt32(hdr.reserved2, 0) & 0x3FFF;
+ uint hdrptr = BitConverter.ToUInt32(arm9Data, (int)initptr + 0x14);
if (initptr == 0)
{
hdrptr = hdr.ARM9ramAddress + hdr.ARM9size;
- }
- uint postSize = (uint)arm9Data.Length - (hdrptr - hdr.ARM9ramAddress);
- bool cmparm9 = hdrptr > hdr.ARM9ramAddress && hdrptr + nitrocode_length >= hdr.ARM9ramAddress + arm9Data.Length;
- if (cmparm9)
- {
- Stream input = new MemoryStream(arm9Data);
- MemoryStream output = new MemoryStream();
-
- LZOvl blz = new LZOvl();
- blz.Decompress(input, hdrptr - hdr.ARM9ramAddress, output);
- output.Write(arm9Data, arm9Data.Length - (int)postSize, (int)postSize);
- input.Close();
- decompressed = output.ToArray();
- cmparm9 = false;
-
- input.Close();
- output.Close();
- }
-
- return cmparm9;
- }
-
- ///
- /// Compress ARM9.bin
- ///
- /// Uncompressed ARM9.bin data
- /// ROM header
- /// Data size from the end what will be ignored.
- /// Compressed data with uncompressed Secure Area (first 0x4000 bytes).
- public static byte[] Compress(byte[] arm9Data, Estructuras.ROMHeader hdr, uint postSize = 0)
- {
- Stream input = new MemoryStream(arm9Data);
- input.Position = 0x4000;
- MemoryStream output = new MemoryStream();
- output.Write(arm9Data, 0, 0x4000);
- LZOvl blz = new LZOvl();
- blz.Compress(input, input.Length - 0x4000, output);
- input.Close();
- output.Write(arm9Data, arm9Data.Length - (int)postSize, (int)postSize);
- byte[] result = output.ToArray();
- output.Close();
-
- // Update size
- uint initptr = BitConverter.ToUInt32(hdr.reserved2, 0) & 0x3FFF;
- if (initptr > 0)
- {
- uint hdrptr = (uint)result.Length - postSize + hdr.ARM9ramAddress;
- Array.Copy(BitConverter.GetBytes(hdrptr), 0, result, initptr + 0x14, 4);
- }
-
- return result;
- }
- }
-}
+ }
+ uint postSize = (uint)arm9Data.Length - (hdrptr - hdr.ARM9ramAddress);
+ bool cmparm9 = hdrptr > hdr.ARM9ramAddress && hdrptr + nitrocode_length >= hdr.ARM9ramAddress + arm9Data.Length;
+ if (cmparm9)
+ {
+ Stream input = new MemoryStream(arm9Data);
+ MemoryStream output = new MemoryStream();
+
+ LZOvl blz = new LZOvl();
+ blz.Decompress(input, hdrptr - hdr.ARM9ramAddress, output);
+ output.Write(arm9Data, arm9Data.Length - (int)postSize, (int)postSize);
+ input.Close();
+ decompressed = output.ToArray();
+
+ input.Close();
+ output.Close();
+ return 1;
+ }
+
+ return 0;
+ }
+
+ ///
+ /// Compress ARM9.bin
+ ///
+ /// Uncompressed ARM9.bin data
+ /// ROM header
+ /// Data size from the end what will be ignored.
+ /// 0 = BLZ; 1 = BLZ-Cue
+ /// Compressed data with uncompressed Secure Area (first 0x4000 bytes).
+ public static byte[] Compress(byte[] arm9Data, Estructuras.ROMHeader hdr, uint postSize = 0, bool method = false)
+ {
+ Stream input = new MemoryStream(arm9Data);
+ input.Position = 0x4000;
+ MemoryStream output = new MemoryStream();
+ output.Write(arm9Data, 0, 0x4000);
+ LZOvl blz = new LZOvl();
+ LZOvl.LookAhead = method;
+ blz.Compress(input, input.Length - 0x4000, output);
+ input.Close();
+ output.Write(arm9Data, arm9Data.Length - (int)postSize, (int)postSize);
+ byte[] result = output.ToArray();
+ output.Close();
+
+ // Update size
+ uint initptr = BitConverter.ToUInt32(hdr.reserved2, 0) & 0x3FFF;
+ if (initptr > 0)
+ {
+ uint hdrptr = (uint)result.Length - postSize + hdr.ARM9ramAddress;
+ Array.Copy(BitConverter.GetBytes(hdrptr), 0, result, initptr + 0x14, 4);
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/Tinke/langs/en-us.xml b/Tinke/langs/en-us.xml
index 72c33c00..2fccd251 100644
--- a/Tinke/langs/en-us.xml
+++ b/Tinke/langs/en-us.xml
@@ -425,6 +425,8 @@
Cancel
Safe Trim
Keep Original RSA SHA1 Signature
+ Recompress ARM9 binary (BLZ)
+ Better compress method (BLZ-Cue)
File
diff --git a/Tinke/langs/es-es.xml b/Tinke/langs/es-es.xml
index e7c895eb..8e883002 100644
--- a/Tinke/langs/es-es.xml
+++ b/Tinke/langs/es-es.xml
@@ -429,6 +429,8 @@
Cancelar
Safe Trim
Keep Original RSA SHA1 Signature
+ Recompress ARM9 binary (BLZ)
+ Better compress method (BLZ-Cue)
Archivo
diff --git a/Tinke/langs/fr-fr.xml b/Tinke/langs/fr-fr.xml
index 260cd726..c4496857 100644
--- a/Tinke/langs/fr-fr.xml
+++ b/Tinke/langs/fr-fr.xml
@@ -425,6 +425,8 @@
Annuler
Safe Trim
Keep Original RSA SHA1 Signature
+ Recompress ARM9 binary (BLZ)
+ Better compress method (BLZ-Cue)
Archive
diff --git a/Tinke/langs/it-it.xml b/Tinke/langs/it-it.xml
index 8ebeb578..b591a43e 100644
--- a/Tinke/langs/it-it.xml
+++ b/Tinke/langs/it-it.xml
@@ -424,6 +424,8 @@
Cancella
Safe Trim
Keep Original RSA SHA1 Signature
+ Recompress ARM9 binary (BLZ)
+ Better compress method (BLZ-Cue)
File
diff --git a/Tinke/langs/zh-hans.xml b/Tinke/langs/zh-hans.xml
index 134dc29b..0e79d242 100644
--- a/Tinke/langs/zh-hans.xml
+++ b/Tinke/langs/zh-hans.xml
@@ -422,6 +422,8 @@
取消
安全裁剪
保持原始的 RSA SHA1 签名
+ 重压缩 ARM9 文件 (BLZ 算法)
+ 更好的压缩率算法 (BLZ-Cue)
文件
diff --git a/changelog.txt b/changelog.txt
index 208ee37f..ae720ff7 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -13,10 +13,12 @@ TinkeDSi 0.9.5 (Made by R-YaTian)
* DSDecmp: Add and use CUE's BLZ_Encoder, clean old method
* Add saveoptions window before saving rom (Allow keep original RSA signature, safe trim the rom)
* Allow opening .SRL .IDS .DSI .APP files
-* WIP: Improve ARM9BLZ compression logic
+* Improve ARM9BLZ compression logic
* Add McDonalds Maker Code to Estructuras.makerCode
* Image: Set gimp_error to default false, hope this will fix palette exporting for anything that's not GIMP
* 3DModels: Update to OpenTK 3.3.3, fix bug on fullscreen btn
+* Improved SF Feather Plugin (By @mn1712trungson)
+* Core: Improve Nitrocode check when saving rom
TODO: full i18n support (include plugins)
TinkeDSi 0.9.4
diff --git a/compile.bat b/compile.bat
index d79516b7..8bf07a51 100644
--- a/compile.bat
+++ b/compile.bat
@@ -41,7 +41,7 @@ REM Get compiler
SET netver=v4.5
SET msbuild_path=%windir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe
SET msbuild=%msbuild_path% /p:Configuration=%conf% /p:TargetFrameworkVersion=%netver%
-SET msbuild_plugin=%msbuild% /p:OutputPath="%build_dir%\Plugins\\"
+SET msbuild_plugin=%msbuild% /p:OutputPath="%build_dir%\Plugins\\" /m
REM Compile program in standard directory, to allow plugins find Ekona
ECHO Compiling base library
@@ -49,7 +49,7 @@ ECHO Compiling base library
REM Compiling program
echo Compiling Tinke
-%msbuild% /p:Platform=%plat% /p:OutputPath="%build_dir%\\" Tinke.sln > error.log || (TYPE error.log & EXIT /B 1)
+%msbuild% /p:Platform=%plat% /p:OutputPath="%build_dir%\\" /m Tinke.sln > error.log || (TYPE error.log & EXIT /B 1)
REM Compiling format plugins
call :compile_plugin "Plugins\Pack\Pack.sln"