Go Back   The PokéCommunity Forums > ROM Hacking > Tools, Tutorials & Resources
Reload this Page [Tutorial] Make your own ROM hacking tool (C#)

Notices
For all updates, view the main page.

Tools, Tutorials & Resources Various tools to help you develop your hacks can be found here.
New threads in this forum are to be approved by a moderator before they are displayed.



Reply
 
Thread Tools
  #1    
Old August 22nd, 2014 (02:14 AM). Edited September 9th, 2014 by xGal.
xGal's Avatar
xGal xGal is offline
Mhm
 
Join Date: Nov 2011
Location: A tree
Gender: Other
Nature: Relaxed
Posts: 238
INTRODUCTION
Spoiler:

Long ago, Darthatron made a tutorial on how to code a tool in VB, using Visual Basic 6.

To be honest, meh. His tutorial is very old and not up to date. Other than that, the programming language VB sucks, comparing to C# and Java.

Few weeks ago, I finished a Java course in a college that teaches computer science. Unfortunatly, I only know how to use Java as a console, so I decided to try to learn C# too. I found Java and C# pretty similar to each other, so if you already know Java, I highly suggest you to learn C# too .

That was pretty off-topic, eh?

Anyway, I tried to make a tool in C#, using the latest version of Visual Studio, Visual Studio 13, and you know what's cool about this tutorial? Unlike Darthatron's tutorial, it works with almost any Visual Studio, because I don't use any costum functions! It meants that if someone will see this tutorial, even more 100 years, he will still be able to use it in his latest Visual Studio (Visual Studio 2113?). The only way that this tutorial won't work is if Microsoft are going to change complete C#, which probably won't happen .

Anyways, you will need:
- Visual Studio 2013
- Basic C# knowledge (if, true/false, else, all dat basic shet)
- A good name for your program (believe me or not, this is very critical. If you will call you program "Gal's Ultra Super Fantastic Mega Tool", it will atract more people than if you name it "Gal's Tool").

This tutorial will teach you making a very simple program, that enables/disables running shoes indoor, in FireRed only.

Well, let's start coding!



THE CODE
Spoiler:

Start your VS and open a new Visual C# project. Now, go to the very top of your code. You should see lots of usages of the command "using". Make a new line after the last "using" ("using System.Windows.Forms;", and write:
Code:
using System.IO;
Go back to your design and make 3 buttons and one label.
Change the name of the first button to "btnOpen" and change the text to "Open ROM",
change the name of the first button to "btnEnable" and the text to "Enable Running Indoor", the second to "btnDisable" and "Disable Running Indoor" and the label's text to "Loaded Game: ".
Disable btnOpen and btnEnable.

Make the window look like this:


Double click on your "Open ROM" button.
Let's make the Open ROM button.
Type in the line before "private void button1_Click(object sender, EventArgs e)":
Code:
OpenFileDialog ofd = new OpenFileDialog();
What it does is it makes an integer called "ofd" to be the new open file dialog.

Now, go to the design again and double click on the Open ROM button again.
Type in the space here:
Code:
            ofd.Filter = "GBA File(*.gba)|*.gba"; //Makes a filter for the open file dialog. You don't want the user to open .NDS files, aren't ya?
            ofd.ShowDialog();//Shows the open file dialog
            string gameCode = string.Empty;//Makes a new string that will be used to the gamecode.
            using (BinaryReader br = new BinaryReader(File.OpenRead(ofd.FileName))) //Sets a new integer to the BinaryReader
            {
                br.BaseStream.Seek(0xAC, SeekOrigin.Begin); //The seek is starting from 0xAC
                gameCode = Encoding.UTF8.GetString(br.ReadBytes(4)); //Reads 4 bytes from 0xAC and encodes it to text
            }
            br.Close(); //Closes the BinaryReader. Without it, opening the file with any other command will result the error "This file is being used by another process".
            if (gamecode == "BPRE") // Checks if the game code is BPRE.
            {
                label1.Text = "Loaded Game: Pokémon FireRed"; //If it's BPRE, it changes label1's text.
                btnEnable.Enabled = true; //Enables btnEnable, if the gamecode is BPRE.
                btnDisable.Enabled = true; //Enables btnDisable, if the gamecode is BPRE.
            }
            else //If the gamecode isn't BPRE.
            {
                label1.Text = "Loaded Game: ???"; //Changes label1's text.
                btnEnable.Enabled = false; //Disables btnEnable, if the gamecode isn't BPRE.
                btnDisable.Enabled = false; //Disables btnEnable, if the gamecode isn't BPRE.
                MessageBox.Show ("The loaded game isn't supported"); //Creates a message box with the text "The loaded game isn't supported", since this program only supports FireRed (BPRE).
            }
Don't get scared because of the code.
Every time you get scared because of the code, watch this video:
Spoiler:

(unless you have epilepsy).

So, the binary reader is fine, now let's make the hex writing command.

The command is (spoiler alert):
Spoiler:
Code:
BinaryWriter


OK, go back to your deigner and double click on "Enable Running Indoor" button.

Write in the space between the { } the following code:
Code:
           BinaryWriter bw = new BinaryWriter(File.OpenWrite(ofd.FileName)); //Makes a new integer for the BinaryWriter. It also "tells" the BinaryWriter what file it should write.
            for (int x = 0xBD494; x <= 0xBD494; x++) //Makes another integer that holds the first and the last offset you want the BinaryWriter to change. In the "running indoor" case, only 1 byte needs to be changed so both first and last offset are 0xBD494 (the location of the indoor running byte in FireRed).
            {

                bw.BaseStream.Position = x;
                bw.Write(0x00); //0x00 is the byte you need to replace 0x08 with in order to make running indoor work. This code "tells" the BinaryWriter to write 0x00 at the specified offset.


            }
            bw.Close(); //Yet again, closes the BinaryWriter to avoid errors.
Now, double click on the other button, the Disable Running Indoor button and copy the EXACT code in the Enable Running Indoor button. Just change the line bw.Write(0x00); with:
Code:
bw.Write(0x08); //The old value.
Now, the result should be:
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;

namespace WindowsFormsApplication8
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        OpenFileDialog ofd = new OpenFileDialog();

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "GBA File(*.gba)|*.gba";
            ofd.ShowDialog();
            string gameCode = string.Empty;
            using (BinaryReader br = new BinaryReader(File.OpenRead(ofd.FileName)))
            {
                br.BaseStream.Seek(0xAC, SeekOrigin.Begin);
                gameCode = Encoding.UTF8.GetString(br.ReadBytes(4));
            }
            br.Close();
            if (gamecode == "BPRE")
            {
                label1.Text = "Loaded Game: Pokémon FireRed";
                btnEnable.Enabled = true;
                btnDisable.Enabled = true;
            }
            else
            {
                label1.Text = "Loaded Game: ???";
                btnEnable.Enabled = false;
                btnDisable.Enabled = false;
                MessageBox.Show("The loaded game isn't supported");
            }
        }

        private void btnEnable_Click(object sender, EventArgs e)
        {
            BinaryWriter bw = new BinaryWriter(File.OpenWrite(ofd.FileName));
            for (int x = 0xBD494; x <= 0xBD494; x++)
            {

                bw.BaseStream.Position = x;
                bw.Write(0x00);


            }
            bw.Close();
        }

        private void btnDisable_Click(object sender, EventArgs e)
        {
            BinaryWriter bw = new BinaryWriter(File.OpenWrite(ofd.FileName));
            for (int x = 0xBD494; x <= 0xBD494; x++)
            {

                bw.BaseStream.Position = x;
                bw.Write(0x08);


            }
            bw.Close();
        }
    }
}
Alternatively for these codes, you can also use itari's code. Check it out in this post: http://www.pokecommunity.com/showpost.php?p=8411828&postcount=7.
If you want to make the BinaryWriter read and replace text & offset from textboxes, see this post: http://www.pokecommunity.com/showpost.php?p=8431971&postcount=21.
Also, if you want to make your program support more than one or two versions, here is a template I made for you guys for the Open ROM button:
Spoiler:
Code:
            OpenFileDialog ofd = new OpenFileDialog(); //Sets a new variable to be OpenFileDialog
            ofd.Filter = "GBA File(*.gba)|*.gba"; //Filter
            ofd.ShowDialog(); //Shows the dialog
            string gameCode = string.Empty; //Creates a new empty string
            using (BinaryReader br = new BinaryReader(File.OpenRead(ofd1.FileName))) //Sets a new variable to be BinaryReader
            {
                br.BaseStream.Seek(0xAC, SeekOrigin.Begin); //0xAC is the beginning offset
                gameCode = Encoding.UTF8.GetString(br.ReadBytes(4)); //Reads 4 bytes from 0xAC and encodes it to text
            }
           if (gameCode == "BPRE")
            {

                MessageBox.Show("FireRed English");
            }
            if (gameCode == "BPGE")
            {

                MessageBox.Show("LeafGreen");
            }
            if (gameCode == "BPRJ")
            {
                MessageBox.Show("FireRed Japanese");
            }
            if (gameCode == "BPGJ")
            {
                MessageBox.Show("LeafGreen Japanese");
            }
            if (gameCode == "BPRD")
            {
                MessageBox.Show("FireRed German");
            }
            if (gameCode=="BPGD"){
                MessageBox.Show("LeafGreen German");
            }
            if (gameCode == "AXVE")
            {
                MessageBox.Show("Ruby English");

            }
            if (gameCode == "AXPE")
            {
                MessageBox.Show("Sapphire English");
            }
            if (gameCode == "AXVJ")
            {
                MessageBox.Show("Ruby Japanese");
            }
            if (gameCode == "AXPJ")
            {
                MessageBox.Show("Sapphire Japanese");
            }
            if (gameCode == "AXVD")
            {
                MessageBox.Show("Ruby German");
            }
            if (gameCode == "AXPD")
            {
                MessageBox.Show("Sapphire German");

            }
            else
            {
                MessageBox.Show("This version is currently unsupported");
            }
