It is currently Tue Aug 21, 2018 12:58 am

 All times are UTC - 7 hours

 Page 1 of 1 [ 12 posts ]
 Print view Previous topic | Next topic
Author Message
 Post subject: Game Gene Code Generation AlgorithmPosted: Thu Jul 21, 2016 2:28 pm

Joined: Sun Jun 05, 2016 1:41 pm
Posts: 74
I just wanted to share an algorithm (in C#) for converting two types of cheats (substitute and compare-and-substitute) into Game Genie codes. The Game Genie decoding algorithm can be found online (http://tuxnes.sourceforge.net/gamegenie.html) but I couldn't find one for the encoding process. Most likely there's one in some emulator's source repository somewhere but I was too lazy to keep searching and decided to have a go at reversing the decoding process myself

Some things to note:
• The algorithm here is in the form of a property (getter method) of a Cheat class. It has access to properties: Address (unsigned short), Value (byte), NeedsComparison (boolean) and CompareValue (byte)
• When NeedsComparison is False, CompareValue is ignored and two 6-letter Game Genie code variants are generated using Address and Value only. This is a substitute-only code
• When NeedsComparison is True, CompareValue is taken into consideration and two 8-letter Game Genie code variants are generated using Address, Value and CompareValue. This is a compare-and-substitute code
• The algorithm generates two code variants because bit 7 of the 3rd letter nybble in the code is not used when decoding the cheat properties and can hence be either 1 or 0. The two variants differ only in the 3rd letter. For example, the codes GOSSIP and GOISIP both represent the same cheat (substitute \$14 at address \$D1DD)
• The algorithm does not work with cheats that target the lower 32K of the address space since when decoded, the addresses are mapped in the upper 32K (3rd letter bit 7 could have been used for this purpose, in hindsight)

So here goes:
Code:
public string GameGenieCode
{
get
{
byte[] nybbles = new byte[NeedsComparison ? 8 : 6];

// reverse of
// address = 0x8000 + ((n3 & 7) << 12) | ((n5 & 7) << 8) | ((n4 & 8) << 8) | ((n2 & 7) << 4) | ((n1 & 8) << 4) | (n4 & 7) | (n3 & 8);

// common to both 6-letter and 8-letter codes
nybbles[0] = (byte)(((Value   >> 4) & 8) | ((Value   >>  0) & 7));
nybbles[1] = (byte)(((Address >> 4) & 8) | ((Value   >>  4) & 7));

nybbles[2] = (byte)(((Address >> 4) & 7)); // unknown bit 7 produces 2 variants
nybbles[3] = (byte)(((Address >> 0) & 8) | ((Address >> 12) & 7));
nybbles[4] = (byte)(((Address >> 8) & 8) | ((Address >>  0) & 7));

if (NeedsComparison)
{
// reverse of
// data = ((n1 & 7) << 4) | ((n0 & 8) << 4) | (n0 & 7) | (n7 & 8);
// compare = ((n7 & 7) << 4) | ((n6 & 8) << 4) | (n6 & 7) | (n5 & 8);
nybbles[5] = (byte)(((CompareValue >> 0) & 8) | ((Address      >> 8) & 7));
nybbles[6] = (byte)(((CompareValue >> 4) & 8) | ((CompareValue >> 0) & 7));
nybbles[7] = (byte)(((Value        >> 0) & 8) | ((CompareValue >> 4) & 7));
}
else // 6 letter code
{
// reverse of
// data = ((n1 & 7) << 4) | ((n0 & 8) << 4) | (n0 & 7) | (n5 & 8);
nybbles[5] = (byte)(((Value   >> 0) & 8) | ((Address >> 8) & 7));
}

StringBuilder stringBuilder = new StringBuilder();
foreach (byte nybble in nybbles)
stringBuilder.Append(gameGenieNybbleToChar[nybble]);

stringBuilder.Append(" / ");

nybbles[2] |= 8; // variant

foreach (byte nybble in nybbles)
stringBuilder.Append(gameGenieNybbleToChar[nybble]);

return stringBuilder.ToString();
}
}

public static char[] gameGenieNybbleToChar = new char[]
{ 'A', 'P', 'Z', 'L', 'G', 'I', 'T', 'Y',
'E', 'O', 'X', 'U', 'K', 'S', 'V', 'N' };

_________________
Tile IDE and tile engine for XNA: http://tide.codeplex.com/
Fancy Fish Mod - Minecraft Mod: http://fancyfishmod.weebly.com/

Last edited by colinvella on Fri Jul 22, 2016 1:33 am, edited 2 times in total.

Top

 Post subject: Re: Game Gene Code Generation AlgorithmPosted: Thu Jul 21, 2016 7:21 pm

Joined: Sun Mar 03, 2013 1:52 am
Posts: 106
Location: Texas, USA
colinvella wrote:
The algorithm generates two code variants because bit 7 of the cheat Address is not used when decoding the cheat properties and can hence be either 1 or 0. The two variants differ only in the 3rd letter. For example, the codes GOSSIP and GOISIP both represent the same cheat (substitute \$14 at address \$D1DD)

When entering codes on an actual Game Genie, the high bit of the third letter helps move the cursor automatically to make entering codes easier.

After you enter the 6th letter, the Game Genie checks if the high bit of the third letter is clear. If so, it will move the cursor to the next line. (If you're on the last line, the cursor will stay on the 6th letter.) You can still add the 7th and 8th letters by pressing B to back up or by clicking on the 7th blank. Any 8-letter code is converted to a "compare and value" modification, no matter what the value of the extra bit is.

If the Game Genie thinks it was an 8-letter code, you can click on the next line to skip the 7th and 8th letters and enter another code. Any 6-letter code is converted to a "value only" modification, no matter what the value of the extra bit is.

But setting the extra bit correctly is a nice thing to do in case the code is ever used on a real Game Genie. When the bit is set wrong, you'll have to manually adjust the cursor.

Top

 Post subject: Re: Game Gene Code Generation AlgorithmPosted: Thu Jul 21, 2016 9:35 pm

Joined: Sat Jul 12, 2014 3:04 pm
Posts: 958
Bavi beat me to it. GOSSIP is a bad example for this reason, it has the "8-character code?" bit (n2&8) set, but is six-character.?
I wasn't sure if it controlled the compare check or just the input.
*doublechecks* PowerPak seems to just go "is it 8 characters" too to decide "is this a compare cheat?" (So does Mednafen.)
One should set it for cheats that use the compare value, though.

 Attachments: File comment: Default cursor positions. GGenieN2d8.png [ 1.06 KiB | Viewed 2596 times ]
Top

 Post subject: Re: Game Gene Code Generation AlgorithmPosted: Thu Jul 21, 2016 10:15 pm

Joined: Sun Mar 03, 2013 1:52 am
Posts: 106
Location: Texas, USA
I wasn't sure if it controlled the compare check or just the input.

I should clarify that I have only tested with the Game Genie ROM, not the actual Game Genie hardware. I used the FCEUX script attached below to capture the writes the Game Genie uses to send the codes to its hardware as described in these posts:

My understanding is the bits described as "set if an 8-letter code" or "compare enable" are what actually turns on the "compare and value" ability. When I tested the Game Genie ROM in FCEUX, I found these bits are set for any 8 letter code, it doesn't matter what the "extra bit" (the high bit of the 3rd letter) is. These results make me think the Game Genie only uses the "extra bit" to move the cursor.

Note: If you re-create the test, be aware that if you enter multiple codes for the same address, the Game Genie only uses the first one and marks the others as invalid/disabled. For example, you'll have to test GOSSIP and GOISIP on separate runs, not by entering them both on the same run.

EDIT 2018-05-05: Put the lua file inside a zip file because lua attachments are now disabled for security reasons.

Last edited by Bavi_H on Sat May 05, 2018 7:25 am, edited 1 time in total.
Top

 Post subject: Re: Game GenIe Code Generation AlgorithmPosted: Thu Jul 21, 2016 10:42 pm

Joined: Sat Jul 12, 2014 3:04 pm
Posts: 958
Bavi_H wrote:
Note: If you re-create the test, be aware that if you enter multiple codes for the same address, the Game Genie only uses the first one and marks the others as invalid/disabled. For example, you'll have to test GOSSIP and GOISIP on separate runs, not by entering them both on the same run.

Hmm, that would mean you can't patch the same byte simultaneously in different banks even if it's different.

Quickly verified on real NES/GG/SMB3 that it's 6/8 character that matters, not n2&8: IEUXKGAA (Tanooki Mario start, SMB3) , IEUXKG, IELXKG, IELXKGAA all still perform the modification (bit set without a full 8-character code does not make for an invalid length, apparently). IELXKGAP (compare = 10 instead of 00, but 8-char bit unset) does not, much like IEUXKGAP (compare = 10, 8-char set).

Top

 Post subject: Re: Game GenIe Code Generation AlgorithmPosted: Thu Jul 21, 2016 11:51 pm

Joined: Sun Mar 03, 2013 1:52 am
Posts: 106
Location: Texas, USA
Bavi_H wrote:
be aware that if you enter multiple codes for the same address, the Game Genie only uses the first one and marks the others as invalid/disabled.
Hmm, that would mean you can't patch the same byte simultaneously in different banks even if it's different.

Yep. The Game Genie manual [PDF] says if you enter multiple codes and they don't work as you expected to try entering them in a different order. I think this was in case you tried to enter two codes that used the same address. Since you can't get them both to work at the same time, re-arranging them might make you a little happier that you can at least get one to work at a time, instead of just thinking the disabled code didn't work at all.

Another interesting thing from the manual: I now know that the "programming methods" in the manual describe how you can swap letters in a way that changes the "value" part of the code without affecting the "address" or "compare" parts, and without telling you what the letters actually mean.

(When I first read my cousin's Game Genie manual as a kid, I saw the programming section in the contents and was excited, thinking it would explain how the letters mapped to addresses and values like POKEs on my Commodore 64. I quickly flipped to that section and read it, but I was so mad it only told you to play around with swapping letters and didn't tell you what they meant.)

Top

 Post subject: Re: Game Gene Code Generation AlgorithmPosted: Fri Jul 22, 2016 12:35 am

Joined: Sun Jun 05, 2016 1:41 pm
Posts: 74
I keep wondering why CodeMasters (or whoever came up with the Game Genie coding system) chose to not use bit 8 of the third nybble letter in the code and restrict the resulting address to the top 32K. Had they included the bit in the coding process, they would have been able to address the lower 32K as well, allowing cheats in lower ram, including PPU and joypad registers.

_________________
Tile IDE and tile engine for XNA: http://tide.codeplex.com/
Fancy Fish Mod - Minecraft Mod: http://fancyfishmod.weebly.com/

Top

 Post subject: Re: Game Gene Code Generation AlgorithmPosted: Fri Jul 22, 2016 12:46 am

Joined: Mon Jan 03, 2005 10:36 am
Posts: 3111
Location: Tampere, Finland
colinvella wrote:
I keep wondering why CodeMasters (or whoever came up with the Game Genie coding system) chose to not use bit 8 of the third nybble letter in the code and restrict the resulting address to the top 32K. Had they included the bit in the coding process, they would have been able to address the lower 32K as well, allowing cheats in lower ram, including PPU and joypad registers.

This would not have been technically possible. The cart connector does not have the necessary signals to unmap the 2 KB RAM from the bus (which would be required to override the value). Same goes for the CPU/PPU registers.

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi

Top

 Post subject: Re: Game Gene Code Generation AlgorithmPosted: Fri Jul 22, 2016 12:53 am

Joined: Sun Jun 05, 2016 1:41 pm
Posts: 74
thefox wrote:
colinvella wrote:
I keep wondering why CodeMasters (or whoever came up with the Game Genie coding system) chose to not use bit 8 of the third nybble letter in the code and restrict the resulting address to the top 32K. Had they included the bit in the coding process, they would have been able to address the lower 32K as well, allowing cheats in lower ram, including PPU and joypad registers.

This would not have been technically possible. The cart connector does not have the necessary signals to unmap the 2 KB RAM from the bus (which would be required to override the value). Same goes for the CPU/PPU registers.

I think I see what you mean. Some cartridges can do some nifty tricks with the bus (the MMC5 extended graphics mode and Namco 163 nametable banking comes to mind), but they do not have access to the first 8K main memory accessible to the CPU. This wasn't immediately obvious to me as my cheat system sits between CPU and main memory, not CPU and cartridge.

_________________
Tile IDE and tile engine for XNA: http://tide.codeplex.com/
Fancy Fish Mod - Minecraft Mod: http://fancyfishmod.weebly.com/

Top

 Post subject: Re: Game Gene Code Generation AlgorithmPosted: Fri Jul 22, 2016 1:54 am

Joined: Sun Jun 05, 2016 1:41 pm
Posts: 74
Here's an update of the encoder that sets the 8 letter bit correctly. Only one code is generated.

Code:
public string GameGenieCode
{
get
{
byte[] nybbles = new byte[NeedsComparison ? 8 : 6];

// reverse of
// address = 0x8000 + ((n3 & 7) << 12) | ((n5 & 7) << 8) | ((n4 & 8) << 8) | ((n2 & 7) << 4) | ((n1 & 8) << 4) | (n4 & 7) | (n3 & 8);

// common to both 6-letter and 8-letter codes
nybbles[0] = (byte)(((Value   >> 4) & 8) | ((Value   >>  0) & 7));
nybbles[1] = (byte)(((Address >> 4) & 8) | ((Value   >>  4) & 7));

nybbles[2] = (byte)(((Address >> 4) & 7));
nybbles[3] = (byte)(((Address >> 0) & 8) | ((Address >> 12) & 7));
nybbles[4] = (byte)(((Address >> 8) & 8) | ((Address >>  0) & 7));

if (NeedsComparison)
{
nybbles[2] |= 8; // set 3rd nybble bit 7 to make it behave nicely in real Game Genie

// reverse of
// data = ((n1 & 7) << 4) | ((n0 & 8) << 4) | (n0 & 7) | (n7 & 8);
// compare = ((n7 & 7) << 4) | ((n6 & 8) << 4) | (n6 & 7) | (n5 & 8);
nybbles[5] = (byte)(((CompareValue >> 0) & 8) | ((Address      >> 8) & 7));
nybbles[6] = (byte)(((CompareValue >> 4) & 8) | ((CompareValue >> 0) & 7));
nybbles[7] = (byte)(((Value        >> 0) & 8) | ((CompareValue >> 4) & 7));
}
else // 6 letter code
{
// reverse of
// data = ((n1 & 7) << 4) | ((n0 & 8) << 4) | (n0 & 7) | (n5 & 8);
nybbles[5] = (byte)(((Value   >> 0) & 8) | ((Address >> 8) & 7));
}

StringBuilder stringBuilder = new StringBuilder();
foreach (byte nybble in nybbles)
stringBuilder.Append(gameGenieNybbleToChar[nybble]);

return stringBuilder.ToString();
}
}

public static char[] gameGenieNybbleToChar = new char[]
{ 'A', 'P', 'Z', 'L', 'G', 'I', 'T', 'Y',
'E', 'O', 'X', 'U', 'K', 'S', 'V', 'N' };

_________________
Tile IDE and tile engine for XNA: http://tide.codeplex.com/
Fancy Fish Mod - Minecraft Mod: http://fancyfishmod.weebly.com/

Top

 Post subject: Re: Game Gene Code Generation AlgorithmPosted: Fri Jul 22, 2016 5:27 am
 Formerly ~J-@D!~

Joined: Sun Mar 12, 2006 12:36 am
Posts: 454
Location: Rive nord de Montréal
Bavi_H wrote:
colinvella wrote:
The algorithm generates two code variants because bit 7 of the cheat Address is not used when decoding the cheat properties and can hence be either 1 or 0. The two variants differ only in the 3rd letter. For example, the codes GOSSIP and GOISIP both represent the same cheat (substitute \$14 at address \$D1DD)

When entering codes on an actual Game Genie, the high bit of the third letter helps move the cursor automatically to make entering codes easier.

After you enter the 6th letter, the Game Genie checks if the high bit of the third letter is clear. If so, it will move the cursor to the next line. (If you're on the last line, the cursor will stay on the 6th letter.) You can still add the 7th and 8th letters by pressing B to back up or by clicking on the 7th blank. Any 8-letter code is converted to a "compare and value" modification, no matter what the value of the extra bit is.

If the Game Genie thinks it was an 8-letter code, you can click on the next line to skip the 7th and 8th letters and enter another code. Any 6-letter code is converted to a "value only" modification, no matter what the value of the extra bit is.

But setting the extra bit correctly is a nice thing to do in case the code is ever used on a real Game Genie. When the bit is set wrong, you'll have to manually adjust the cursor.

Oh man, you just gave me the info I needed! I made too a Game Genie code generator/decoder and was wondering what's the purpose of that bit, and I ended up adding a parameter to select which of the 2 equivalent codes to return for encoding a Game Genie code.

_________________
((λ (x) (x x)) (λ (x) (x x)))

Top

 Post subject: Re: Game Gene Code Generation AlgorithmPosted: Fri Jul 22, 2016 7:34 pm

Joined: Sun Mar 03, 2013 1:52 am
Posts: 106
Location: Texas, USA
The most popular explanations of the Game Genie encoding assign values to the letters like this:

letter: APZLGITY
hex...: 01234567

letter: EOXUKSVN
hex...: 89ABCDEF

If you use these assignments, you have to move the bits like this:

Attachment:
File comment: top: In a 6-letter code, letters 1 through 6 are rearranged to value and address.
bottom: In an 8-letter code, letters 1 through 8 are rearranged to value, address, and compare.

extra-bits-high.png [ 8.32 KiB | Viewed 2498 times ]

In A Note on Game Genie Codes for the NES, the author explains if you assign values to the letters this way:

letter: APZLGITY
hex...: 02468ACE

letter: EOXUKSVN
hex...: 13579BDF

Then the bit movement is easier (a shift and some nybble swaps):

Attachment:
File comment: top: In a 6-letter code, letters 1 through 6 are rearranged to value and address.
bottom: In an 8-letter code, letters 1 through 8 are rearranged to value, address, and compare.

extra-bits-low.png [ 10.44 KiB | Viewed 2498 times ]

Top

 Display posts from previous: All posts1 day7 days2 weeks1 month3 months6 months1 year Sort by AuthorPost timeSubject AscendingDescending
 Page 1 of 1 [ 12 posts ]

 All times are UTC - 7 hours

#### Who is online

Users browsing this forum: TmEE and 4 guests

 You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum

Search for:
 Jump to:  Select a forum ------------------ NES / Famicom    NESdev    NESemdev    NES Graphics    NES Music    Homebrew Projects       2018 NESdev Competition       2017 NESdev Competition       2016 NESdev Competition       2014 NESdev Competition       2011 NESdev Competition    Newbie Help Center    NES Hardware and Flash Equipment       Reproduction    NESdev International       FCdev       NESdev China       NESdev Middle East Other    General Stuff    Membler Industries    Other Retro Dev       SNESdev       GBDev    Test Forum Site Issues    phpBB Issues    Web Issues    nesdevWiki