Converting between Game Genie's NES codes and hex codes
NES codes are so simple that they can be converted between the two formats by hand. You don't even need to know any binary math! The two "proper" methods will be listed as well for technical people or perhaps for programmers.
The Pidgin Method: GG to hex
First, you need to see the codebook table:
A P Z L G I T Y
E O X U K S V N
Each letter is associated with a number. A = 0, P = 1... T = 6, Y = 7. The letters in the second row are equal to the same number as the letters above them. Thus, E = 0, O = 1... V = 6, N = 7. This does not mean that the row is irrelevant, but the row does not affect the numeric value of the letter.
The leftmost hex digit (address 3 by its proper name) is equal to the numeric value of the fourth GG letter. For example, xxxUxx --> 3zzzzz. xxxTxxxx --> 6zzzzzzz.
The next hex digit (address 2) is equal to the value of the sixth letter, plus 8 if the fifth letter comes from the bottom row of the above table. Remember, these are hex digits. 9 + 1 = A, etc. Anyway, examples: xxxxGK --> z4zzzz. xxxxKKxx --> zCzzzzzz.
The next digit (address 1) is equal to the value of the third letter, plus 8 if the second letter is from the bottom row. xAZxxx --> zz2zzz. xKZxxxxx --> zzAzzzzz.
The next digit (address 0) is equal to the value of the fifth letter, plus 8 if the fourth letter is from the bottom row. xxxLNx --> zzz7zz. xxxUNx --> zzzFzz.
The next part of the code (data 1) is equal to the value of the second letter, plus 8 if the first letter is from the bottom row. ZSxxxx --> zzzz5z. XSxxxx --> zzzzDz.
The next digit (data 0) is equal to the value of the first letter, plus 8 if the last letter is from the bottom row. PxxxxI --> zzzzz1. PxxxxxxV --> zzzzz9zz. If your code only contains six letters, stop now.
The next part of the code (check 1) is equal to the value of the eighth letter, plus 8 if the seventh letter is from the bottom row. xxxxxxLA --> zzzzzz0z. xxxxxxEA --> zzzzzz8z.
The last digit (check 0) is equal to the value of the seventh letter, plus 8 if the sixth letter is from the bottom row. xxxxxYVx --> zzzzzzz6. xxxxxNVx --> zzzzzzzE.
Whew! If you are writing a program to convert codes, don't do it this way...
The Pidgin Method: Hex to GG
There's not much to add going backwards. The only trick is that instead of looking at two letters to construct one digit, you look at one digit and construct two letters from it. If you do it on paper, it helps to write a small '+8' above a character slot when the given hex digit is 8 or greater. Then, when you get to that letter, you will remember to take it from the second row of the table instead of the first.
The Binary Method
It is probably easiest to demonstrate this method by showing how I implemented it in the code converter. Don't worry too much about the programmy look. Just remember that & is binary AND, | is binary OR, << and >> are binary shifts, and bizarre things like &= or |= simply perform an operation and store the result in the variable on the left.
static CString N6GGtoHx(CString ncode) //CStrings are like character arrays.
{
CString hresult=" ";
char tstring[2]="";
int mval=0;
for (mval=0;mval<=5;mval++) //This part looks for errors. GetVal takes a GG
{ //letter and returns the value of it
if (GetVal(ncode[mval])== -1) //(hand-written, not shown)
return "------";
}
mval=GetVal(ncode[3])&7; //Take the value of the fourth letter, regardless of
_itoa(mval,tstring,16); //its row in the table. _itoa just turns a number into
hresult.SetAt(0,tstring[0]); //a string, and SetAt copies it into the final answer.
mval=(GetVal(ncode[5])&7)|(GetVal(ncode[4])&8);
_itoa(mval,tstring,16); //Take the value of the 6th, +8 if the 5th is bottom row.
hresult.SetAt(1,tstring[0]); //Remember, ncode[x] is character x+1.
mval=(GetVal(ncode[2])&7)|(GetVal(ncode[1])&8);
_itoa(mval,tstring,16); //Etc., so forth, the rest are the same.
hresult.SetAt(2,tstring[0]);
mval=(GetVal(ncode[4])&7)|(GetVal(ncode[3])&8);
_itoa(mval,tstring,16);
hresult.SetAt(3,tstring[0]);
mval=(GetVal(ncode[1])&7)|(GetVal(ncode[0])&8);
_itoa(mval,tstring,16);
hresult.SetAt(4,tstring[0]);
mval=(GetVal(ncode[0])&7)|(GetVal(ncode[5])&8);
_itoa(mval,tstring,16);
hresult.SetAt(5,tstring[0]);
return hresult; //hresult has now been constructed character by character into
} //the hex code we want.
static CString N8GGtoHx(CString ncode) //Same operation as before, really.
{
CString hresult=" ";
char tstring[2]="";
int mval=0;
for (mval=0;mval<=7;mval++)
{
if (GetVal(ncode[mval])==-1)
return "--------";
}
mval=GetVal(ncode[3])&7;
_itoa(mval,tstring,16);
hresult.SetAt(0,tstring[0]);
mval=(GetVal(ncode[5])&7)|(GetVal(ncode[4])&8);
_itoa(mval,tstring,16);
hresult.SetAt(1,tstring[0]);
mval=(GetVal(ncode[2])&7)|(GetVal(ncode[1])&8);
_itoa(mval,tstring,16);
hresult.SetAt(2,tstring[0]);
mval=(GetVal(ncode[4])&7)|(GetVal(ncode[3])&8);
_itoa(mval,tstring,16);
hresult.SetAt(3,tstring[0]);
mval=(GetVal(ncode[7])&7)|(GetVal(ncode[6])&8);
_itoa(mval,tstring,16);
hresult.SetAt(4,tstring[0]);
mval=(GetVal(ncode[6])&7)|(GetVal(ncode[5])&8);
_itoa(mval,tstring,16);
hresult.SetAt(5,tstring[0]);
mval=(GetVal(ncode[1])&7)|(GetVal(ncode[0])&8);
_itoa(mval,tstring,16);
hresult.SetAt(6,tstring[0]);
mval=(GetVal(ncode[0])&7)|(GetVal(ncode[7])&8);
_itoa(mval,tstring,16);
hresult.SetAt(7,tstring[0]);
return hresult;
}
static CString N6HxtoGG(CString ncode) //Performs the formula in reverse
{
CString gresult=" ";
int i;
for (i=0;i<=5;i++) //Error checking, again.
{
if (AtoH(ncode[i])== -1) //AtoH turns hex digits in a string into real numbers.
return "------"; //(hand-written, not shown)
}
//GetChar turns numbers into their GG equivalents (hand-written, not shown)
gresult.SetAt(0,GetChar((AtoH(ncode[5])&7)|(AtoH(ncode[4])&8)));
gresult.SetAt(1,GetChar((AtoH(ncode[4])&7)|(AtoH(ncode[2])&8)));
gresult.SetAt(2,GetChar(AtoH(ncode[2])&7));
gresult.SetAt(3,GetChar((AtoH(ncode[0])&7)|(AtoH(ncode[3])&8)));
gresult.SetAt(4,GetChar((AtoH(ncode[3])&7)|(AtoH(ncode[1])&8)));
gresult.SetAt(5,GetChar((AtoH(ncode[1])&7)|(AtoH(ncode[5])&8)));
return gresult;
}
static CString N8HxtoGG(CString ncode)
{
CString gresult=" ";
int i;
for (i=0;i<=7;i++)
{
if (AtoH(ncode[i])==-1)
return "--------";
}
gresult.SetAt(0,GetChar((AtoH(ncode[7])&7)|(AtoH(ncode[6])&8)));
gresult.SetAt(1,GetChar((AtoH(ncode[6])&7)|(AtoH(ncode[2])&8)));
gresult.SetAt(2,GetChar((AtoH(ncode[2])&7)|8));
gresult.SetAt(3,GetChar((AtoH(ncode[0])&7)|(AtoH(ncode[3])&8)));
gresult.SetAt(4,GetChar((AtoH(ncode[3])&7)|(AtoH(ncode[1])&8)));
gresult.SetAt(5,GetChar((AtoH(ncode[1])&7)|(AtoH(ncode[5])&8)));
gresult.SetAt(6,GetChar((AtoH(ncode[5])&7)|(AtoH(ncode[4])&8)));
gresult.SetAt(7,GetChar((AtoH(ncode[4])&7)|(AtoH(ncode[7])&8)));
return gresult;
}
The Bitmap Method
After the previous 200 pages, you may be wondering why on Earth you need this, too. You don't. In fact, I recommend you steer clear of it. It is only included for completeness.
6 letter
GG code: 0123 4567 8911 1111 1111 2222
01 2345 6789 0123
Hex code: x111 1222 5911 1111 : 1678 2234
345 6123 01 2789 0
*x represents a bit which is ALWAYS 0.
8 letter
GG code: 0123 4567 8911 1111 1111 2222 2222 2233
01 2345 6789 0123 4567 8901
Hex code: x111 1222 5911 1111 ? 2233 2222 : 1678 2234
345 6123 01 2789 4901 0567 8