posted by xdaniel on Feb 26, 2016:
Try4ce said:
Regardless, this is pretty fascinating stuff, and we'd love to address it in a shorter video on our channel. If anyone would like to collaborate to help us come to a better understanding of what's going on here, how to explain to people how they could generate their own codes (you're figuring this out with some sort of software?), and help us come up with more codes to feature, that would be great! I'm in the US, and Mario Kart 64 was the only code I could find in this thread that was for a game old enough to work on my GameShark. We would also like to be able to point people to an easy-to-browse resource that includes the codes... is anyone planning to make one?
I can try to help a bit with the "how to generate your own codes" part. There's two ways to create the GameShark codes I know of: the first would be using an emulator with memory viewing/editing capabilities (ex. Nemu64) and ROMs of the games, while the second would be using a GameShark capable of linking up to a PC for code generation.
The first way, via emulation, is probably the easiest as it just requires a copy of Nemu64 v0.8 and the game's ROM image. Leaving the matter of acquiring the ROM aside, it's quite simple. Boot up the game in Nemu, then go into the "Plugins" menu, then select "Debugger: Memory..." to open up the Memory window. There, use the "Address" textbox to go to address A4400000, which is the system's VI_STATUS register, and take note of the 4-byte/32-bit value there - in Mario Kart 64's case, it's 00013016. Now, click the "Search..." button, put that value into the "Search value" textbox (making sure "Hex" is checked and "32 bits (aligned)" selected to the right of it) and click "Search". You'll hopefully wind up with only two possible results, both exactly 0x30 hexadecimal (48 decimal) bytes apart. Make note of both addresses. If you want, you can also double-click them to go to the address in question in the memory editor. For MK64, the two results are 000EB3DC and 000EB40C. I'll get to what to do with these two addresses after describing the alternate way.
Screenshots:
Spoiler
The second way is more involved, as it requires some hardware, as stated before: namely an N64 (obviously), a GameShark Pro with a functioning parallel port on the back, a PC with a parallel port (I believe USB adapters for connecting printers won't work), the game you want to find codes for, and, if the game requires a GS keycode to boot (Zelda, F-Zero, etc.), another game like Super Mario 64, Mario Kart 64 and most others to boot the system, to select the correct keycode, then turn the system off again, swap in the cart that needs the keycode, and then turning everything back on. I should note that the whole procedure can be quite unstable regardless of the setup, and I, personally, have had the best luck using a Windows 98 setup on an old laptop, although at least the "Game Software Code Creator" tool, GSCC for sort, is supposed to also work under Windows XP, at least. See
the Kodewerx EnHacklopedia for more details about the PC connection.
With the N64 booted up and on the GameShark's main menu screen, have the GSCC software on the PC detect the proper settings for communication in its configuration screen, then start the game on the N64 with the Code Generator turned ON. Once somewhere in-game, go to GSCC's RAM editor via the menu "Ram Edit", then "Open Window". Once there, click the "Goto Address" button, then enter "0xA4400000" as the address and click "Goto". The main editor window will now show the memory starting at address A4400000, where you should find the same values as with the Nemu64 method, i.e. 00013016 for MK64. Now, press the "Find Memory" button next to Goto Address, put the value into the "Find What" textbox, make sure "Hex" is selected for "Value" and press "Find Now". This'll freeze the game until the value has been found in memory, so don't be alarmed. Once the value has been found, the game resumes and the RAM editor jumps to the value's location, in this case, again, 000EB3DC (or rather 000EB3D0, as that's how the display works, but the result is in fact at 000EB3DC). Once again, there's another copy of the same value 0x30 bytes away.
Screenshots:
Spoiler
Sorry it's only two, as I mentioned this setup can be kinda unstable, plus that old laptop isn't the fastest, etc.
Now, what values to write to these addresses, and how to turn them into GameShark codes. My codes so far have done two things: one, disable the dither filter (which removes dithering in 16bpp display modes), and two, change the anti-aliasing mode to only resample, not anti-alias. What exactly the four AA modes do I honestly can't say for certain; other people like saturnu or Zoinkity know much more about the N64 hardware than I do. Also, this'll be a very simplified breakdown, so you might want to refer to saturnu's post above for more details about the bits in the register, etc.
First, let's remove the anti-aliasing. The AA mode is encoded in bits 8 and 9 of the VI_STATUS value, which in MK64's case are set to 0, 00013016. Note that this digit could theoretically be something higher than 3, in which case you'd need to do some math to modify only the bits you need. Changing this to 00013216 will disable AA while keeping resampling enabled. I'm not sure if this is an issue on my end, but if I set this to 3, i.e. 00013316, I tend to get scrambled video output on my NTSC system and some distortion on my PAL machine (see the comparison photos below and
this previous post of mine).
Spoiler
Next, removing the dither filtering. Bit 16 in the VI_STATUS value controls this, which is set to 1 in our MK64 example, 00013016. Thus, disabling the filter is as simple as changing 00013016 to 00003016, and putting the two together, we turn 00013016 into 00003216.
Finally, the easiest way to turn this into a GameShark code is by turning it into two 16-bit writes. Split the changed value of 00003216 into two, i.e. 0000 and 3216. 16-bit writes are prefixed with 81 before the address, so the addresses we've written down, 000EB3DC and 000EB40C, become 810EB3DC and 810EB40C, and because we need to use two writes per location, we'll need four codes in total, 810EB3DC, 810EB3DE, 810EB40C and 810EB40E. Thus, the final codes are 810EB3DC 0000, 810EB3DE 3216, 810EB40C 0000 and 810EB40E 3216.
I hope this is in any way useful, no matter to whom. If there's anything wrong with my explanations, feel free to correct me, or if there's any questions, I'll try to answer them.
(Edit: fixed some minor errors)