These are the version I remember. If you guys remember more versions or just want to fix a mistake I did, write it as a comment .




DECORATE IT
Spoiler:

Let's be real here. The design of this program is boring. Make a new design to make people want use this program.

This is what I did:

You guessed it - I am not the best designer in the world, but hey, I know how to make tools in C#


NOTES
Spoiler:

This is the very basic of making tools. If you want the tool to read graphics from GBA, read from an INI file or read reverse hex, you will need to have functions.

You can make your own functions, or visit Jambo51's or SBird's GitHub. Link for their GitHub: https://github.com/Jambo51, https://github.com/SBird1337/Single.net.

If you guys have questions about the code or C#, comment in the thread. I will try to help you as much I can .

If you have used this tutorial or the source code for this project, please credit me. I worked really hard on that tutorial .

Also, if you want to know why C# is the best language to use, check out SBird's post: http://www.pokecommunity.com/showpost.php?p=8411792&postcount=6.
You can download the source code on my GitHub: https://github.com/Omastars.

CREDITS
Spoiler:

Microsoft - Making this amazing programming language.
Jambo51 - Pushing me to learn C#, instead of just sticking in VB.
HackMew - Running Indoors Hack (http://www.pokecommunity.com/showthread.php?t=207026).
http://www.animalseatinganimals.com/ - Wombat Picture.
Unknown - Ditto Conga Video.

Please inform me if I forgot someone :D.



__________________
Ten Sho Sho Ten Sho
Reply With Quote
  #2    
Old August 22nd, 2014 (02:25 PM).
Danny0317's Avatar
Danny0317 Danny0317 is offline
deez nuts!!!1!!!1!!!1!!
Gold Tier
 
Join Date: Jun 2013
Location: Miami, FL
Age: 15
Gender: Male
Nature: Hasty
Posts: 971
Overall, pretty good. But you should make a note that the program will crash if the rom is opened in A-Map, at least that's what happened to me
__________________
I've released four betas of two hacks.. click on my threads if you wanna download..


god damn it danny, another hack?
Reply With Quote
  #3    
Old August 22nd, 2014 (02:39 PM). Edited August 22nd, 2014 by xGal.
xGal's Avatar
xGal xGal is offline
Mhm
 
Join Date: Nov 2011
Location: A tree
Gender: Other
Nature: Relaxed
Posts: 238
Quote originally posted by Dark Sneasel:
Overall, pretty good. But you should make a note that the program will crash if the rom is opened in A-Map, at least that's what happened to me
Yeah, I'll guess that's what is going to happen because unlike my code, aMap uses the rom all the time it's being opened by advanced map. The good thing about my code is that it's only using the file in the opening and saving processes . Anyways, thanks for your feedback :D. BTW guys I'll fix my grammar errors as soon I get back on my computer .
__________________
Ten Sho Sho Ten Sho
Reply With Quote
  #4    
Old August 22nd, 2014 (03:23 PM).
kearnseyboy6's Avatar
kearnseyboy6 kearnseyboy6 is offline
Aussie's Toughest Mudder
 
Join Date: Dec 2008
Posts: 294
This is great, I plan on learning C+ very soon and help make some tools. I will be bookmarking this for the future but I also do recommend a check to see if the ROM is already open (like HxD and Jambo's tools do).
__________________
HOLIDAYING CURRENTLY!!
Reply With Quote
  #5    
Old August 23rd, 2014 (12:44 AM).
Touched's Avatar
Touched Touched is offline
Resident ASMAGICIAN
 
Join Date: Jul 2014
Gender: Male
Posts: 367
I'm not a C# programmer, but I think you should at least alert people to the existence of Mono - the community is moving towards being cross platform and I think most tool makers should be told how to do this. I'd guess i18n is also important, but I'm really not so sure how to do this in C#.

Anyway, I dislike C# much more than I dislike Java, so that might does make me biased, but is C# really the best language for people to lean? (Does anyone else hate how in Chrome, if you type "C#" as the first part of your query in the omnibox, it doesn't work? Another reason to hate the language) It's not exactly cross-platform, and it's hardly user-friendly. Additionally it's very Microsoft-centric. Besides, it's not exactly difficult to create a GUI in Java (by Java standards, that is), so why don't you just use that?

Also, why do we need a tool to do every little thing for us? This is easily done in a hex editor. Besides, I'm of the opinion that programmers should try and integrate their tools into something cohesive, rather than fragment functionality like this.
Reply With Quote
  #6    
Old August 23rd, 2014 (09:45 AM).
SBird SBird is offline
 
Join Date: Aug 2009
Gender: Male
Posts: 70
I would really recommend programmers to use object oriented elements if you want to use an object oriented language... Also: Get yourselves some basic style of coding. Even if you do not follow any damn standard that exists out there (And there are lots) - give your variables consistant names, do not name something "classnameAlphanumericalNumber" because it gives a potential reader headaches!

As for C# I wrote a library: https://github.com/SBird1337/Single.net feel free to use it as it implements most of the stuff you could possibly want to access in a gba rom (Header Data, Graphics, raw byte manipulation, etc) even if im not yet fully statisfied with the text encoding / decoding which probably needs rework.

When interacting with files, regardless(for most parts) of the language: Error freaking handling! What happens if a user wants to open a non-existant file or if its currently in use? Your program will throw an exception, an ugly wall-of-error will fill the users screen (Which is basically good, because if its a smart user he will give you the error message and you can fix the problem, anyways if you caught the exception in the first place you would be able to give him a proper error message instead of a long list of stack traces etc)

For all the Java, insert-other-language-that-is-so-much-better-then-c# and other fanboys: Stop that, there are many reasons why you would prefer a language over another, as for C# its an awesome IDE, a freaking huge framework with all you will probably ever need, syntax elements such as LINQ, generics, lambda functions and so on, i'm sure you can find some for your prefered language too, but keep in mind: I don't even care!

~SBird
Reply With Quote
  #7    
Old August 23rd, 2014 (10:36 AM). Edited August 23rd, 2014 by Lost Heart.
Lost Heart's Avatar
Lost Heart Lost Heart is offline
the better journalist
Crystal Tier
 
Join Date: Mar 2010
Age: 18
Gender: Other
Nature: Impish
Posts: 2,091
The code you use for reading the ROM code is okay, but not really as good as it could be. Here's what I would do:

Code:
string gameCode = string.Empty;
using (BinaryReader br = new BinaryReader(File.OpenRead(ofd.FileName)))
{
     br.BaseStream.Seek(0xAC, SeekOrigin.Begin);
     gameCode = Encoding.UTF8.GetString(br.ReadBytes(4));
}
Using this method is a lot cleaner, and it guarantees that the file stream is disposed of correctly.

Then, for the enable/disable stuff, try this:

Code:
using (BinaryWriter bw = new BinaryWriter(File.OpenWrite(ofd.FileName)))
{
     bw.Seek(0xBD494, SeekOrigin.Begin);
     bw.Write((byte)0x00); // or bw.Write((byte)0x08); // Change depending on use.
}
The way you use the for loop coupled with setting the stream's position each time you write is a BAD idea, because it just slows things down.
__________________
Reply With Quote
  #8    
Old August 23rd, 2014 (12:55 PM).
xGal's Avatar
xGal xGal is offline
Mhm
 
Join Date: Nov 2011
Location: A tree
Gender: Other
Nature: Relaxed
Posts: 238
Quote originally posted by SBird:
I would really recommend programmers to use object oriented elements if you want to use an object oriented language... Also: Get yourselves some basic style of coding. Even if you do not follow any damn standard that exists out there (And there are lots) - give your variables consistant names, do not name something "classnameAlphanumericalNumber" because it gives a potential reader headaches!

As for C# I wrote a library: https://github.com/SBird1337/Single.net feel free to use it as it implements most of the stuff you could possibly want to access in a gba rom (Header Data, Graphics, raw byte manipulation, etc) even if im not yet fully statisfied with the text encoding / decoding which probably needs rework.

When interacting with files, regardless(for most parts) of the language: Error freaking handling! What happens if a user wants to open a non-existant file or if its currently in use? Your program will throw an exception, an ugly wall-of-error will fill the users screen (Which is basically good, because if its a smart user he will give you the error message and you can fix the problem, anyways if you caught the exception in the first place you would be able to give him a proper error message instead of a long list of stack traces etc)

For all the Java, insert-other-language-that-is-so-much-better-then-c# and other fanboys: Stop that, there are many reasons why you would prefer a language over another, as for C# its an awesome IDE, a freaking huge framework with all you will probably ever need, syntax elements such as LINQ, generics, lambda functions and so on, i'm sure you can find some for your prefered language too, but keep in mind: I don't even care!

~SBird
Quote originally posted by itari:
The code you use for reading the ROM code is okay, but not really as good as it could be. Here's what I would do:

Code:
string gameCode = string.Empty;
using (BinaryReader br = new BinaryReader(File.OpenRead(ofd.FileName)))
{
     br.BaseStream.Seek(0xAC, SeekOrigin.Begin);
     gameCode = Encoding.UTF8.GetString(br.ReadBytes(4));
}
Using this method is a lot cleaner, and it guarantees that the file stream is disposed of correctly.

Then, for the enable/disable stuff, try this:

Code:
using (BinaryWriter bw = new BinaryWriter(File.OpenWrite(ofd.FileName)))
{
     bw.Seek(0xBD494, SeekOrigin.Begin);
     bw.Write((byte)0x00); // or bw.Write((byte)0x08); // Change depending on use.
}
The way you use the for loop coupled with setting the stream's position each time you write is a BAD idea, because it just slows things down.
Thanks for your contributions, I will add them in the main post .
__________________
Ten Sho Sho Ten Sho
Reply With Quote
  #9    
Old August 23rd, 2014 (09:52 PM).
Le pug's Avatar
Le pug Le pug is offline
Creator of Pokémon: Discovery / Fat Kid
Crystal Tier
 
Join Date: Aug 2013
Location: Le bed
Age: 22
Gender: Male
Nature: Bold
Posts: 681
I like this contribution a lot. There are a few tool ideas I've had in mind forever but don't know where to begin for which type of language to use or whatever. This gives me a great idea and will help a lot. If you're willing, maybe even expand on this tutorial to add more tidbits of knowledge in the future until we overdose on C+ knowledge? Great tutorial and I know it'll help people steer in the right direction.
__________________







/// Pokémon: Discovery
/// Pokémon: Fat Kid
/// Tile Insertion Tutorial For AdvanceMap
/// Pokémon Emerald Specials Resource Thread
/// Pokémon Emerald Decapitalization Patch
/// Emerald Titlescreen Cloud Removal Tutorial
/// Tutorial For Fixing Any ROM-related Bug
Reply With Quote
  #10    
Old August 24th, 2014 (08:29 AM).
Touched's Avatar
Touched Touched is offline
Resident ASMAGICIAN
 
Join Date: Jul 2014
Gender: Male
Posts: 367
Quote originally posted by SBird:
I would really recommend programmers to use object oriented elements if you want to use an object oriented language... Also: Get yourselves some basic style of coding. Even if you do not follow any damn standard that exists out there (And there are lots) - give your variables consistant names, do not name something "classnameAlphanumericalNumber" because it gives a potential reader headaches!

As for C# I wrote a library: https://github.com/SBird1337/Single.net feel free to use it as it implements most of the stuff you could possibly want to access in a gba rom (Header Data, Graphics, raw byte manipulation, etc) even if im not yet fully statisfied with the text encoding / decoding which probably needs rework.

When interacting with files, regardless(for most parts) of the language: Error freaking handling! What happens if a user wants to open a non-existant file or if its currently in use? Your program will throw an exception, an ugly wall-of-error will fill the users screen (Which is basically good, because if its a smart user he will give you the error message and you can fix the problem, anyways if you caught the exception in the first place you would be able to give him a proper error message instead of a long list of stack traces etc)

For all the Java, insert-other-language-that-is-so-much-better-then-c# and other fanboys: Stop that, there are many reasons why you would prefer a language over another, as for C# its an awesome IDE, a freaking huge framework with all you will probably ever need, syntax elements such as LINQ, generics, lambda functions and so on, i'm sure you can find some for your prefered language too, but keep in mind: I don't even care!

~SBird
I was not recommending any one language. I was merely recommending that you choose a language that is designed to be cross-platform, instead of one that is quite anchored to one platform. What's wrong with wanting tools to be more accessible to the community? Besides, none of the features you listed are at all unique to C#. Any high-level language will boast similar features.
Reply With Quote
  #11    
Old August 24th, 2014 (10:06 PM). Edited August 28th, 2014 by Team Fail.
Team Fail's Avatar
Team Fail Team Fail is online now
fun in the sun
Platinum Tier
 
Join Date: May 2009
Age: 20
Gender: Male
Nature: Brave
Posts: 10,703
Never, ever, ever, ever, ever do this:

Code:
ofd.ShowDialog();
Doing this is a terrible idea. If the user closes the OpenFileDialog or clicks "cancel", the application will hang. To make it work properly, your button1_click event would be best like this:

Code:
private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "GBA File(*.gba)|*.gba";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                string gameCode = string.Empty;
                using (BinaryReader br = new BinaryReader(File.OpenRead(ofd.FileName)))
                {
                    br.BaseStream.Seek(0xAC, SeekOrigin.Begin);
                    gameCode = Encoding.UTF8.GetString(br.ReadBytes(4));
                }
                br.Close();
                if (gamecode == "BPRE")
                {
                    label1.Text = "Loaded Game: Pokémon FireRed";
                    btnEnable.Enabled = true;
                    btnDisable.Enabled = true;
                }
                else
                {
                    label1.Text = "Loaded Game: ???";
                    btnEnable.Enabled = false;
                    btnDisable.Enabled = false;
                    MessageBox.Show("Theed game isn't supported");
                }
            }
        }
