- Added prop case editor for BW and B2W2

- Fixed crash when changing flags in MemoryLink.cs
- Embedded grotto table images into executable (no longer needed as separate files)
This commit is contained in:
suloku
2021-03-16 17:54:12 +01:00
parent dbcf569103
commit 06edc5d51c
13 changed files with 8641 additions and 8 deletions

View File

@@ -62,6 +62,10 @@
<Compile Include="Editors\Entralink_DreamWorld.Designer.cs">
<DependentUpon>Entralink_DreamWorld.cs</DependentUpon>
</Compile>
<Compile Include="Editors\Propcase.cs" />
<Compile Include="Editors\Propcase.Designer.cs">
<DependentUpon>Propcase.cs</DependentUpon>
</Compile>
<Compile Include="Editors\Join_avenue.cs" />
<Compile Include="Editors\Join_avenue.Designer.cs">
<DependentUpon>Join_avenue.cs</DependentUpon>
@@ -147,6 +151,9 @@
<EmbeddedResource Include="Editors\MemoryLink.resx">
<DependentUpon>MemoryLink.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Editors\Propcase.resx">
<DependentUpon>Propcase.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Editors\TrainerInfo.resx">
<DependentUpon>TrainerInfo.cs</DependentUpon>
</EmbeddedResource>

View File

@@ -284,7 +284,6 @@ namespace BW_tool
this.groupBox5.ResumeLayout(false);
this.groupBox6.ResumeLayout(false);
this.ResumeLayout(false);
}
}
}

View File

@@ -35,5 +35,6 @@ namespace BW_tool
// TODO: Add constructor code after the InitializeComponent() call.
//
}
}
}

View File

