diff --git a/BizHawk.MultiClient/BizHawk.MultiClient.csproj b/BizHawk.MultiClient/BizHawk.MultiClient.csproj
index 7a9bff9d0b..532ff0d953 100644
--- a/BizHawk.MultiClient/BizHawk.MultiClient.csproj
+++ b/BizHawk.MultiClient/BizHawk.MultiClient.csproj
@@ -132,6 +132,12 @@
     <Compile Include="NEStools\NameTableViewer.cs">
       <SubType>Component</SubType>
     </Compile>
+    <Compile Include="NEStools\NESGameGenie.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="NEStools\NESGameGenie.designer.cs">
+      <DependentUpon>NESGameGenie.cs</DependentUpon>
+    </Compile>
     <Compile Include="NEStools\NESPPU.cs">
       <SubType>Form</SubType>
     </Compile>
@@ -294,6 +300,10 @@
     <EmbeddedResource Include="images\BuilderDialog_moveup.bmp" />
     <EmbeddedResource Include="images\InserSeparator.bmp" />
     <EmbeddedResource Include="images\search.ico" />
+    <EmbeddedResource Include="NEStools\NESGameGenie.resx">
+      <DependentUpon>NESGameGenie.cs</DependentUpon>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
     <EmbeddedResource Include="NEStools\NESPPU.resx">
       <DependentUpon>NESPPU.cs</DependentUpon>
       <SubType>Designer</SubType>
diff --git a/BizHawk.MultiClient/MainForm.Designer.cs b/BizHawk.MultiClient/MainForm.Designer.cs
index 02a5126239..46639da53d 100644
--- a/BizHawk.MultiClient/MainForm.Designer.cs
+++ b/BizHawk.MultiClient/MainForm.Designer.cs
@@ -157,7 +157,6 @@
             this.luaConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.NESToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.pPUViewerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.nameTableViewerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.gameGenieCodesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.helpToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
@@ -704,33 +703,33 @@
             // pauseToolStripMenuItem
             // 
             this.pauseToolStripMenuItem.Name = "pauseToolStripMenuItem";
-            this.pauseToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
+            this.pauseToolStripMenuItem.Size = new System.Drawing.Size(144, 22);
             this.pauseToolStripMenuItem.Text = "&Pause";
             this.pauseToolStripMenuItem.Click += new System.EventHandler(this.pauseToolStripMenuItem_Click);
             // 
             // toolStripSeparator1
             // 
             this.toolStripSeparator1.Name = "toolStripSeparator1";
-            this.toolStripSeparator1.Size = new System.Drawing.Size(149, 6);
+            this.toolStripSeparator1.Size = new System.Drawing.Size(141, 6);
             // 
             // powerToolStripMenuItem
             // 
             this.powerToolStripMenuItem.Name = "powerToolStripMenuItem";
-            this.powerToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
+            this.powerToolStripMenuItem.Size = new System.Drawing.Size(144, 22);
             this.powerToolStripMenuItem.Text = "Power Cycle";
             this.powerToolStripMenuItem.Click += new System.EventHandler(this.powerToolStripMenuItem_Click);
             // 
             // resetToolStripMenuItem
             // 
             this.resetToolStripMenuItem.Name = "resetToolStripMenuItem";
-            this.resetToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
+            this.resetToolStripMenuItem.Size = new System.Drawing.Size(144, 22);
             this.resetToolStripMenuItem.Text = "&Reset";
             this.resetToolStripMenuItem.Click += new System.EventHandler(this.resetToolStripMenuItem_Click);
             // 
             // toolStripSeparator8
             // 
             this.toolStripSeparator8.Name = "toolStripSeparator8";
-            this.toolStripSeparator8.Size = new System.Drawing.Size(149, 6);
+            this.toolStripSeparator8.Size = new System.Drawing.Size(141, 6);
             // 
             // sega8bitToolStripMenuItem
             // 
@@ -739,7 +738,7 @@
             this.overclockWhenKnownSafeToolStripMenuItem,
             this.forceStereoSeparationToolStripMenuItem});
             this.sega8bitToolStripMenuItem.Name = "sega8bitToolStripMenuItem";
-            this.sega8bitToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
+            this.sega8bitToolStripMenuItem.Size = new System.Drawing.Size(144, 22);
             this.sega8bitToolStripMenuItem.Text = "Sega 8-bit";
             // 
             // enableFMChipToolStripMenuItem
@@ -1144,35 +1143,35 @@
             // rAMWatchToolStripMenuItem
             // 
             this.rAMWatchToolStripMenuItem.Name = "rAMWatchToolStripMenuItem";