Put all your game check code in an if statement. You can also toss an "else" statement in there if you want to make it do something should the user decide to cancel what they're doing.

Code:
private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "GBA File(*.gba)|*.gba";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                string gameCode = string.Empty;
                using (BinaryReader br = new BinaryReader(File.OpenRead(ofd.FileName)))
                {
                    br.BaseStream.Seek(0xAC, SeekOrigin.Begin);
                    gameCode = Encoding.UTF8.GetString(br.ReadBytes(4));
                }
                br.Close();
                if (gamecode == "BPRE")
                {
                    label1.Text = "Loaded Game: Pokémon FireRed";
                    btnEnable.Enabled = true;
                    btnDisable.Enabled = true;
                }
                else
                {
                    label1.Text = "Loaded Game: ???";
                    btnEnable.Enabled = false;
                    btnDisable.Enabled = false;
                    MessageBox.Show("Theed game isn't supported");
                }
            }
            else
            {
                //do whatever...
            }
       }
Edit: This also applies to SaveFileDialog as well, fwiw.

Edit 2: You can also make your code a bit faster with regards to adding multiple versions. Instead of making it check the version using a bunch of if statements, use a switch/case/default combination.
Code:
BinaryReader br = new BinaryReader(File.OpenRead(ofd.FileName));
br.BaseStream.Seek(0xAC, SeekOrigin.Begin);
switch(Encoding.UTF8.GetString(br.ReadBytes(4)))
{
	case "BPRE"
		MessageBox.Show("FireRed");
		break;
	case "BPGE"
		MessageBox.Show("LeafGreen");
		break;
	case "AVXE"
		MessageBox.Show("Ruby");
		break;
	case "AXPE"
		MessageBox.Show("Sapphire");
		break;
	case "BPEE"
		MessageBox.Show("Emerald");
		break;
	default
		MessageBox.Show("Game not supported.");
		break;
}
That way, once it hits a match, it'll break out of the statement and keep going, instead of checking all the other titles even though it has a match. However, if it can't find a match, it'll go to the "default" case and tell you the game is unsupported.
__________________


