Can dump decrypted forest block.

This commit is contained in:
suloku
2015-10-18 17:41:27 +02:00
parent 0687f0a432
commit 40598251fb
2 changed files with 96 additions and 14 deletions

View File

@@ -18,6 +18,7 @@ partial class MainForm
private System.Windows.Forms.TextBox savegamename;
private System.Windows.Forms.Button dump_but;
private System.Windows.Forms.Button inject_but;
private System.Windows.Forms.Button dump_dec_but;
/// <summary>
/// Disposes resources used by the form.
@@ -44,6 +45,7 @@ private void InitializeComponent()
this.savegamename = new System.Windows.Forms.TextBox();
this.dump_but = new System.Windows.Forms.Button();
this.inject_but = new System.Windows.Forms.Button();
this.dump_dec_but = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// loadsave
@@ -86,11 +88,23 @@ private void InitializeComponent()
this.inject_but.UseVisualStyleBackColor = true;
this.inject_but.Click += new System.EventHandler(this.Inject_butClick);
//
// dump_dec_but
//
this.dump_dec_but.Enabled = false;
this.dump_dec_but.Location = new System.Drawing.Point(13, 97);
this.dump_dec_but.Name = "dump_dec_but";
this.dump_dec_but.Size = new System.Drawing.Size(161, 36);
this.dump_dec_but.TabIndex = 5;
this.dump_dec_but.Text = "Dump Entralink Forest Data (decrypted)";
this.dump_dec_but.UseVisualStyleBackColor = true;
this.dump_dec_but.Click += new System.EventHandler(this.Dump_dec_butClick);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(354, 95);
this.ClientSize = new System.Drawing.Size(354, 136);
this.Controls.Add(this.dump_dec_but);
this.Controls.Add(this.savegamename);
this.Controls.Add(this.dump_but);
this.Controls.Add(this.loadsave);

View File

@@ -16,6 +16,23 @@
using System.Windows.Forms;
using System.IO;
/*
Kaphotics info about forest data:
0x850 bytes of data
u16 update counter
u16 checksum
checksum: crc-ccitt (16 bit) over the 0x850 range
encryption seed: last 4 bytes of the 0x850 bytes (the only thing that isn't encrypted!)
encryption method: 32bit lcrng, same used for Pokemon encryption, xor (result >> 16).
The internal structure should be pretty easy to figure out if you just compare it to PokeStock's display. Something like u16 Species, u16 Move.
A species' level is static, determined by a table stored in the ROM (NARC file) afaik.
The one save file I checked had it at 0x22A00, must have been B2W2 (not BW).
*/
namespace BW_Entralink_Forest_tool
{
@@ -38,6 +55,7 @@ public MainForm()
string forestfile;
byte[] savebuffer = new byte[524288];
byte[] forestbuffer = new byte[2304];
byte[] forestbuffer_dec = new byte[2304];
//adapted from Gocario's PHBank (www.github.com/gocario/phbank)
byte[] ccitt16(byte[] data)
@@ -61,6 +79,33 @@ byte[] ccitt16(byte[] data)
return BitConverter.GetBytes(crc);
}
UInt32 LCRNG(UInt32 seed)
// --------------------------------------------------
{
UInt32 a = 0x41c64e6d;
UInt32 c = 0x00006073;
return (UInt32)(((UInt64)seed * (UInt64)a + (UInt64)c)&0x00000000FFFFFFFF);
}
void decryptForest()
// --------------------------------------------------
{
Array.Copy(forestbuffer, forestbuffer_dec, 2304);
UInt32 pv = BitConverter.ToUInt32(forestbuffer_dec, 0x84C);
byte sv = (byte)((((pv & 0x3e000) >> 0xd) % 24)&0x000000FF);
UInt32 seed = pv;
UInt16 tmp;
for (Int32 i = 0x0; i < 0x850; i += 0x2)
{
tmp = BitConverter.ToUInt16(forestbuffer_dec, i);
seed = LCRNG(seed);
tmp ^= (UInt16)((seed >> 16)&0x0000FFFF);
Array.Copy(BitConverter.GetBytes(tmp), 0, forestbuffer_dec, i, 2);
}
}
/// <summary>
/// Reads data into a complete array, throwing an EndOfStreamException
@@ -124,6 +169,20 @@ private void PDR_save_data()
saveFile.Write(savebuffer, 0, savebuffer.Length);
saveFile.Close();
MessageBox.Show("File Saved.", "Save file");
}
}
private void PDR_save_decforest_data()
{ SaveFileDialog saveFD = new SaveFileDialog();
//saveFD.InitialDirectory = "c:\\";
saveFD.Filter = "Entralink Forest Decrypted Data|*.efdd|All Files (*.*)|*.*";
if (saveFD.ShowDialog() == DialogResult.OK)
{
System.IO.FileStream saveFile;
saveFile = new FileStream(saveFD.FileName, FileMode.Create);
//Write file
saveFile.Write(forestbuffer_dec, 0, forestbuffer_dec.Length);
saveFile.Close();
MessageBox.Show("File Saved.", "Save file");
}
}
private void PDR_dump_forest_data()
@@ -141,19 +200,6 @@ private void PDR_dump_forest_data()
MessageBox.Show("Entralink forest data dumped to:\r"+saveFD.FileName+".", "Dump Entralink Forest Data");
}
}
private void PDR_read_forest_data()
{
System.IO.FileStream saveFile;
saveFile = new FileStream(forestfile, FileMode.Open);
if (saveFile.Length != 0x900){
//forestfile = "";
MessageBox.Show("Invalid file length", "Error");
return;
}
ReadWholeArray(saveFile, forestbuffer);
saveFile.Close();
PDR_injectNsave();
}
private void PDR_get_forest_data()
{
OpenFileDialog openFD = new OpenFileDialog();
@@ -168,6 +214,18 @@ private void PDR_get_forest_data()
}
}
private void PDR_read_forest_data()
{
System.IO.FileStream forestFile;
forestFile = new FileStream(forestfile, FileMode.Open);
if (forestFile.Length != 0x900){
//forestfile = "";
MessageBox.Show("Invalid file length", "Error");
return;
}
ReadWholeArray(forestFile, forestbuffer);
forestFile.Close();
}
private void PDR_injectNsave()
{
//Put new forest in both save file slots
@@ -213,9 +271,11 @@ void SavegamenameTextChanged(object sender, EventArgs e)
{
if (savegamename.Text.Length > 0){
dump_but.Enabled = true;
dump_dec_but.Enabled = true;
inject_but.Enabled = true;
}else{
dump_but.Enabled = false;
dump_dec_but.Enabled = false;
inject_but.Enabled = false;
}
@@ -223,6 +283,14 @@ void SavegamenameTextChanged(object sender, EventArgs e)
void Inject_butClick(object sender, EventArgs e)
{
PDR_get_forest_data();
PDR_injectNsave();
}
void Dump_dec_butClick(object sender, EventArgs e)
{
//Copy forest to buffer
Array.Copy(savebuffer, 0x22C00, forestbuffer, 0, 0x900);
decryptForest();
PDR_save_decforest_data();
}
}