-            this.rAMWatchToolStripMenuItem.Size = new System.Drawing.Size(143, 22);
+            this.rAMWatchToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
             this.rAMWatchToolStripMenuItem.Text = "RAM &Watch";
             this.rAMWatchToolStripMenuItem.Click += new System.EventHandler(this.RAMWatchToolStripMenuItem_Click);
             // 
             // rAMSearchToolStripMenuItem
             // 
             this.rAMSearchToolStripMenuItem.Name = "rAMSearchToolStripMenuItem";
-            this.rAMSearchToolStripMenuItem.Size = new System.Drawing.Size(143, 22);
+            this.rAMSearchToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
             this.rAMSearchToolStripMenuItem.Text = "RAM &Search";
             this.rAMSearchToolStripMenuItem.Click += new System.EventHandler(this.rAMSearchToolStripMenuItem_Click);
             // 
             // rAMPokeToolStripMenuItem
             // 
             this.rAMPokeToolStripMenuItem.Name = "rAMPokeToolStripMenuItem";
-            this.rAMPokeToolStripMenuItem.Size = new System.Drawing.Size(143, 22);
+            this.rAMPokeToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
             this.rAMPokeToolStripMenuItem.Text = "RAM &Poke";
             this.rAMPokeToolStripMenuItem.Click += new System.EventHandler(this.rAMPokeToolStripMenuItem_Click);
             // 
             // hexEditorToolStripMenuItem
             // 
             this.hexEditorToolStripMenuItem.Name = "hexEditorToolStripMenuItem";
-            this.hexEditorToolStripMenuItem.Size = new System.Drawing.Size(143, 22);
+            this.hexEditorToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
             this.hexEditorToolStripMenuItem.Text = "&Hex Editor";
             this.hexEditorToolStripMenuItem.Click += new System.EventHandler(this.hexEditorToolStripMenuItem_Click);
             // 
             // luaConsoleToolStripMenuItem
             // 
             this.luaConsoleToolStripMenuItem.Name = "luaConsoleToolStripMenuItem";
-            this.luaConsoleToolStripMenuItem.Size = new System.Drawing.Size(143, 22);
+            this.luaConsoleToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
             this.luaConsoleToolStripMenuItem.Text = "Lua Console";
             this.luaConsoleToolStripMenuItem.Click += new System.EventHandler(this.luaConsoleToolStripMenuItem_Click);
             // 
@@ -1180,7 +1179,6 @@
             // 
             this.NESToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
             this.pPUViewerToolStripMenuItem,
-            this.nameTableViewerToolStripMenuItem,
             this.gameGenieCodesToolStripMenuItem});
             this.NESToolStripMenuItem.Name = "NESToolStripMenuItem";
             this.NESToolStripMenuItem.Size = new System.Drawing.Size(38, 20);
@@ -1189,23 +1187,16 @@
             // pPUViewerToolStripMenuItem
             // 
             this.pPUViewerToolStripMenuItem.Name = "pPUViewerToolStripMenuItem";
-            this.pPUViewerToolStripMenuItem.Size = new System.Drawing.Size(176, 22);
+            this.pPUViewerToolStripMenuItem.Size = new System.Drawing.Size(228, 22);
             this.pPUViewerToolStripMenuItem.Text = "&PPU Viewer";
             this.pPUViewerToolStripMenuItem.Click += new System.EventHandler(this.pPUViewerToolStripMenuItem_Click);
             // 
-            // nameTableViewerToolStripMenuItem
-            // 
-            this.nameTableViewerToolStripMenuItem.Enabled = false;
-            this.nameTableViewerToolStripMenuItem.Name = "nameTableViewerToolStripMenuItem";
-            this.nameTableViewerToolStripMenuItem.Size = new System.Drawing.Size(176, 22);
-            this.nameTableViewerToolStripMenuItem.Text = "&Name Table Viewer";
-            // 
             // gameGenieCodesToolStripMenuItem
             // 
-            this.gameGenieCodesToolStripMenuItem.Enabled = false;
             this.gameGenieCodesToolStripMenuItem.Name = "gameGenieCodesToolStripMenuItem";
-            this.gameGenieCodesToolStripMenuItem.Size = new System.Drawing.Size(176, 22);
-            this.gameGenieCodesToolStripMenuItem.Text = "&Game Genie Codes";
+            this.gameGenieCodesToolStripMenuItem.Size = new System.Drawing.Size(228, 22);
+            this.gameGenieCodesToolStripMenuItem.Text = "&Game Genie Encoder/Decoder";
+            this.gameGenieCodesToolStripMenuItem.Click += new System.EventHandler(this.gameGenieCodesToolStripMenuItem_Click);
             // 
             // helpToolStripMenuItem
             // 
