# Technical Overview Game Genie codes are 6 or 8 characters. 6-character codes translate to a 15-bit address and 8-bit data byte. 8-character codes are the same but include a compare byte, which is used to conditionally return a value based on an existing in-memory value (which is largely there for [[bank switching]]). ## Code Mapping Game Genie codes use the following mapping: | A | 0 | | --- | --- | | P | 1 | | Z | 2 | | L | 3 | | G | 4 | | I | 5 | | T | 6 | | Y | 7 | | E | 8 | | O | 9 | | X | 10 | | U | 11 | | K | 12 | | S | 13 | | V | 14 | | N | 15 | ## Decoding Decoding consists of: 1. Turning the code into numeric values. 2. Applying bitmask operations to generate an address and a data value. The way this is done is dependent on the code length. ### 6-Character Codes This is done as follows: ```python n0, n1, n2, n3, n4, n5 = [ CODE_TABLE[c] for c in code ] address = ( 0x8000 + ((n3 & 0b0111) << 12) | ((n5 & 0b0111) << 8) | ((n4 & 0b1000) << 8) | ((n2 & 0b0111) << 4) | ((n1 & 0b1000) << 4) | (n4 & 0b0111) | (n3 & 0b1000) ) data = ( ((n1 & 0b0111) << 4) | ((n0 & 0b1000) << 4) | (n0 & 0b0111) | (n5 & 0b1000) ) ``` ### 8-Character Codes This is similar. In fact, `address` is the same as before, but `data` has changed and we now set `compare`: ```python n0, n1, n2, n3, n4, n5, n6, n7 = [ CODE_TABLE[c] for c in code ] address = ( 0x8000 + ((n3 & 0b0111) << 12) | ((n5 & 0b0111) << 8) | ((n4 & 0b1000) << 8) | ((n2 & 0b0111) << 4) | ((n1 & 0b1000) << 4) | (n4 & 0b0111) | (n3 & 0b1000) ) # Only the last OR value changes. data = ( ((n1 & 0b0111) << 4) | ((n0 & 0b1000) << 4) | (n0 & 0b0111) | (n7 & 0b1000) ) compare = ( ((n7 & 0b0111) << 4) | ((n6 & 0b1000) << 4) | (n6 & 0b0111) | (n5 & 0b1000) ) ``` ### Combined ```python n = [ CODE_TABLE[c] for c in code ] address = ( 0x8000 + ((n[3] & 0b0111) << 12) | ((n[5] & 0b0111) << 8) | ((n[4] & 0b1000) << 8) | ((n[2] & 0b0111) << 4) | ((n[1] & 0b1000) << 4) | (n[4] & 0b0111) | (n[3] & 0b1000) ) data = ( ((n[1] & 0b0111) << 4) | ((n[0] & 0b1000) << 4) | (n[0] & 0b0111) ) if len(n) == 6: data |= (n[5] & 0b1000) compare = None else: data |= (n[7] & 0b1000) compare = ( ((n[7] & 0b0111) << 4) | ((n[6] & 0b1000) << 4) | (n[6] & 0b0111) | (n[5] & 0b1000) ) return address, data, compare ``` ## Encoding To encode, we reverse those operations, turning an address and data into the individual code numeric values and then feeding them back through the translation table. ### 6-Character Codes ```python n0 = ((data >> 4) & 0b1000) | (data & 0b0111) n1 = ((address >> 4) & 0b1000) | ((data >> 4) & 0b0111) n2 = (address >> 4) & 0b0111 n3 = ((address >> 12) & 0b0111) | (address & 0b1000) n4 = ((address >> 8) & 0b1000) | (address & 0b0111) n5 = ((address >> 8) & 0b0111) | (data & 0b1000) code = ''.join( REVERSE_CODE_TABLE[n] for n in (n0, n1, n2, n3, n4, n5) ) ``` ### 8-Character Codes ```python n0 = ((data >> 4) & 0b1000) | (data & 0b0111) n1 = ((address >> 4) & 0b1000) | ((data >> 4) & 0b0111) n2 = (address >> 4) & 0b0111 n3 = ((address >> 12) & 0b0111) | (address & 0b1000) n4 = ((address >> 8) & 0b1000) | (address & 0b0111) n5 = ((address >> 8) & 0b0111) | (compare & 0b1000) n6 = ((compare >> 4) & 0b1000) | (compare & 0b0111) n7 = ((compare >> 4) & 0b0111) | (data & 0b1000) code = ''.join( REVERSE_CODE_TABLE[n] for n in (n0, n1, n2, n3, n4, n5, n6, n7) ) ``` ### Combined ```python n = [ ((data >> 4) & 0b1000) | (data & 0b0111), ((address >> 4) & 0b1000) | ((data >> 4) & 0b0111), (address >> 4) & 0b0111, ((address >> 12) & 0b0111) | (address & 0b1000), ((address >> 8) & 0b1000) | (address & 0b0111), ] if compare is None: n.append(((address >> 8) & 0b0111) | (data & 0b1000)) else: n += [ ((address >> 8) & 0b0111) | (compare & 0b1000), ((compare >> 4) & 0b1000) | (compare & 0b0111), ((compare >> 4) & 0b0111) | (data & 0b1000), ] return ''.join( REVERSE_CODE_TABLE[i] for i in n ) ``` ## Resources [Game Genie Technical Notes](https://tuxnes.sourceforge.net/gamegenie.html)