voler avec moi
Reply With Quote
  #12    
Old August 30th, 2014 (12:05 PM). Edited August 30th, 2014 by LocksmithArmy.
LocksmithArmy's Avatar
LocksmithArmy LocksmithArmy is offline
Mew!
 
Join Date: Feb 2013
Age: 26
Gender: Male
Posts: 402
I really enjoyed this little tutorial. Being a C# programmer myself it motivated me to make my own tool...

I am pretty well finished except I cant for the life of me figure out how to open images inside the game... My tool is a Item editor... and i want to be able to edit the items images(along with all the other stuff), but I cant figure out how to decompress them, then recompress them (after they have been altered)...

any one have any ideas (or a pre written class) imput an offset (int or string) and return a bitmap lol
__________________
Reply With Quote
  #13    
Old August 30th, 2014 (12:29 PM).
Touched's Avatar
Touched Touched is offline
Resident ASMAGICIAN
 
Join Date: Jul 2014
Gender: Male
Posts: 367
Quote originally posted by LocksmithArmy:
I really enjoyed this little tutorial. Being a C# programmer myself it motivated me to make my own tool...

I am pretty well finished except I cant for the life of me figure out how to open images inside the game... My tool is a Item editor... and i want to be able to edit the items images(along with all the other stuff), but I cant figure out how to decompress them, then recompress them (after they have been altered)...