@@ -16,7 +16,9 @@ using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections.Generic;
using System.Reflection;
using System.Resources;
namespace BW_tool
{
@@ -26,6 +28,8 @@ namespace BW_tool
/// </summary>
public partial class Grotto : Form
{
ResourceManager resources = new ResourceManager("BW_tool.Grotto", Assembly.GetExecutingAssembly());
//Hidden Hollow BW2
/* Structure:
The block at 0x23B00 contains rival data and hidden hollow information.
@@ -715,7 +719,8 @@ namespace BW_tool
try
{
pictureBox.Dock = DockStyle.Fill;
pictureBox.Image = Image.FromFile("./grotto_tables/b2_"+Grotto_route.SelectedIndex+".png");
//pictureBox.Image = Image.FromFile("./grotto_tables/b2_"+Grotto_route.SelectedIndex+".png");
pictureBox.Image = (Bitmap)resources.GetObject("b2_"+Grotto_route.SelectedIndex);
pictureBox.SizeMode = PictureBoxSizeMode.StretchImage;
form.Controls.Add(pictureBox);
Size size = new Size(720,300);

File diff suppressed because it is too large Load Diff

View File

@@ -526,7 +526,7 @@ namespace BW_tool
if (status == true)
Data[0x8D] |= (byte) (0x1<<index);
else
Data[0x8D] &= (byte) (~(0x1<<index));
Data[0x8D] &= unchecked((byte) (~(0x1<<index)));
}
public void set_hof(byte[] input)

266
BW_tool/Editors/Propcase.Designer.cs generated Normal file
View File

@@ -0,0 +1,266 @@
/*
* Created by SharpDevelop.
* User: suloku
* Date: 15/03/2021
* Time: 20:37
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
namespace BW_tool
{
partial class PropCase
{
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the form.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
private void InitializeComponent()
{
this.Proplist = new System.Windows.Forms.ComboBox();
this.hasprop_checkbox = new System.Windows.Forms.CheckBox();
this.unloackAllBut = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.propHex = new System.Windows.Forms.Label();
this.Exit_but = new System.Windows.Forms.Button();
this.Saveexit_but = new System.Windows.Forms.Button();
this.spriteBox = new System.Windows.Forms.PictureBox();
this.removeAllBut = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.spriteBox)).BeginInit();
this.SuspendLayout();
//
// Proplist
//
this.Proplist.FormattingEnabled = true;
this.Proplist.Items.AddRange(new object[] {
"Pink Barrette",
"Blue Barrette",
"Red Barrette",
"Blue Flower",
"Crimson Scarf",
"Red Flower",
"Big Barrette",
"Headband",
"Square Glasses",
"Striped Barrette",
"Small Barrette",
"Decorative Ribbon",
"Purse",
"Necklace",
"Gorgeous Flower",
"Round Button",
"Green Barrette",
"Straw Hat",
"Snow Crystal",
"Lonely Flower",
"Paintbrush",
"Beret",
"Whisk",
"Ladle",
"Toy Cake",
"Chef\'s Hat",
"Frying Pan",
"Bib",
"Red Parasol",
"Germ Mask",
"Mallet",
"Colorful Parasol",
"Wrench",
"Lantern",
"Windup Key",
"Helmet",
"Frilly Apron",
"Dressy Tie",
"Lace Cap",
"Scarlet Cape",
"Toy Cutlass",
"Toy Sword",
"Pirate Hat",
"Cowboy Hat",
"Rigid Shield",
"Black Wings",
"Witchy Hat",
"White Wings",
"Umber Belt",
"Horned Helm",
"Trident",
"Magic Wand",
"Red Nose",
"Jester\'s Cap",
"Googly Specs",
"Crown",
"Black Tie",
"Black Cape",
"Gorgeous Specs",
"Top Hat",
"White Domino Mask",
"White Cape",
"Gentleman\'s Hat",
"Cane",
"Striped Tie",
"Pocket Watch",
"Bowtie",
"Tiara",
"Rose",
"Monocle",
"Tie",
"Wig",
"Standing Mike",
"Tambourine",
"Fedora",
"Microphone",
"Maraca",
"Trumpet",
"Laurel Wreath",
"White Pompom",
"Pennant",
"Football",
"Winner\'s Belt",
"Racket",
"Electric Guitar",
"Toy Fishing Rod",
"Smiley-Face Mask",
"Fake Belly Button",
"Professor Hat",
"Hula Skirt",
"Thick Book",
"Bouquet",
"Fake Bone",
"Round Mushroom",
"Shuriken",
"Scarlet Hat",
"Big Bag",
"Candy",
"Fluffy Beard",
"Gift Box"});
this.Proplist.Location = new System.Drawing.Point(26, 28);
this.Proplist.Name = "Proplist";
this.Proplist.Size = new System.Drawing.Size(121, 21);
this.Proplist.TabIndex = 0;
this.Proplist.SelectedIndexChanged += new System.EventHandler(this.ProplistSelectedIndexChanged);
//
// hasprop_checkbox
//
this.hasprop_checkbox.Location = new System.Drawing.Point(168, 28);
this.hasprop_checkbox.Name = "hasprop_checkbox";
this.hasprop_checkbox.Size = new System.Drawing.Size(104, 24);
this.hasprop_checkbox.TabIndex = 1;
this.hasprop_checkbox.Text = "Obtained";
this.hasprop_checkbox.UseVisualStyleBackColor = true;
this.hasprop_checkbox.CheckedChanged += new System.EventHandler(this.Hasprop_checkboxCheckedChanged);
//
// unloackAllBut
//
this.unloackAllBut.Location = new System.Drawing.Point(26, 68);
this.unloackAllBut.Name = "unloackAllBut";
this.unloackAllBut.Size = new System.Drawing.Size(102, 23);
this.unloackAllBut.TabIndex = 2;
this.unloackAllBut.Text = "Unlock all";
this.unloackAllBut.UseVisualStyleBackColor = true;
this.unloackAllBut.Click += new System.EventHandler(this.Button1Click);
//
// label1
//
this.label1.Location = new System.Drawing.Point(26, 94);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(100, 23);
this.label1.TabIndex = 3;
this.label1.Text = "Hex value:";
//
// propHex
//
this.propHex.Location = new System.Drawing.Point(93, 94);
this.propHex.Name = "propHex";
this.propHex.Size = new System.Drawing.Size(290, 23);
this.propHex.TabIndex = 4;
this.propHex.Text = "0x";
//
// Exit_but
//
this.Exit_but.Location = new System.Drawing.Point(26, 111);
this.Exit_but.Name = "Exit_but";
this.Exit_but.Size = new System.Drawing.Size(102, 23);
this.Exit_but.TabIndex = 21;
this.Exit_but.Text = "Exit";
this.Exit_but.UseVisualStyleBackColor = true;
this.Exit_but.Click += new System.EventHandler(this.Exit_butClick);
//
// Saveexit_but
//
this.Saveexit_but.Location = new System.Drawing.Point(133, 111);
this.Saveexit_but.Name = "Saveexit_but";
this.Saveexit_but.Size = new System.Drawing.Size(102, 23);
this.Saveexit_but.TabIndex = 20;
this.Saveexit_but.Text = "Save and Exit";
this.Saveexit_but.UseVisualStyleBackColor = true;
this.Saveexit_but.Click += new System.EventHandler(this.Saveexit_butClick);
//
// spriteBox
//
this.spriteBox.Location = new System.Drawing.Point(254, 18);
this.spriteBox.Name = "spriteBox";
this.spriteBox.Size = new System.Drawing.Size(129, 73);
this.spriteBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
this.spriteBox.TabIndex = 22;
this.spriteBox.TabStop = false;
//
// removeAllBut
//
this.removeAllBut.Location = new System.Drawing.Point(133, 68);
this.removeAllBut.Name = "removeAllBut";
this.removeAllBut.Size = new System.Drawing.Size(102, 23);
this.removeAllBut.TabIndex = 23;
this.removeAllBut.Text = "Remove all";
this.removeAllBut.UseVisualStyleBackColor = true;
this.removeAllBut.Click += new System.EventHandler(this.RemoveAllButClick);
//
// PropCase
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(393, 141);
this.Controls.Add(this.removeAllBut);
this.Controls.Add(this.unloackAllBut);
this.Controls.Add(this.spriteBox);
this.Controls.Add(this.Exit_but);
this.Controls.Add(this.Saveexit_but);
this.Controls.Add(this.propHex);
this.Controls.Add(this.label1);
this.Controls.Add(this.hasprop_checkbox);
this.Controls.Add(this.Proplist);
this.Name = "PropCase";
this.Text = "Props Case editor";
((System.ComponentModel.ISupportInitialize)(this.spriteBox)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
private System.Windows.Forms.Button removeAllBut;
private System.Windows.Forms.PictureBox spriteBox;
private System.Windows.Forms.Button Saveexit_but;
private System.Windows.Forms.Button Exit_but;
private System.Windows.Forms.Label propHex;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button unloackAllBut;
private System.Windows.Forms.CheckBox hasprop_checkbox;
private System.Windows.Forms.ComboBox Proplist;
}
}

160
BW_tool/Editors/Propcase.cs Normal file
View File

@@ -0,0 +1,160 @@
/*
* Created by SharpDevelop.
* User: suloku
* Date: 15/03/2021
* Time: 20:37
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Reflection;
using System.Resources;
namespace BW_tool
{
/// <summary>
/// Description of PropCase.
/// </summary>
public partial class PropCase : Form
{
ResourceManager resources = new ResourceManager("BW_tool.Propcase", Assembly.GetExecutingAssembly());
PROPCASE myProps;
public PropCase()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
myProps = new PROPCASE(MainForm.save.getData(0x1F958, 13));//Same offset for BW1 and BW2. Should update to block management...
Proplist.SelectedIndex = 0;
hasprop_checkbox.Checked = myProps.getProp(Proplist.SelectedIndex);
//propHex.Text = "0x" + BitConverter.ToString(myProps.Data).Replace("-", string.Empty);
propHex.Text = "0x" + BitConverter.ToString(myProps.Data);
//
// TODO: Add constructor code after the InitializeComponent() call.
//
}
Bitmap sprites_data;
void showProp()
{
string cur_sprite = "Prop_"+Proplist.Text+"_Sprite";
cur_sprite = cur_sprite.Replace(" ", "_");
cur_sprite = cur_sprite.Replace("'", string.Empty);
sprites_data = (Bitmap)resources.GetObject(cur_sprite);
spriteBox.Image = sprites_data;
}
public class PROPCASE
{
internal int Size = 13;
internal int max_props = 99;
public int props_offset = 0x1F958;
public byte[] Data;
public PROPCASE(byte[] data = null)
{
Data = data ?? new byte[Size];
}
public byte[] getData(int Offset, int Length)
{
return Data.Skip(Offset).Take(Length).ToArray();
}
public void setData(byte[] input, int Offset)
{
input.CopyTo(Data, Offset);
}
public bool getProp (int Pos)
{
if (Pos >99)
Pos = 99;
int curbyte = Pos/8;
return ((Data[curbyte] & (0x1 << Pos-(curbyte*8)) ) != 0);
}
public void setProp (int Pos, bool Obtained)
{
if (Pos >99)
Pos = 99;
int curbyte = Pos/8;
if (Obtained == true)
Data[curbyte] |= (byte) ( 0x1 << (Pos-(curbyte*8)) );
else
Data[curbyte] &= unchecked ((byte) (~(0x1<< (Pos-(curbyte*8)) )) );
}
}
void ProplistSelectedIndexChanged(object sender, EventArgs e)
{
hasprop_checkbox.Checked = myProps.getProp(Proplist.SelectedIndex);
showProp();
}
void Hasprop_checkboxCheckedChanged(object sender, EventArgs e)
{
myProps.setProp(Proplist.SelectedIndex, hasprop_checkbox.Checked);
propHex.Text = "0x" + BitConverter.ToString(myProps.Data);
}
void Exit_butClick(object sender, EventArgs e)
{
this.Close();
}
void Saveexit_butClick(object sender, EventArgs e)
{
//Check that there's at least one prop
int i = 0;
while(i<100)
{
if (myProps.getProp(i) == true) break;
i++;
if (i==100)
{
MessageBox.Show("Warning! Game will freeze if you have no props. Pink Barrette has been set by default.");
myProps.setProp(0, true); //Set at least one prop
}
}
MainForm.save.setData(myProps.Data, 0x1F958);
//Mirror
MainForm.save.setData(myProps.Data, 0x45958);
//Update Checksum
MainForm.save.block_crc_recalc(42);
this.Close();
}
void Button1Click(object sender, EventArgs e)
{
int i = 0;
for (i=0;i<100;i++)
myProps.setProp(i, true);
propHex.Text = "0x" + BitConverter.ToString(myProps.Data);
hasprop_checkbox.Checked = myProps.getProp(Proplist.SelectedIndex);
showProp();
}
void RemoveAllButClick(object sender, EventArgs e)
{
int i = 0;
for (i=0;i<100;i++)
myProps.setProp(i, false);
propHex.Text = "0x" + BitConverter.ToString(myProps.Data);
hasprop_checkbox.Checked = myProps.getProp(Proplist.SelectedIndex);
showProp();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -72,6 +72,7 @@ namespace BW_tool
this.memory_but = new System.Windows.Forms.Button();
this.dlc_but = new System.Windows.Forms.Button();
this.dr_but = new System.Windows.Forms.Button();
this.prop_but = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// loadsave_but
@@ -157,7 +158,7 @@ namespace BW_tool
// trainer_records_but
//
this.trainer_records_but.Enabled = false;
this.trainer_records_but.Location = new System.Drawing.Point(12, 107);
this.trainer_records_but.Location = new System.Drawing.Point(304, 107);
this.trainer_records_but.Name = "trainer_records_but";
this.trainer_records_but.Size = new System.Drawing.Size(140, 23);
this.trainer_records_but.TabIndex = 8;
@@ -265,12 +266,24 @@ namespace BW_tool
this.dr_but.UseVisualStyleBackColor = true;
this.dr_but.Click += new System.EventHandler(this.Dr_butClick);
//
// prop_but
//
this.prop_but.Enabled = false;
this.prop_but.Location = new System.Drawing.Point(12, 107);
this.prop_but.Name = "prop_but";
this.prop_but.Size = new System.Drawing.Size(140, 23);
this.prop_but.TabIndex = 18;
this.prop_but.Text = "Prop Case";
this.prop_but.UseVisualStyleBackColor = true;
this.prop_but.Click += new System.EventHandler(this.Prop_butClick);
//
// MainForm
//
this.AllowDrop = true;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(503, 239);
this.Controls.Add(this.prop_but);
this.Controls.Add(this.dr_but);
this.Controls.Add(this.dlc_but);
this.Controls.Add(this.memory_but);
@@ -295,7 +308,7 @@ namespace BW_tool
this.DragEnter += new System.Windows.Forms.DragEventHandler(this.MainScreenDragEnter);
this.ResumeLayout(false);
this.PerformLayout();
}
private System.Windows.Forms.Button prop_but;
}
}

View File

@@ -92,6 +92,7 @@ namespace BW_tool
memory_but.Enabled = true;
dlc_but.Enabled = true;
dr_but.Enabled = true;
prop_but.Enabled = true;
}
else if (save.BW)
{
@@ -111,6 +112,7 @@ namespace BW_tool
memory_but.Enabled = false;
dlc_but.Enabled = true;
dr_but.Enabled = false;
prop_but.Enabled = true;
}
else versiontext.Text = "Invalid file";
@@ -211,5 +213,11 @@ namespace BW_tool
Form dr = new DreamRadar();
dr.ShowDialog();
}
void Prop_butClick(object sender, EventArgs e)
{
Form propcase = new PropCase();
propcase.ShowDialog();
}
}
}

View File

@@ -493,6 +493,7 @@ namespace BW_tool
return;
}
//Updates both MAIN and BACKUP crc (editor updates both MAIN and BACKUP when using setBlock)
public void block_crc_recalc(int index)
{
setBlock(getBlock(index), index);

View File

@@ -1,2 +1,65 @@
# BW_tool
Tool to modify Pokémon generation V savegames
@::::::::::::::::::::::::::::::::::::::::::::::::::@
| |
| Pokémon Generation 5 Save tool by suloku '16-21 |
| |
@::::::::::::::::::::::::::::::::::::::::::::::::::@
Source code is available here: https://github.com/suloku/BW_tool
This is a multipurpose savegame editor for generation 5 games.
Current features:
_________________
For BW and BW2:
* Entralink forest editor (*see exanded note)
* Trainer information and badges editor (also rival name for BW2)
* Prop Case editor
* Block dumper/injector (also decripts/recripts the known encrypted blocks such as entralink forest data block)
* Checksum verifier/corrector
Only for BW2:
* Hidden grotto and swarm editor
* Join Avenue editor (also can import/export visitors)**
* Key system editor (allows to unlock any keys and change the game configuration)
* Medal editor: still in a very basic stage, but allows to unlock any medal (to unlock a medal, set it to any date).
* Memory Link editor: can edit trainer name, TID and SID. Can export/import the memory link block. Can import Name, TID, SID and hall of fame from BW1 savegame. The flags are mostly unknown for now.
* 3DS Link editor: this allows to edit the 3DS link data, which was only ever used by Pokémon Dream radar. This has a "legal mode" (default), on which you can only insert pokémon and items available in Dream Radar and a "All mode" on which you can insert any pokémon or item. The main purpose is to allow the retreival of Dream Radar exclusive pokémon (like weather trio terrian formes) without the actual need to use Dream Radar. You can also clear the catched flags so you may transfer the legendary pokémon again to your savefile.
**4 visitor files are included in the file
*About entralink forest editor:
Two kind of files can be used: phl files, which are AREA files and are compatible with pockestock and pikaedit; and efdd files, which is basically the decrypted forest block, so it contains all areas and forest settings. The package includes a legitimate efdd file from Black 1 containing several Dream World Pokémon and the PGL Arceus; and also a legitimate efdd file from White 2 with a couple event pokemon and 9 dream world Pokémon.
The most interesting feature is the "Dream World Simulator", which are some handy buttons with the Dream World areas that allow injecting to the forest a pokémon from Dream World. The pokémon are restricted to what the dream world offered and only that. Each pokémon allows to select the move slot A, B or C*** and gender when aplicable (remember that in gen 5 only females can produce hidden ability eggs).
Similar to "Dream World Simulator" there's a PGL Promotions button, that allows to inject the PGL distributed pokémon as they were distributed. Please note that some of these pokémon were only obtainable on some languages, so receiving it in another language game renders it ilegal. The languages the pokémon could be received on are shown on screen for convenience. Also, these pokémon had fixed gender and moves.
Just to clarify: any pokémon injected using the Dream World or PGL buttons will be absolutely the same as if received from the online service (except out of region PGL pokémon, as there is no region filter in the editor).
*** Dream World moves
A: the pokémon learns via level up
B: pokemon learns trough breeding
C: dream world exclusive move or breeding move (depends on the pokemon)
Possible future features:
_________________
* Finish medal editor and trainer records: these features need research, since some medals are tied to in-game records. The goal is to make the editing as legit as possible, at the very least for the online exclusive medals that are not obtainable anymore and those almost impossible to obtain medals (30 people funfest mission, etc.).
* Memory link injecting/editing for BW2, and maybe importing some data from a BW1 savegame to memory link.
Note: there's a trainer records button, which is a possible future feature, and I haven't locked it for release.
Note 2: savegame can be loaded via drag and drop.
Thanks to:
__________
Many people that I'm probably missing out now, but those who shall not be missed are BlackShark for many research and information and kaphotics for reference on pkhex source code and research at project pokemon forums.