@@ -1384,7 +1375,6 @@
         private System.Windows.Forms.ToolStripMenuItem replayInputLogToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem NESToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem pPUViewerToolStripMenuItem;
-        private System.Windows.Forms.ToolStripMenuItem nameTableViewerToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem gameGenieCodesToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem enableRewindToolStripMenuItem;
     }
diff --git a/BizHawk.MultiClient/MainForm.cs b/BizHawk.MultiClient/MainForm.cs
index a1f900b17e..21fc9908da 100644
--- a/BizHawk.MultiClient/MainForm.cs
+++ b/BizHawk.MultiClient/MainForm.cs
@@ -1223,5 +1223,11 @@ namespace BizHawk.MultiClient
         {
 			HandlePlatformMenus();
         }
+
+        private void gameGenieCodesToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            NESGameGenie g = new NESGameGenie();
+            g.Show();
+        }
 	}
 }
\ No newline at end of file
diff --git a/BizHawk.MultiClient/NEStools/NESGameGenie.Designer.cs b/BizHawk.MultiClient/NEStools/NESGameGenie.Designer.cs
new file mode 100644
index 0000000000..c23c68eafb
--- /dev/null
+++ b/BizHawk.MultiClient/NEStools/NESGameGenie.Designer.cs
@@ -0,0 +1,406 @@
+namespace BizHawk.MultiClient
+{
+    partial class NESGameGenie
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.GameGenieCode = new System.Windows.Forms.TextBox();
+            this.GameGenieCodeBox = new System.Windows.Forms.GroupBox();
+            this.label3 = new System.Windows.Forms.Label();
+            this.label2 = new System.Windows.Forms.Label();
+            this.label1 = new System.Windows.Forms.Label();
+            this.CompareBox = new System.Windows.Forms.TextBox();
+            this.ValueBox = new System.Windows.Forms.TextBox();
+            this.AddressBox = new System.Windows.Forms.TextBox();
+            this.AddCheat = new System.Windows.Forms.Button();
+            this.ButtonPanel = new System.Windows.Forms.Panel();
+            this.N = new System.Windows.Forms.Button();
+            this.V = new System.Windows.Forms.Button();
+            this.S = new System.Windows.Forms.Button();
+            this.K = new System.Windows.Forms.Button();
+            this.U = new System.Windows.Forms.Button();
+            this.X = new System.Windows.Forms.Button();
+            this.O = new System.Windows.Forms.Button();
+            this.E = new System.Windows.Forms.Button();
+            this.Y = new System.Windows.Forms.Button();
+            this.T = new System.Windows.Forms.Button();
+            this.I = new System.Windows.Forms.Button();
+            this.G = new System.Windows.Forms.Button();
+            this.L = new System.Windows.Forms.Button();
+            this.Z = new System.Windows.Forms.Button();
+            this.P = new System.Windows.Forms.Button();
+            this.A = new System.Windows.Forms.Button();
+            this.groupBox1 = new System.Windows.Forms.GroupBox();
+            this.GameGenieCodeBox.SuspendLayout();
+            this.ButtonPanel.SuspendLayout();
+            this.groupBox1.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // GameGenieCode
+            // 
+            this.GameGenieCode.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper;
+            this.GameGenieCode.Location = new System.Drawing.Point(6, 19);
+            this.GameGenieCode.MaxLength = 8;
+            this.GameGenieCode.Name = "GameGenieCode";
+            this.GameGenieCode.Size = new System.Drawing.Size(86, 20);
+            this.GameGenieCode.TabIndex = 0;
+            this.GameGenieCode.TextChanged += new System.EventHandler(this.GameGenieCode_TextChanged);
+            this.GameGenieCode.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.GameGenieCode_KeyPress);
+            // 
+            // GameGenieCodeBox
+            // 
+            this.GameGenieCodeBox.Controls.Add(this.GameGenieCode);
+            this.GameGenieCodeBox.Location = new System.Drawing.Point(12, 85);
+            this.GameGenieCodeBox.Name = "GameGenieCodeBox";
+            this.GameGenieCodeBox.Size = new System.Drawing.Size(115, 54);
+            this.GameGenieCodeBox.TabIndex = 1;
+            this.GameGenieCodeBox.TabStop = false;
+            this.GameGenieCodeBox.Text = "Game Genie Code";
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.Location = new System.Drawing.Point(15, 68);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(34, 13);
+            this.label3.TabIndex = 5;
+            this.label3.Text = "Value";
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(15, 42);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(49, 13);
+            this.label2.TabIndex = 4;
+            this.label2.Text = "Compare";
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(15, 16);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(45, 13);
+            this.label1.TabIndex = 3;
+            this.label1.Text = "Address";
+            // 
+            // CompareBox
+            // 
+            this.CompareBox.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper;
+            this.CompareBox.Location = new System.Drawing.Point(87, 39);
+            this.CompareBox.MaxLength = 2;
+            this.CompareBox.Name = "CompareBox";
+            this.CompareBox.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
+            this.CompareBox.Size = new System.Drawing.Size(27, 20);
+            this.CompareBox.TabIndex = 2;
+            this.CompareBox.TextChanged += new System.EventHandler(this.CompareBox_TextChanged);
+            this.CompareBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.CompareBox_KeyPress);
+            // 
+            // ValueBox
+            // 
+            this.ValueBox.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper;
+            this.ValueBox.Location = new System.Drawing.Point(87, 65);
+            this.ValueBox.MaxLength = 2;
+            this.ValueBox.Name = "ValueBox";
+            this.ValueBox.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
+            this.ValueBox.Size = new System.Drawing.Size(27, 20);
+            this.ValueBox.TabIndex = 1;
+            this.ValueBox.TextChanged += new System.EventHandler(this.ValueBox_TextChanged);
+            this.ValueBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.ValueBox_KeyPress);
+            // 
+            // AddressBox
+            // 
+            this.AddressBox.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper;
+            this.AddressBox.Location = new System.Drawing.Point(68, 13);
+            this.AddressBox.MaxLength = 4;
+            this.AddressBox.Name = "AddressBox";
+            this.AddressBox.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
+            this.AddressBox.Size = new System.Drawing.Size(46, 20);
+            this.AddressBox.TabIndex = 0;
+            this.AddressBox.TextChanged += new System.EventHandler(this.AddressBox_TextChanged);
+            this.AddressBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.AddressBox_KeyPress);
+            // 
+            // AddCheat
+            // 
+            this.AddCheat.Enabled = false;
+            this.AddCheat.Location = new System.Drawing.Point(177, 217);
+            this.AddCheat.Name = "AddCheat";
+            this.AddCheat.Size = new System.Drawing.Size(75, 21);
+            this.AddCheat.TabIndex = 3;
+            this.AddCheat.Text = "Add Cheat";
+            this.AddCheat.UseVisualStyleBackColor = true;
+            // 
+            // ButtonPanel
+            // 
+            this.ButtonPanel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+            this.ButtonPanel.Controls.Add(this.N);
+            this.ButtonPanel.Controls.Add(this.V);
+            this.ButtonPanel.Controls.Add(this.S);
+            this.ButtonPanel.Controls.Add(this.K);
+            this.ButtonPanel.Controls.Add(this.U);
+            this.ButtonPanel.Controls.Add(this.X);
+            this.ButtonPanel.Controls.Add(this.O);
+            this.ButtonPanel.Controls.Add(this.E);
+            this.ButtonPanel.Controls.Add(this.Y);
+            this.ButtonPanel.Controls.Add(this.T);
+            this.ButtonPanel.Controls.Add(this.I);
+            this.ButtonPanel.Controls.Add(this.G);
+            this.ButtonPanel.Controls.Add(this.L);
+            this.ButtonPanel.Controls.Add(this.Z);
+            this.ButtonPanel.Controls.Add(this.P);
+            this.ButtonPanel.Controls.Add(this.A);
+            this.ButtonPanel.Location = new System.Drawing.Point(12, 12);
+            this.ButtonPanel.Name = "ButtonPanel";
+            this.ButtonPanel.Size = new System.Drawing.Size(240, 67);
+            this.ButtonPanel.TabIndex = 4;
+            // 
+            // N
+            // 
+            this.N.Location = new System.Drawing.Point(206, 35);
+            this.N.Name = "N";
+            this.N.Size = new System.Drawing.Size(26, 23);
+            this.N.TabIndex = 15;
+            this.N.Text = "N";
+            this.N.UseVisualStyleBackColor = true;
+            this.N.Click += new System.EventHandler(this.Keypad_Click);
+            // 
+            // V
+            // 
+            this.V.Location = new System.Drawing.Point(178, 35);
+            this.V.Name = "V";
+            this.V.Size = new System.Drawing.Size(26, 23);
+            this.V.TabIndex = 14;
+            this.V.Text = "V";
+            this.V.UseVisualStyleBackColor = true;
+            this.V.Click += new System.EventHandler(this.Keypad_Click);
+            // 
+            // S
+            // 
+            this.S.Location = new System.Drawing.Point(149, 35);
+            this.S.Name = "S";
+            this.S.Size = new System.Drawing.Size(26, 23);
+            this.S.TabIndex = 13;
+            this.S.Text = "S";
+            this.S.UseVisualStyleBackColor = true;
+            this.S.Click += new System.EventHandler(this.Keypad_Click);
+            // 
+            // K
+            // 
+            this.K.Location = new System.Drawing.Point(121, 35);
+            this.K.Name = "K";
+            this.K.Size = new System.Drawing.Size(26, 23);
+            this.K.TabIndex = 12;
+            this.K.Text = "K";
+            this.K.UseVisualStyleBackColor = true;
+            this.K.Click += new System.EventHandler(this.Keypad_Click);
+            // 
+            // U
+            // 
+            this.U.Location = new System.Drawing.Point(91, 35);
+            this.U.Name = "U";
+            this.U.Size = new System.Drawing.Size(26, 23);
+            this.U.TabIndex = 11;
+            this.U.Text = "U";
+            this.U.UseVisualStyleBackColor = true;
+            this.U.Click += new System.EventHandler(this.Keypad_Click);
+            // 
+            // X
+            // 
+            this.X.Location = new System.Drawing.Point(63, 35);
+            this.X.Name = "X";
+            this.X.Size = new System.Drawing.Size(26, 23);
+            this.X.TabIndex = 10;
+            this.X.Text = "X";
+            this.X.UseVisualStyleBackColor = true;
+            this.X.Click += new System.EventHandler(this.Keypad_Click);
+            // 
+            // O
+            // 
+            this.O.Location = new System.Drawing.Point(34, 35);
+            this.O.Name = "O";
+            this.O.Size = new System.Drawing.Size(26, 23);
+            this.O.TabIndex = 9;
+            this.O.Text = "O";
+            this.O.UseVisualStyleBackColor = true;
+            this.O.Click += new System.EventHandler(this.Keypad_Click);
+            // 
+            // E
+            // 
+            this.E.Location = new System.Drawing.Point(6, 35);
+            this.E.Name = "E";
+            this.E.Size = new System.Drawing.Size(26, 23);
+            this.E.TabIndex = 8;
+            this.E.Text = "E";
+            this.E.UseVisualStyleBackColor = true;
+            this.E.Click += new System.EventHandler(this.Keypad_Click);
+            // 
+            // Y
+            // 
+            this.Y.Location = new System.Drawing.Point(206, 5);
+            this.Y.Name = "Y";
+            this.Y.Size = new System.Drawing.Size(26, 23);
+            this.Y.TabIndex = 7;
+            this.Y.Text = "Y";
+            this.Y.UseVisualStyleBackColor = true;
+            this.Y.Click += new System.EventHandler(this.Keypad_Click);
+            // 
+            // T
+            // 
+            this.T.Location = new System.Drawing.Point(178, 5);
+            this.T.Name = "T";
+            this.T.Size = new System.Drawing.Size(26, 23);
+            this.T.TabIndex = 6;
+            this.T.Text = "T";
+            this.T.UseVisualStyleBackColor = true;
+            this.T.Click += new System.EventHandler(this.Keypad_Click);
+            // 
+            // I
+            // 
+            this.I.Location = new System.Drawing.Point(149, 5);
+            this.I.Name = "I";
+            this.I.Size = new System.Drawing.Size(26, 23);
+            this.I.TabIndex = 5;
+            this.I.Text = "I";
+            this.I.UseVisualStyleBackColor = true;
+            this.I.Click += new System.EventHandler(this.Keypad_Click);
+            // 
+            // G
+            // 
+            this.G.Location = new System.Drawing.Point(121, 5);
+            this.G.Name = "G";
+            this.G.Size = new System.Drawing.Size(26, 23);
+            this.G.TabIndex = 4;
+            this.G.Text = "G";
+            this.G.UseVisualStyleBackColor = true;
+            this.G.Click += new System.EventHandler(this.Keypad_Click);
+            // 
+            // L
+            // 
+            this.L.Location = new System.Drawing.Point(91, 5);
+            this.L.Name = "L";
+            this.L.Size = new System.Drawing.Size(26, 23);
+            this.L.TabIndex = 3;
+            this.L.Text = "L";
+            this.L.UseVisualStyleBackColor = true;
+            this.L.Click += new System.EventHandler(this.Keypad_Click);
+            // 
+            // Z
+            // 
+            this.Z.Location = new System.Drawing.Point(63, 5);
+            this.Z.Name = "Z";
+            this.Z.Size = new System.Drawing.Size(26, 23);
+            this.Z.TabIndex = 2;
+            this.Z.Text = "Z";
+            this.Z.UseVisualStyleBackColor = true;
+            this.Z.Click += new System.EventHandler(this.Keypad_Click);
+            // 
+            // P
+            // 
+            this.P.Location = new System.Drawing.Point(34, 5);
+            this.P.Name = "P";
+            this.P.Size = new System.Drawing.Size(26, 23);
+            this.P.TabIndex = 1;
+            this.P.Text = "P";
+            this.P.UseVisualStyleBackColor = true;
+            this.P.Click += new System.EventHandler(this.Keypad_Click);
+            // 
+            // A
+            // 
+            this.A.Location = new System.Drawing.Point(6, 5);
+            this.A.Name = "A";
+            this.A.Size = new System.Drawing.Size(26, 23);
+            this.A.TabIndex = 0;
+            this.A.Text = "A";
+            this.A.UseVisualStyleBackColor = true;
+            this.A.Click += new System.EventHandler(this.Keypad_Click);
+            // 
+            // groupBox1
+            // 
+            this.groupBox1.Controls.Add(this.label3);
+            this.groupBox1.Controls.Add(this.label1);
+            this.groupBox1.Controls.Add(this.label2);
+            this.groupBox1.Controls.Add(this.AddressBox);
+            this.groupBox1.Controls.Add(this.ValueBox);
+            this.groupBox1.Controls.Add(this.CompareBox);
+            this.groupBox1.Location = new System.Drawing.Point(12, 145);
+            this.groupBox1.Name = "groupBox1";
+            this.groupBox1.Size = new System.Drawing.Size(126, 93);
+            this.groupBox1.TabIndex = 5;
+            this.groupBox1.TabStop = false;
+            // 
+            // NESGameGenie
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(290, 266);
+            this.Controls.Add(this.groupBox1);
+            this.Controls.Add(this.ButtonPanel);
+            this.Controls.Add(this.AddCheat);
+            this.Controls.Add(this.GameGenieCodeBox);
+            this.Name = "NESGameGenie";
+            this.Text = "Game Genie Encoder / Decoder";
+            this.Load += new System.EventHandler(this.NESGameGenie_Load);
+            this.GameGenieCodeBox.ResumeLayout(false);
+            this.GameGenieCodeBox.PerformLayout();
+            this.ButtonPanel.ResumeLayout(false);
+            this.groupBox1.ResumeLayout(false);
+            this.groupBox1.PerformLayout();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.TextBox GameGenieCode;
+        private System.Windows.Forms.GroupBox GameGenieCodeBox;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.TextBox CompareBox;
+        private System.Windows.Forms.TextBox ValueBox;
+        private System.Windows.Forms.TextBox AddressBox;
+        private System.Windows.Forms.Button AddCheat;
+        private System.Windows.Forms.Panel ButtonPanel;
+        private System.Windows.Forms.Button L;
+        private System.Windows.Forms.Button Z;
+        private System.Windows.Forms.Button P;
+        private System.Windows.Forms.Button A;
+        private System.Windows.Forms.Button Y;
+        private System.Windows.Forms.Button T;
+        private System.Windows.Forms.Button I;
+        private System.Windows.Forms.Button G;
+        private System.Windows.Forms.Button N;
+        private System.Windows.Forms.Button V;
+        private System.Windows.Forms.Button S;
+        private System.Windows.Forms.Button K;
+        private System.Windows.Forms.Button U;
+        private System.Windows.Forms.Button X;
+        private System.Windows.Forms.Button O;
+        private System.Windows.Forms.Button E;
+        private System.Windows.Forms.GroupBox groupBox1;
+    }
+}
\ No newline at end of file
diff --git a/BizHawk.MultiClient/NEStools/NESGameGenie.cs b/BizHawk.MultiClient/NEStools/NESGameGenie.cs
new file mode 100644
index 0000000000..58c2fea5e0
--- /dev/null
+++ b/BizHawk.MultiClient/NEStools/NESGameGenie.cs
@@ -0,0 +1,245 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace BizHawk.MultiClient
+{
+    public partial class NESGameGenie : Form
+    {
+        int address = -1;
+        int value = -1;
+        int compare = -1;
+        Dictionary<char, int> GameGenieTable = new Dictionary<char, int>();
+
+        public NESGameGenie()
+        {
+            InitializeComponent();
+        }
+
+        private void NESGameGenie_Load(object sender, EventArgs e)
+        {
+            GameGenieTable.Add('A', 0);     //0000
+            GameGenieTable.Add('P', 1);     //0001
+            GameGenieTable.Add('Z', 2);     //0010
+            GameGenieTable.Add('L', 3);     //0011
+            GameGenieTable.Add('G', 4);     //0100
+            GameGenieTable.Add('I', 5);     //0101
+            GameGenieTable.Add('T', 6);     //0110
+            GameGenieTable.Add('Y', 7);     //0111
+            GameGenieTable.Add('E', 8);     //1000
+            GameGenieTable.Add('O', 9);     //1001
+            GameGenieTable.Add('X', 10);    //1010
+            GameGenieTable.Add('U', 11);    //1011
+            GameGenieTable.Add('K', 12);    //1100
+            GameGenieTable.Add('S', 13);    //1101
+            GameGenieTable.Add('V', 14);    //1110
+            GameGenieTable.Add('N', 15);    //1111
+        }
+
+        private void GameGenieCode_KeyPress(object sender, KeyPressEventArgs e)
+        {
+            //Make uppercase
+            if (e.KeyChar > 97 && e.KeyChar < 123)
+                e.KeyChar -= (char)32;
+
+            if (!(GameGenieTable.ContainsKey(e.KeyChar))) 
+                e.Handled = true;
+        }
+
+        private int GetBit(int value, int bit)
+        {
+            return (value >> bit) & 1;
+        }
+
+        private void DecodeGameGenieCode(string code)
+        {
+            //char 3 bit 3 denotes the code length.
+            if (code.Length == 6)
+            {
+                //Char # |   1   |   2   |   3   |   4   |   5   |   6   |
+                //Bit  # |3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0|
+                //maps to|1|6|7|8|H|2|3|4|-|I|J|K|L|A|B|C|D|M|N|O|5|E|F|G|
+                value = 0;
+                address = 0x8000;
+                int x;
+
+                GameGenieTable.TryGetValue(code[0], out x);
+                value |= (x & 0x07);
+                value |= (x & 0x08) << 4;
+
+                GameGenieTable.TryGetValue(code[1], out x);
+                value |= (x & 0x07) << 4;
+                address |= (x & 0x08) << 4; 
+                
+                GameGenieTable.TryGetValue(code[2], out x);
+                address |= (x & 0x07) << 4;
+
+                GameGenieTable.TryGetValue(code[3], out x);
+                address |= (x & 0x07) << 12;
+                address |= (x & 0x08);
+
+                GameGenieTable.TryGetValue(code[4], out x);
+                address |= (x & 0x07);
+                address |= (x & 0x08) << 8;
+                
+                GameGenieTable.TryGetValue(code[5], out x);
+                address |= (x & 0x07) << 8;
+                value |= (x & 0x08);
+
+                SetProperties();
+
+            }
+            else if (code.Length == 8)
+            {
+                //Char # |   1   |   2   |   3   |   4   |   5   |   6   |   7   |   8   |
+                //Bit  # |3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0|
+                //maps to|1|6|7|8|H|2|3|4|-|I|J|K|L|A|B|C|D|M|N|O|%|E|F|G|!|^|&|*|5|@|#|$|
+                value = 0;
+                address = 0x8000;
+                compare = 0;
+                int x;
+
+                GameGenieTable.TryGetValue(code[0], out x);
+                value |= (x & 0x07);
+                value |= (x & 0x08) << 4;
+
+                GameGenieTable.TryGetValue(code[1], out x);
+                value |= (x & 0x07) << 4;
+                address |= (x & 0x08) << 4;
+
+                GameGenieTable.TryGetValue(code[2], out x);
+                address |= (x & 0x07) << 4;
+
+                GameGenieTable.TryGetValue(code[3], out x);
+                address |= (x & 0x07) << 12;
+                address |= (x & 0x08);
+
+                GameGenieTable.TryGetValue(code[4], out x);
+                address |= (x & 0x07);
+                address |= (x & 0x08) << 8;
+
+                GameGenieTable.TryGetValue(code[5], out x);
+                address |= (x & 0x07) << 8;
+                compare |= (x & 0x08);
+
+                GameGenieTable.TryGetValue(code[6], out x);
+                compare |= (x & 0x07);
+                compare |= (x & 0x08) << 4;
+
+                GameGenieTable.TryGetValue(code[7], out x);
+                compare |= (x & 0x07) << 4;
+                value |= (x & 0x08);
+                SetProperties();
+            }
+        }
+
+        private void SetProperties()
+        {
+            if (address >= 0)
+                AddressBox.Text = String.Format("{0:X4}", address);
+            else
+                AddressBox.Text = "";
+
+            if (compare >= 0)
+                CompareBox.Text = String.Format("{0:X2}", compare);
+            else
+                CompareBox.Text = "";
+
+            if (value >= 0)
+                ValueBox.Text = String.Format("{0:X2}", value);
+
+        }
+
+        private void ClearProperties()
+        {
+            address = -1;
+            value = -1;
+            compare = -1;
+            AddressBox.Text = "";
+            CompareBox.Text = "";
+            ValueBox.Text = "";
+        }
+
+        private void GameGenieCode_TextChanged(object sender, EventArgs e)
+        {
+            if (GameGenieCode.Text.Length == 6 || GameGenieCode.Text.Length == 8)
+                DecodeGameGenieCode(GameGenieCode.Text);
+            else
+                ClearProperties();
+        }
+
+        private void Keypad_Click(object sender, EventArgs e)
+        {
+            if (GameGenieCode.Text.Length < 8)
+            {
+                if (sender == A) GameGenieCode.Text += "A";
+                if (sender == P) GameGenieCode.Text += "P";
+                if (sender == Z) GameGenieCode.Text += "Z";
+                if (sender == L) GameGenieCode.Text += "L";
+                if (sender == G) GameGenieCode.Text += "G";
+                if (sender == I) GameGenieCode.Text += "I";
+                if (sender == T) GameGenieCode.Text += "T";
+                if (sender == Y) GameGenieCode.Text += "Y";
+                if (sender == E) GameGenieCode.Text += "E";
+                if (sender == O) GameGenieCode.Text += "O";
+                if (sender == X) GameGenieCode.Text += "X";
+                if (sender == U) GameGenieCode.Text += "U";
+                if (sender == K) GameGenieCode.Text += "K";
+                if (sender == S) GameGenieCode.Text += "S";
+                if (sender == V) GameGenieCode.Text += "V";
+                if (sender == N) GameGenieCode.Text += "N";
+            }
+        }
+
+        private void AddressBox_KeyPress(object sender, KeyPressEventArgs e)
+        {
+            //TODO: IsValidHex
+            //if not ignore input
+        }
+
+        private void CompareBox_KeyPress(object sender, KeyPressEventArgs e)
+        {
+            //TODO: IsValidHex
+        }
+
+        private void ValueBox_KeyPress(object sender, KeyPressEventArgs e)
+        {
+            //TODO: IsValidHex
+        }
+
+        private void AddressBox_TextChanged(object sender, EventArgs e)
+        {
+            /*
+            int a = int.Parse(AddressBox.Text); //TODO: try/catch just in case?
+            if (a >= 0x8000)
+            {
+                if (ValueBox.Text.Length > 0 && CompareBox.Text.Length > 0)
+                {
+                    address = a;
+                    EncodeGameGenie(); //TODO: check to make sure value & compare are set
+                }
+            }
+            */ //TODO: decoder will change the text and trigger this event, find a way around it
+        }
+
+        private void CompareBox_TextChanged(object sender, EventArgs e)
+        {
+            
+        }
+
+        private void ValueBox_TextChanged(object sender, EventArgs e)
+        {
+
+        }
+
+        private void EncodeGameGenie()
+        {
+
+        }
+    }
+}
diff --git a/BizHawk.MultiClient/NEStools/NESGameGenie.resx b/BizHawk.MultiClient/NEStools/NESGameGenie.resx
new file mode 100644
index 0000000000..ff31a6db56
--- /dev/null
+++ b/BizHawk.MultiClient/NEStools/NESGameGenie.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/BizHawk.MultiClient/NEStools/NESPPU.cs b/BizHawk.MultiClient/NEStools/NESPPU.cs
index 1630e18037..a30f31889f 100644
--- a/BizHawk.MultiClient/NEStools/NESPPU.cs
+++ b/BizHawk.MultiClient/NEStools/NESPPU.cs
@@ -118,9 +118,18 @@ namespace BizHawk.MultiClient
             }
 			PatternView.pattern.UnlockBits(bmpdata);
 			PatternView.Refresh();
+
+            //Nametable viewer
+            for (int i = 0; i < 30; i++)
+            {
+                for (int j = 0; j < 32; j++)
+                {
+                    int v = Nes.ppu.ppubus_read(0x2000 + i + j);
+                }
+            }
 		}
 
-		private void NESPPU_Load(object sender, EventArgs e)
+        private void NESPPU_Load(object sender, EventArgs e)
 		{
 			LoadConfigSettings();
 			Nes = Global.Emulator as NES;