any one have any ideas (or a pre written class) imput an offset (int or string) and return a bitmap lol
Image data like that is LZSS compressed. You can either implement your own given the spec on GBATek or use this library.
Reply With Quote
  #14    
Old August 30th, 2014 (01:34 PM).
LocksmithArmy's Avatar
LocksmithArmy LocksmithArmy is offline
Mew!
 
Join Date: Feb 2013
Age: 26
Gender: Male
Posts: 402
Quote originally posted by Touched:
Image data like that is LZSS compressed. You can either implement your own given the spec on GBATek or use this library.
Spoiler:
SWI 11h (GBA/NDS7/NDS9) - LZ77UnCompWram
SWI 12h (GBA/NDS7/NDS9) - LZ77UnCompVram (NDS: with Callback)
Expands LZ77-compressed data. The Wram function is faster, and writes in units of 8bits. For the Vram function the destination must be halfword aligned, data is written in units of 16bits.
If the size of the compressed data is not a multiple of 4, please adjust it as much as possible by padding with 0. Align the source address to a 4-Byte boundary.
r0 Source address, pointing to data as such:
Data header (32bit)
Bit 0-3 Reserved
Bit 4-7 Compressed type (must be 1 for LZ77)
Bit 8-31 Size of decompressed data
Repeat below. Each Flag Byte followed by eight Blocks.
Flag data (8bit)
Bit 0-7 Type Flags for next 8 Blocks, MSB first
Block Type 0 - Uncompressed - Copy 1 Byte from Source to Dest
Bit 0-7 One data byte to be copied to dest
Block Type 1 - Compressed - Copy N+3 Bytes from Dest-Disp-1 to Dest
Bit 0-3 Disp MSBs
Bit 4-7 Number of bytes to copy (minus 3)
Bit 8-15 Disp LSBs
r1 Destination address
r2 Callback parameter (NDS SWI 12h only, see Callback notes below)
r3 Callback structure (NDS SWI 12h only, see Callback notes below)
Return: No return value.


Its not too complicated... but what do MSBs and LSBs mean?

Ive seen dsdecmp before but it does not seem to work like I want (cant get output to image) or im messing up somewhere else, could be anything... who knows
__________________
Reply With Quote
  #15    
Old August 30th, 2014 (02:51 PM).
Gamer2020's Avatar
Gamer2020 Gamer2020 is offline
This love is a sickness...
 
Join Date: Jun 2008
Location: Distant Land
Gender: Male
Nature: Bold
Posts: 802
Send a message via Skype™ to Gamer2020
There are image functions for VB.net in my signature. You can convert them to C# and use them if you want.
__________________
ENERGYSEARCH.ME
A Pokemon TCG database and Social network!
Pokemon Game Editor Download!
PGE is not being worked on currently but is there for those that need it.
Fun Fact: Even though PGE isn't posted on PC anymore it still has the same number of downloads per day.
Accept no imitations!
Reply With Quote
  #16    
Old August 30th, 2014 (06:29 PM).
AkimotoBubble AkimotoBubble is offline
 
Join Date: Aug 2014
Gender: Male
Posts: 28
why not put it on the phone?
__________________
i am bubble,and sorry my english is not good ......
Reply With Quote
  #17    
Old August 31st, 2014 (12:42 AM).
Touched's Avatar
Touched Touched is offline
Resident ASMAGICIAN
 
Join Date: Jul 2014
Gender: Male
Posts: 367
Quote originally posted by LocksmithArmy:
Spoiler:
SWI 11h (GBA/NDS7/NDS9) - LZ77UnCompWram
SWI 12h (GBA/NDS7/NDS9) - LZ77UnCompVram (NDS: with Callback)
Expands LZ77-compressed data. The Wram function is faster, and writes in units of 8bits. For the Vram function the destination must be halfword aligned, data is written in units of 16bits.
If the size of the compressed data is not a multiple of 4, please adjust it as much as possible by padding with 0. Align the source address to a 4-Byte boundary.
r0 Source address, pointing to data as such:
Data header (32bit)
Bit 0-3 Reserved
Bit 4-7 Compressed type (must be 1 for LZ77)
Bit 8-31 Size of decompressed data
Repeat below. Each Flag Byte followed by eight Blocks.
Flag data (8bit)
Bit 0-7 Type Flags for next 8 Blocks, MSB first
Block Type 0 - Uncompressed - Copy 1 Byte from Source to Dest
Bit 0-7 One data byte to be copied to dest
Block Type 1 - Compressed - Copy N+3 Bytes from Dest-Disp-1 to Dest
Bit 0-3 Disp MSBs
Bit 4-7 Number of bytes to copy (minus 3)
Bit 8-15 Disp LSBs
r1 Destination address
r2 Callback parameter (NDS SWI 12h only, see Callback notes below)
r3 Callback structure (NDS SWI 12h only, see Callback notes below)
Return: No return value.


Its not too complicated... but what do MSBs and LSBs mean?

Ive seen dsdecmp before but it does not seem to work like I want (cant get output to image) or im messing up somewhere else, could be anything... who knows
http://en.wikipedia.org/wiki/Most_significant_bit
http://en.wikipedia.org/wiki/Least_significant_bit

You can't just decompress the image; its not just a standard array of pixels. Its basically each 8x8 tile stored sequentially. You have to read it 64 pixels at a time (items are 4bpp). Keep in mind that you also have to load the palette, etc. etc. Also, a number of other image formats are used. Take a look at Tile Molester to see how many image codecs can be used.
Reply With Quote
  #18    
Old August 31st, 2014 (11:05 PM).
diegoisawesome's Avatar
diegoisawesome diegoisawesome is offline
Please understand
Silver Tier
 
Join Date: Dec 2007
Location: Goldenrod City, Johto
Age: 18
Gender: Male
Nature: Quirky
Posts: 978
Quote originally posted by SBird:
As for C# I wrote a library: https://github.com/SBird1337/Single.net feel free to use it as it implements most of the stuff you could possibly want to access in a gba rom (Header Data, Graphics, raw byte manipulation, etc) even if im not yet fully statisfied with the text encoding / decoding which probably needs rework.
I would like to use your functions in my own tool but I don't know how to import them in and use them in my project. Could you please help?
__________________


My other resources:
My Website
diegoisawesome's MEGA-HUGE XSE Scripting Tutorial
diegoisawesome's Miscellaneous Finds
The Ruins of Alph Puzzles
Diego's Miscellaneous Patches
GBA Intro Manager
The Secret Sauce: Triple-Layer Tiles
Reply With Quote
  #19    
Old September 1st, 2014 (01:42 AM).
xGal's Avatar
xGal xGal is offline
Mhm
 
Join Date: Nov 2011
Location: A tree
Gender: Other
Nature: Relaxed
Posts: 238
Quote originally posted by diegoisawesome:
I would like to use your functions in my own tool but I don't know how to import them in and use them in my project. Could you please help?
If you want, I could help. Just download the files from his GitHub, open your project in Visual Studio, press Shift+Alt+A and choose the functions you have downloaded.
__________________
Ten Sho Sho Ten Sho
Reply With Quote
  #20    
Old September 1st, 2014 (05:51 PM).
SBird SBird is offline
 
Join Date: Aug 2009
Gender: Male
Posts: 70
Quote originally posted by diegoisawesome:
I would like to use your functions in my own tool but I don't know how to import them in and use them in my project. Could you please help?
You can either download and compile the project and just reference the library file (.dll) in your projects, that should work.

If you want to view the code in the debugger I recommend adding the whole project to your project folder. In case you are using visual studio do as follows: Right click in your solution explorer on the solution you are currently working on and select: Add - Existing project. Select the project file from the github master folder and (very important) reference the Single project from your main project (just like adding a normal reference, but checking the project tab - its where you find libraries that are already inside your solution.

The code is currently partly commended, but in german. I will probably recomment most of it when I find the time to, but most of the stuff is pretty self-explaining.

Keep in mind that the library will copy any rom object into the memory and work with a byte[] object. In order write changes to files you have to use Rom.Save or Rom.Patch, which will either overwrite a file / create a new one or patch a file.

Good luck programming

~SBird
Reply With Quote
  #21    
Old September 9th, 2014 (09:00 PM).
xGal's Avatar
xGal xGal is offline
Mhm
 
Join Date: Nov 2011
Location: A tree
Gender: Other
Nature: Relaxed
Posts: 238
This is how to make the BinaryWriter write a specified offset and a specified byte from textboxes:

Code:
            using (BinaryWriter bw = new BinaryWriter(File.OpenWrite(ofd.FileName)))
            {
                bw.Seek(Convert.ToInt32([OffsetMessageBox].Text, 16), SeekOrigin.Begin);
                bw.Write((byte)Convert.ToInt32([ByteMessageBox].Text));
            }
Replace [OffsetMessageBox] to the textbox where the user should put the offset and the [ByteMessageBox] to the byte you want the BinaryWriter to change.
__________________
Ten Sho Sho Ten Sho
Reply With Quote
  #22    
Old September 10th, 2014 (04:26 PM).
nasonex's Avatar
nasonex nasonex is offline
is trying to learn how to hack
 
Join Date: Jan 2010
Location: Parañaque City, Metro Manila, Philippines
Gender: Male
Nature: Hasty
Posts: 195
Send a message via Windows Live Messenger to nasonex Send a message via Yahoo to nasonex
How can you make a .EXE of the program in c#? Or make it an installer?
__________________
This signature has been disabled.
Exceeding signature height limit
Please review and fix the issues by reading the signature rules.

You must edit it to meet the limits set by the rules before you may remove the [sig-reason] code from your signature. Removing this tag will re-enable it.

Do not remove the tag until you fix the issues in your signature. You may be infracted for removing this tag if you do not fix the specified issues. Do not use this tag for decoration purposes.
Reply With Quote
  #23    
Old September 10th, 2014 (04:58 PM).
Gamer2020's Avatar
Gamer2020 Gamer2020 is offline
This love is a sickness...
 
Join Date: Jun 2008
Location: Distant Land
Gender: Male
Nature: Bold
Posts: 802
Send a message via Skype™ to Gamer2020
Quote originally posted by nasonex:
How can you make a .EXE of the program in c#? Or make it an installer?
In visual studio you right click on the solution and click build. There should be an exe in the bin folder.
__________________
ENERGYSEARCH.ME
A Pokemon TCG database and Social network!
Pokemon Game Editor Download!
PGE is not being worked on currently but is there for those that need it.
Fun Fact: Even though PGE isn't posted on PC anymore it still has the same number of downloads per day.
Accept no imitations!
Reply With Quote
  #24    
Old September 10th, 2014 (05:27 PM).
Team Fail's Avatar
Team Fail Team Fail is online now
fun in the sun
Platinum Tier
 
Join Date: May 2009
Age: 20
Gender: Male
Nature: Brave
Posts: 10,703
Quote originally posted by Gamer2020:
In visual studio you right click on the solution and click build. There should be an exe in the bin folder.
Just gonna tack on that if you debug your application (Pressing F5 to do a test run), it'll also be in your build folder as well.
__________________


voler avec moi
Reply With Quote
  #25    
Old September 10th, 2014 (10:42 PM).
nasonex's Avatar
nasonex nasonex is offline
is trying to learn how to hack
 
Join Date: Jan 2010
Location: Parañaque City, Metro Manila, Philippines
Gender: Male
Nature: Hasty
Posts: 195
Send a message via Windows Live Messenger to nasonex Send a message via Yahoo to nasonex
Quote originally posted by Gamer2020:
In visual studio you right click on the solution and click build. There should be an exe in the bin folder.
Quote originally posted by Team Fail:
Just gonna tack on that if you debug your application (Pressing F5 to do a test run), it'll also be in your build folder as well.
So can you run it in other PCs as well?
__________________
This signature has been disabled.
Exceeding signature height limit
Please review and fix the issues by reading the signature rules.

You must edit it to meet the limits set by the rules before you may remove the [sig-reason] code from your signature. Removing this tag will re-enable it.

Do not remove the tag until you fix the issues in your signature. You may be infracted for removing this tag if you do not fix the specified issues. Do not use this tag for decoration purposes.
Reply With Quote
Reply
Quick Reply

Sponsored Links

You may also like.. (Beta)
Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are UTC -8. The time now is 07:43 PM.