Intro to Game Hacking on the NES
2:51AM Aug 1, 2020
game genie codes
Parts of way cool things all because of the people I met and the experiences I had at my first hacker conference. All at hope number six. I hope that you get to experience hope 2020 and whatever other hacker conferences and hacker events and hacker mindsets and hacker thingies that you like doing it's way worth doing. Maybe it'll change your life or the way better to I think it will. I hope it will. In any case, I hope you will join us for hope 2020
wells here now he's living.
We have no names man. No names. We are nameless. This is a marvel. Kidding, Holocaust 24 hours a day for the rest of our lives. The powers that be are hard at work,
dumbing us to death.
So, to defend ourselves and fight against assimilating this dullness to our thought processes,
you must learn to read the whole
we all need to
defend, preserve. I don't believe it, they did not want you to get this information. So here it is coming
at you. low tech style.
Welcome back hackers on planet 2020 is right here. This is the final talk of this day, which is day seven of hackers on planet Earth. Can you believe that seven days? It's amazing. And it's really an exciting one. We have such variety of topics here at hackers on planet Earth. This is one that's near and dear to our hearts for two reasons. Number one is about gaming is an intro to game hacking on the NES the Nintendo Entertainment System. Number two is about hardware because we're going to feature the Motorola 6502 processor. Take a deep dive into that. Our speakers tonight are lead hacks and stack fault. Let's hear what they have to say.
Hello, and welcome to the intro to game hacking on the NES. My name is leet hacks. I'm a computational scientist, computer science professor and a computer security enthusiast.
Hello, everyone. Welcome to hooked 2020. Thank you all for coming out. I'm stack full and I will be giving you the second portion to the intro to game hacking on the NES.
So I'm going to be covering the first section Which is the introduction to the 6502 instruction set, how the Game Genie works and some tips on right break pointing and editing instructions in the wrong. So here we go the introduction to the 6502 instruction set. The Nintendo NAS utilizes the Motorola 6502 processor, and the 6502 uses one byte opcodes. We're going to learn a little bit about those as well as a 16 bit address space which is based on memory pages that are 256 bytes each. There are also 56 supported instructions and six registers, three of which x y and a registers are utilized heavily by the application programmers. So I invite you to follow along using the mass work 6502 instruction reference. You're going to see that pop up a couple times throughout the presentation. Set a find that all you need to do is Google mass work 6502. And you'll see the instructions set up.
What do you want from me? Well, the numbers before we've ever wanted to
get these fucking numbers that match
what they've learned.
So that's a little call back to you Call of Duty Black Ops there. And the numbers that I'm referring to here are the actual op codes. So each assembly instruction for the 6502 utilizes an opcode or an operation code. And that code is one byte in length. You can see here on the table, there are some examples and we're going to we're going to dive into that a little bit more. So on the left hand side, I mentioned that there are 56 instructions that the 65 To respond to as well as different addressing modes that can be utilized by some of those operations. So there's different different addressing modes depending on the operations that you want to do. And some makes sense for certain opcodes some don't. But the basic gist of it is you have different instructions and different addressing modes to affect memory. So looking a little closer at the table here, the table tells you both the opcode and the addressing mode of instruction. Now granted, you could look this stuff up for each one, but the table gives you a quick reference guide to take a look at the instructions and have a good idea of what sort of addressing mode each one of those instructions utilizes. So just a quick mode on the or a quick word on the addressing modes. The idea behind it is addressing mode is it tells the processor how to interact with memory. So there are different addressing modes. And we're not going to get into the specifics of that there's a lot of good information out there online. If you want to just google 6502 addressing modes, you can find out some great stuff about that.
Okay, so if you happen to bring up that mass work
instruction set that I was talking about, find Appendix A little ways down the page shows the details for each of the instructions, including how many bytes total that instruction is, and what the opcodes so so if, if you're here, consider the way that the ROM is laid out in memory, right. Each instruction is one byte in length, and then may have follow on bytes that indicate what happens with that given instruction. So in the case, at the ADC instruction add memory to the accumulator with a carry. We can see here that there are different addressing modes for the ADC instruction. Some of those include the immediate addressing mode, the zero page addressing mode, and then absolute and indirect address sequence. So with immediate, what happens is you specify the one byte opcode. So you would see six nine in memory. And then you can see that this is a two byte instruction. So, the first byte is the opcode. And then the second byte would actually be the number that you want to add to the accumulate. So, for example, if you had the number one zero in hex, you would have 6910 laid out in in memory and that one zero would be added to whatever is already stored in the accumulator a. Similarly, if you have a zero page instance Option six, five, this is also two bytes in length. And the the follow on byte there tells you where in memory on the zero page, you can find the value to add to the accumulator. So using my example again, if we had 6510, what we would do is we would go to memory address one zero and find whatever value is stored there and then add that to the accumulator A. So those are a couple examples. But the idea is each opcode is one byte. And then there may be trailing bytes that also sort of either have an immediate value or refer to a value that's in memory. So here's another instruction This is the knob instruction, and the knob instruction is used to tell the CPU not to execute anything during those cycles. This becomes an important instruction for us. Game hacking if you will, because a lot of times you want to override the functionality of certain commands and effectively patch them out. So one, one easy way to do that is to patch in knops over existing commands.
So let's talk a little bit about the Game Genie.
With the Game Genie, the device temporarily modifies the game data, allowing the player to cheat, manipulate various aspects of the game, and sometimes access unused assets or functions. So let's look at how this thing works. So it's an intermediate device and it's shoved between the game cartridge and the game console. So effectively, you have the cartridge plugged into the intermediate device and then the intermediate device plugged into the console. What happens is the intermediate device can intercept certain instructions from the cartridge and effectively overwrite those instructions with customized instructions. There's a little flowchart here on the screen and we're not going to get too heavy into the details. But the basic gist of it is, if the console is requesting memory that exists on the cartridge, and that cartridge, memory location has been specified in the Game Genie for replacement, The Game Genie will replace that opcode and trailing bytes with whatever whatever has been specified in the Game Genie codes. Right, so we're going to talk a little bit about that. But the idea is when enabled, the intermediate device can block the game cartridge from returning certain instructions and instead, return patched instructions. Okay, so let's take a look at some instructions here and see that we have some instructions here and see increments 1200 LDA 1200, this is loaded into the accumulator, compare against three find out if this is the third lap branch if not equal to, and this is telling you where to branch to, otherwise it'll jump to the race has been completed. So the idea here is you may want to patch out this be any and jump directly to where the race has been completed. The way this lays out in memory, this is going to occur sequentially. So you'll increment 1200 LDA 1200, compare three, and then you could potentially patch in two knobs here because you have 2006 2007 and then you would go to 2008. So if you were to patch in two knobs here, what would happen is you would Immediately finish the race regardless of what the comparison returned. Okay, so that's one of the things that we're going to look at today is how to patch out certain functionality in the game. Another thing we're going to look at is the specifics with the Game Genie codes. I figured this might be worthwhile to take a look at right so the idea here is a Game Genie code is essentially a word, right? And it's a word that consists of characters, but those characters Mac, map back to hexadecimal values. Okay, so the table on the left hand side over here shows you what the characters correspond to in terms of their hexadecimal values. So for example, an A is represented by hex value zero, a P is represented by hex value one and so on and so forth until you get to And represented by hex value f. Okay, so for the code gossip, write that code gossip is actually encoding both a 15 bit address as well as an eight bit data byte. Okay? So what happens here is this code both encapsulates the location of the patch, as well as the value to be patched out. And there is a, an equation that we're going to look at to figure out what part of this corresponds to the address what what part of this corresponds to the actual data component. So first things first, let's break this string gossip into its components. So we're going to look at n zero through n five and map each one of these characters to their hexadecimal equivalents. Okay, so the G we look at the table here represents x value for BO, value nine, the S value D, the I value five and the p value one. Okay, great. So now that we know that we can actually look at the equation to figure out what address this corresponds to. So what happens here is the address is equal to x 8000 plus this
expression here. So let me just walk you through this. If you've never seen Boolean algebra or bits shifts or anything, this might look confusing, but it's actually quite simple. So in this case, here, we're going to evaluate this expression from into out just like you would in any mathematical expression. So what we're going to do here is we're going to take the value of n three in and that with the number seven, so n three and seven. You can do this on a calculator. Obviously, you don't have to do it by hand. So n three and seven, and then these two Less than less than signs are the left a bit shift operator. So n three and seven produces a result, and then we left shift that 12. Okay, so that result would be 101 and it gets left shift. Well, this green one over here corresponds to the 8000 in hats, right? So we're just going to build this expression, piece by piece here. Okay, and because all of these are ordered, you can see these pipes here represent the or character, we're just going to add these bit strings together and let the ones fall through. Okay, so in three and seven, left, shift 12 or and five and seven, left, shift eight, or, and four, and eight, left, shift eight, right, and we go down the table here and we fill these in as we've we've solved them, and we add them all up. So in the end here, you can see there's no left shifts on these labs. To in the expression and you wind up with 101 and then 1000 respectively. Anyways, you animal up and you get this extremely long bitstream here and all that boils down if you were to dump this into a calculator in binary and convert it to hex, you would get hex address D one DVD. Okay, so this is where on the cartridge the address on the cartridge that you would like to perform your patch. Okay, so that's the 15 bit address. Last the 8000 gives you a 16 bit address where this one is always constant. Okay, so we talked about we're on the cartridge we're going to, we're going to create our patch. Now what we need to do is actually figure out what value is going to now be patched in there. So in the case of gossip here that data byte is, is found by doing n one in seven, left shift four, four and zero and eight. left shift, or, or and zero and seven, or and five and eight, right. So we figure all that out, we add them all up, and we find that it comes out to hex value 14. So what's going to happen now is, whenever the CPU reads from address D, one D, the game chain will intercept that read request and return the byte 14 x 14, in place of whatever byte was stored in that location on the cartridge. So imagine that by it used to be F, F. Well, now when a read request comes in, it's going to be one four. Okay? So you can do this to patch data bytes, or you can do this to patch instructions really, the DNS doesn't care either way. Okay, so now that we've seen that, what we're going to do is take a look at how you would go about creating your own Game Genie code. This is really the inroads into hacking your own any NES games, right. So I really break this down into two phases. The first phase, uses bizhawk. It's an emulator. And the second face uses f Cox. It's also an emulator. It's up to you which tools you want to use. There's a bunch of good tools out there. You don't necessarily have to do it like this. It's just one way of doing right. So in phase one here, what we're going to do is identify a game, launch the game with bizhawk. identifying an interesting characteristic, identify a memory location where that interest interesting characteristic is stored. And then we're going to freeze and poke memory to determine if we have found the desired effect
in memory. So phase two once we verified the address that we're interested in, we can then add a right breakpoint for that memory address. And we can use that breakpoint to determine an address of interest. The game cart itself. Okay, so we'll use the debugger to inspect that instruction and determine its opcode and corresponding data bytes. And then we can use the cheap window to patch the codes with knob instructions, you can obviously patch with anything you want. But the knob instruction works pretty well in a lot of cases. And then finally, you're just going to activate your cheat check the debugger to ensure that the proper instructions have been replaced, and that no undefined behavior exists immediately following your patch. And once satisfied, you're just going to record your cheat codes for use later. So this is going to allow you to create your own Game Genie codes, which is is kind of cool. Oh, okay. How do we do this? So the first thing you want to do is launch a game right? and identify an interesting characteristic, right? So what is it that you care to hack? Right, how many lives you have left, how many moves you have left, your current power level, the amount of time you have Left, there's a bunch of different things that you could potentially hack. So we're just looking here at the the status bar in a game. And you can see these different attributes are represented here, the total score, how many lives you have left, your speed and your weapon, right? So let's say for example, we want it to hack how many lives we have left so that we essentially have infinite lots, right? So this is in the bizhawk. emulator. And I'm just using the memory search feature in that in that, right, so we identify a memory location where interesting characteristic is stored. So to do that, we play the game, right? And when we lose a life in the game, we can see that this interface here on the status is updated. But correspondingly, the memory is also updated. Right? So what we're doing here is we're looking at change counts, and we're seeing that okay, in the time since we died, this value In memory has only changed one time. And it used to be its previous value used to be three. And now it's two. Now in this particular game, this is really easy. They did it, they did, they did a solid here by keeping, you know, three, three and two, two. And it's you know exactly what you see on the interfaces, what you see in memory, that's not always going to be the case, right? Some games are much more tricky about how they lay things out and others, but in this case, we've identified memory address 0034. And we can see that, you know, in the time since we died, the value has gone from three to two. So we're gonna just kind of stick a pin in that and say, Okay, this is probably an area of interest. We may also identify other addresses that have similar sort of look and feel to it. And we may also want to potentially identify those and keep those on the back burner. So what we want to do here now is we want to freeze this area. In memory, right, so what we're going to do is freeze and or poke memory to determine if that has the desired effect. So in this example here, I can freeze memory address 34. And I can keep that value constant at three. So in other words, I can take a death in the game. And because memory address 34 is frozen, what happens is that value stays at three. So no changes to that value occur while that memory address is frozen. Okay, so that now means that the behavior has been verified in the game. So once we've verified that address, we can now move on to the second component, right? So it's important to understand that the NES itself has ram right memory, and these values as you play the game are stored in RAM, so that's great. Um, however, the Game Genie can't access the ram on the counter. So right, what it can do is it can intercept instructions on the game cartridge, and it can replace those instructions. Right? So we're not quite there, right, we've identified where in RAM the value that we're interested in is, but we haven't actually patched this on the game car yet. That's going to be phase two, we now know wearing ram the value of interest is. So what we're going to do is move into phase two. Once an address and relevant data values have been determined, we can now move on to the right brake pointing aspect.
Okay, so in this case here, the address from phase 10034. We're going to launch the game with F Cox open the debugger up and we're going to add a right breakpoint for the memory address. So that's as simple as just clicking the little Add button there. And then you type in 00 34 and you check off the box for right breakpoint. What this means is that the debugger is going to pause whenever memory address 34 is being written to. So what this is going to allow us to do is find out when the cartridge has an instruction that writes to that memory address. Okay? In this situation here, we're going to use the debugger to inspect the instruction and determine its opcode and relevant data bytes. So we run the application, activate the breakpoint and take a death right. So when we take a death, this address c 345. On the game cartridge is jumped to, we can see that it has an opcode of the six and a corresponding data byte of 34. So if we take a look at Appendix A, that instruction set, right we can see that Dec is decrement memory by one which makes sense if you take a death you're going to lose one life and we can also see here that This is a zero page instruction, meaning that we are going to go to memory address 34 and decrement. That value. And that's actually what we sort of saw happening in RAM before when we were looking at this through bizhawk. So now what we've done is we've identified where on the cartridge, the instruction is that decrements that address. Okay, so the next step here is to perform a patch. And what we're going to do is we're going to patch with knobs that behavior. So we're going to go to address c 345. And we're going to patch opcode D six with EA, right EA is the opcode for the knot. So what we're going to do is we're going to go to C 345. We're going to look for D six and we're going to patch that out with EA. Okay, but because knock is one byte, okay, and the decrement operation was actually two bytes, you need to be extra careful about that and also patch out byte c 346. Now, c 346 isn't shown here, because that is the 34 that corresponds with the memory address that we're interested in. So what we're going to do is go to C 346, find value 34. And now patch that out with EA. But what happens here is we wind up patching out these two bytes in memory with these nano instructions. Once we do that, we can now get our Game Genie codes and activate them. And your patch will temporarily replace the code read from the game cartridge. So in this case, we've scored infinite lives and we did it ourselves. So that's really awesome.
Okay, so that concludes my portion
of the presentation. You're now going to be joined by stocks He's going to do a deep dive on the picture processing you hope you enjoyed and have a great night.
So the first thing that you're going to notice about the PPU memory layout or the picture processing unit memory layout is that the addressing space is very heavily organized in where certain data is loaded, and how the data is used. There's also some strange two very strange things about the GPU that we'll be going a little bit more into detail about certain parts of the memory are mirrored, the PPU memory layout is broken up into four tables. Essentially, there are three but you'll see why I say four in just a second. So it's the pattern table, it would be the name table, and this is where the three or four tables kind of come in. So the name table is made up of the tile map and the attribute table. And then the fourth one would be the palace, but time permitted, we may not be able to get into palette. The general layout of the memory starts with the pattern tables. First, there's the background, the background pattern table. And then there's the sprite pattern table. And then there's the name table. And the name table, as I mentioned before, is composed of the tile map and the attribute table, then there's potentially up to three more named tables depending on the NAS cart that you're that you're looking at. Typically, there's two, but some NAS cards can support up to four, zero through three. And then of course, the pallets. The pattern tables are probably one of the more complex aspects of the PPU memory. And it contains not just the shape of the tile and pixels, but also the color. Now there's a little bit of terminology that we have to get, we have to kind of go over in order to really explain this. So if you look at What a tiles a tile is nothing more than a square of eight pixels across by eight pixels down. Now, you basically paint with those tiles to create your background and your sprites. And every bite is an entire row. Now, obviously it one bit per pixel, and whether it's a one or zeros on or off. Now each tile has 16 bytes. So to the astute observer, you may be thinking to yourself, Well, how can there be 16 bytes if each byte is an entire row and it's eight by eight? Well, you're going to see that the there's actually sort of like partner bytes that are concocted together, the bit columns more specifically, or concatenate together, and the color index is based on that concatenation, and we'll go into much more in depth on that. The name table is made up of tile industry. Now that would be the tile map. So the tile indices are numbers that refer to the tile that is in that particular pattern table. And then there's also the attribute table. So when you look at the tile map, it's considerably easier than to deal with the pattern table. And each byte refers to an index to the tile index that is referenced or created in the pattern table. So the name table up to four can be supported zero through three as I mentioned before, and each byte is a tile index. The Tile map is 960 bytes long. And the attribute table is 64 bytes long, giving you 1024 bytes or one kilobyte So typically, you're looking at hearts to have two kilobytes of RAM so the attribute tables contain the pattern number. Now if the pattern table provides the color index into the palette number into the Actual pallet number itself is assigned by the attribute table. And it is always at the end of the name table. And like the tile map, there's one byte per entry. And the screen is broken up into four by four tile, I'll actually show you the bytes and how it's all broken down in just a little bit, but just know that each two bit tuple refers to a quadrant of tiles, and a byte of say, for example, e4 refers to the it goes from left to right top to bottom. I believe that might be the other way around. I always get them backwards. But so let's talk a little bit more about the attribute table so the background sprite attributes are handled differently. And so the background sprites are their little bit more of a pain to deal with than regular sprites. attribute assignment byte is broken up into two bit chunks. And a chunk is a tile set of the block in later when I show you the diagram that I've done, you'll see exactly what I mean by pile set versus a tile versus a block. And all that just just recognize that pallets are assigned to basically a block, which is two by two tile sets, which is four by four tiles.
So if you'll notice, I actually have the CPU memory map in tandem with GPU memory layout next to each other. And the reason why I did that is because when you look at the the memory location in something like sn, which is like one of my favorite emulators, ah, it's easy to get a little confused because you'll see address 0000 in both CPU and GPU memory layout, and you'll be thinking to yourself, well, Aren't they the same and the answer is no, not fact the PPU is on a completely different address, Boston's not read or write to the PPU memory directly. So and the same memory, when you look at the, that's just a sample on the side there, it's just a sample of like, what would be the memory layout, it's all going to depend on how, how the NES game was coded. Now the PPU memory layout, you'll see that that is actually pretty heavily organized in terms of what goes where. And this is just the visual aspect, you'll see you know, there's like a tile map and then the attribute table and then there's the palettes. But let's actually break down the data where the rubber meets the road and actually show you how the bikes are broken down. And looking over here we can see a sample the name of a name table, and over here where there's an arrow, you can see the four DS zero by 14 hex. Now how that breaks down is, Rudy. Interesting in the pattern table, but we'll talk about that. Literally just like a second or two, but you'll see, if you load up messen, and you load into the table viewer and you click on a tile, to see that it gives you all the information about the tile, you can see that it's tile index for D, just before d over here in the bytes. But you'll also see the tile address e one, four D zero. Now, that's significant, because when you look over at the car viewer, as well as the pattern table, you'll see how that particular tile is made up from the bite from the bits. So each row is a single byte. And there it's a tile is eight pixels across by eight pixels down. So you might be saying, Okay, well in a singular, if a single byte is an entire row, then why is there 16 bytes, that's where it actually gets a little strange. So the colors on each of the bytes I put there to show the course that there's a corresponding part So if you look at the zero a here, there's a corresponding zero a, a stride length, let's say like, beyond because you'd 16 bytes in divided path. Now the zero a breaks down in, so you can look at the half, or ANP, it doesn't really matter, I choose AMD, because if you look at the number of columns, I have it set to 16. But if you have something like eight, it might not be left and right at that point. So I'll go with AMD. So we'll look at left side as being a rights as being B. And now when you look at how that's broken down, you see byte a over here and you see byte B, and it's the binary values underneath that. Now, where it gets interesting is is when you look at how these values are concatenate, it takes the byte or the bit in that column, a byte a, and concats it with the bit from the from the corresponding column in the corresponding byte B. So if you look at 08, and zero a bit seven, Have a zero and b are a bit seven, B is zero, put them together, you get 00. So which is summation of zero, so that means the zeroeth color in that palette that will be in that block of where that tile will be painted on the background. And the same thing for the the first bit, or I should say, really the second day, you can look at a sub A and sub B one, one concat them together and you get three, you get three because the first bit column is one and then the second bit column is two and you add them together because they're both on you get three so that means that third brace that means that third color in that palette, and that's why you have two sets because you can catch the bits together to create not just the color, but when you look at whether the pixels on or off it also visit the shape whether it's on or whether pixel is whether it's a pixel there or not. So if you want to look at the tiles and how in screen the background is broken up in the nest like this. So we will you all know that a tile is eight pixels by eight pixels. Well, if you look at a tile set as two by two tiles that's 16 pixels across by 16 pixels down, a block would be four tiles across and four tiles down four by four. And that is the smallest space on the screen that a pallet can be assigned to for background on the NES. Now, sprites are different sprites are a single palette, but it's store the color from the palette is actually the color index that's into the palette is actually stored as part of this great data. So it's a lot easier dealing with sprites in the backgrounds, but this is how a background is actually drawn together, scrolling up with piles that are in the pile maps based on the index of it in the pattern table. And then the pattern table gives it not just the shape, but the color. So that should actually help explain a bit. And when you look at the, the, the blocks and the attributes, if you I think I actually have a sample, yes. So if you look, here, you can see to see 00. Now to see 00 starts the
table three, but just before that will be the attribute table for name table two. So this would be like what the named table two data would look like. It's basically five five a bunch of times and then FF and so forth and so on. And they refer to the, the palette, the actual palette number that's stored in the palette table down at the bottom of memory layout, and that's where you get like zero F and zero f corresponds to here. As is Zero color, and two, two corresponds to this color, so forth and so on. And so you can see how if this is color zero, color one, color two, color three. Well, that's what these are over here from the pattern table. So as you can see here on the name table sample, these bytes of 55 and FF and how they actually dictate the palette, is, as I said, before the the screen is broken up into blocks. And if one of these is a single tile, and there's two by two for tile set, and then you have four by four, four block, the way that works is if you look at this for D right here, that for D correlates over here, to being broken up into this binary value. So the way the binary values are applied to the coordinates is, again, it's in two bit tuples. So this one First one gets broken down into zero and one. And then the next one is 003, and then one. And that is what the palette number is for that tile. And then the pattern table tells you what color is inside that you're going to be using for that, that particular quadrant in that block. So let's go back over to this and you'll see, so, like that zero f 22. These are the pallets, so they're in four byte increments, because each pallet is four colors, and it's 01234 the palette, and then it just kind of repeats and it copied and mirrored. But so when you look at the the attribute table, these are the pallet numbers that is referring to this block this set or this set, or this or this, then the pattern table tells what color in that set. So if we look over at messin real quick We bring up the PPU viewer for one of my favorite games, Metroid. You can look at the name table viewer so if you wanted to get say, let's see, let's pick, let's pick a spot somewhere. Let's go with this one right here this section is top corner right there. And if you turn on car viewer but you turn on, I think it's going to be that one. And then you go into name paper table viewer. You can do highlight tile selected and ch and you can see where what sprite what tile you selected. So we were looking for that corner piece right there, which would be we don't want that we want this one. So this is going to be tile index 01. So pretty likely fat.
Let's try that again.
01 this one
Yeah, it is. Okay. So this is the palette that's being used. And then the pattern table tells you what color. So as I mentioned about the breakdown of the screen, if you want to look at it like, if you want to get a better visual, you can turn on the tile grid. Now, as I mentioned, each one is eight pixels by eight pixels. You can see how each tile is in here. But then if you turn on the attribute grid, you'll see actually where the palettes are assigned to in those quadrants. So if you look at let's see if I can find one here, two, three CC. Okay, so it looks like we're on the edge of one. Yeah. So if you look at where the mouse cursor is next to the selected tile, you'll see that the attribute table, the attribute, address right over there, is two three CC. Now if you follow the cursor over you'll see that it continues to be two three cc until you have reached four tiles over or two tile sets. And it's also two three cc two down, because or two tile sets, then or four down or two tile sets. So then, if you look in you go down, you'll see that the attribute address changes. Now the way that works is, as I mentioned in the, in the spreadsheet here, I did, you can see that these are the palettes that are assigned to those quadrants. And as the bytes change, and they get filtered down to the, to the bits, you can see the palette assignments for each of those quadrants. And that's basically how the colors of the GPU and the sprites are worked. So you should be able to with that knowledge, do some sprite swaps and color swaps and play around with the graphics a bit. So I think that concludes my, my portion of the intro to NES game hacking. Thank you all for coming and will be available for questions.
This is fascinating
stuff. As I said at the opening this is this is what hope is made for right this this is arcane knowledge. You spend hours and hours digging deeper and deeper trying to understand what's going on. And that's what a lot of us do. And the hope concept is you show up here to share it. So thanks very much to Lee tax and sack fault for sharing this. I think I want to just give me give me a little bit of the basic background. Maybe you could tell me a little bit more about your software and if there's a link to the software that you can share with the with the hacker community. Yes. So
in my in my efforts to understand the CPU, memory layout, and how it all works on a hardware level, as well as programming for that hardware. I wrote ns wrong. from scratch, using ns ASM, which is a free available tool, it's written in assembly, I use a rad assembler for my ID. None of it is actually up on the GitHub yet, but I will be publishing it to my GitHub. I will be publishing a project file for rad assembler. So you have the ability to create NSF ASM project files for it. I will also be publishing a lot of the game hack addresses that I found just trying to mess around with Castlevania and stuff like that. As well as I think I might even put up my Vizio slides. So you'll have the full diagram of that. There might be some other things in there too, like so Louis scripts that I wrote for the emulators and stuff, but yeah, well, something
look forward to it. I don't know if you mentioned it, or maybe I missed it in your presentation. Did you give your GitHub? No,
that's just github.com slash Stockholm, Stockholm. Okay, so
basically the same
as your username. Someone today in the chat, whether this applies to the new mini Nester is that actually I told him different beast.
gonna, as far as I know, the the NES Mini the classic is based on the, it's using an ARM processor, and it's running on Linux. So as far as whether it would apply, it would probably apply to the emulation system that's running on the processor, but not the processor itself. Because when you're thinking when you think about it, you're dealing with like a Rico device developed
MLS to Rico, you know, to Motorola,
you're dealing with a different type of
processor than he or multistep was so
somewhat relevant. I guess if someone else had asked maybe a little more recently, we've had these Nintendo source code leaks and is that is that interested? You is have you learned anything from it? Actually hadn't heard about that. That sounds kind of fascinating, though.
Have you heard about that?
Yeah, of course Malmo, Luigi Israel and America 60 Apparently so.
Yeah, I heard about it. I think I think it is fascinating. I've been watching a lot of the YouTube videos about it and stuff like that. One of the things I will say regarding the little presentation about the Game Genie and all that kind of stuff, I was talking about using bizhawk to sort of identify memory addresses and how you can hold a memory address constant. And a lot of the modern day emulators if you're doing this stuff in emulation, you can kind of stop there, you don't need to go the route of right rake pointing and doing all the additional steps that I was doing. But the cool part is if you do actually take it to phase two, that'll work on any of the original hardware. If you happen to have a real Nintendo system and a Game Genie lying around, you can actually implement those hacks on the original hardware. So that's the cool part about that is like yeah, you can stop it phase one with modern emulation technology and be good to go. And that's super easy to do. But you can actually We go full bore into phase two, and then do that on real hardware, which is the cool part of you, is it fair to say that you've looked across the whole entire library of eligible NES games? Did you really do a pretty exhaustive, you know, set? Definitely not.
Now, there's too many of them to just show some of them because someone was asking in the chat, they were wondering what was sort of the most impressive from sort of a, you know, maybe it's a code efficiency or memory use, you know, all these tricks that you have to do to really get the most out of this relatively small system. So one
of the things that I noticed, I was trying to break apart the randomization routines in Who Framed Roger Rabbit. And I will just say that, that game, in my personal opinion, maybe some, I'm sure there's people that disagree, but in my opinion, that game is a mess. I mean, when you look at how much memory is trampled, and just rewritten and read and rewritten, it's like it's all over the place. So just trying to figure out and break down how the randomization works in that game. It's just horrendous. Um, that said, the interesting thing I did find about things like Castlevania, which I would eventually I would say that a lot of Game Studios probably developed many of their games a similar way. And if you take something like Castlevania, or lifeforce or brattiness, they all similar have the same similar style, a status bar. And when you look at the status bar, one of the things that interesting things that I found was it's basically painted as a background. But their the way they wrote it was they did offsets into where the areas are to update for the background. So they can create basically fields to update based on just the offset of that they were specifying for that label.
so it sounds
when you started talking about Roger Rabbit, what it sounds like, it sounds a counterexample, so maybe not a great way of doing things. That got me thinking of another question. I mean, your bio mentions being a computer science professor. And I was wondering whether you teach things related to game hacking or game hacking you think is a good topic for computer science students to learn? Yeah, so
absolutely I teach. I teach an upper level CS course in computer organization, and we introduce assembly in that course. And the way that I do that is by teaching basically this lecture as well as some others as well. So, I think it's super valuable because the kids get interested in, right. I mean, that's the whole idea is that, you know, you can kind of bind this to something that they're naturally interested in. And from there, you see a lot of results, you know, the kids get interested in it, they actually, they have something tangible to work with, and they can see the results. So you know, there's a point to them learning assembly language.
Well, I think I speak for all computer science students who wish that they were learning game hacking alongside a template language, rather than just assembler language. So do you want to we're just at the end of our time here. Did you want to share a screenshot of some of your software that might be worth just spending our last half minute or a minute on? Yeah, sure. Can you just a second? Okay.
here, you guys can see it right? Yep.
Okay, so over here, you'll see the RAD assembler
that I'm using the IDE, and I broke it down to the different libraries and stuff. But over here, you'll see. You'll see the different emulators that I have running. I have messin, I have bizhawk running on now when I was trying to debug the pallet loading for the NES ROM that I wrote. I had to write some scripts in bizhawk, just to kind of make sure that my pallets were loading where they were. And one of the things I was finding was that sir, a lot of the emulators, despite being called emulators don't actually seem to emulate the hardware the way they're supposed to. So if you look at like him, This is the palette data. Now you can see the fights here. But if you switched over to say something like NES Hawk, and you do, reboot core, that's actually the CPU memory there.
either way, either way you look at it, these two right here are literally the same ROM, but over in bizhawk it's not actually shifting the pallets yet over here it is. And the way I did the pallets was just to kind of simulate sort of like a sunset and there's only so many colors you can choose from so and so many colors in the palette, so it was like I did the best I could, but you can see like, I have the input system working, you know, moves around, you can see the the up down arrows of sprites, showing that, you know, those are the keys that you're hitting on, you know, Up Up, Down Down code and all that and be a select Start and all that. And I'll be putting this up on the GitHub so people will be able to look at it and play around with it and make some modifications. Fantastic. Yeah,
I would go through the library,
but there's just not enough time. Yeah, like we're actually out
of time. You All kinds of stuff for Well, the thing to do is just just end with the with a GitHub link again so that people can follow up and, and possibly through GitHub. It sounds like they should be able to get in touch as well. Yeah, yeah. Yeah, we'll just be github.com
slash Sta. KFA Lt. cr Tango alpha kilo Foxtrot, alpha. Lima. Lima, Tango. Thank you so much for
bringing us this this exciting demo. I think we had, we had a lot of good engagement in the in the matrix chat as well. People are wondering a lot of things about what you can learn from this code and what you can discover, you know about about, especially about how, essentially small memory footprint coding can, you know, be relevant to the modern world or have far greater resources? Yeah, I think that that discussion can continue. Thanks. Again. This has been retox and stack fault, telling us all about hacking the NDS. Thanks, Greg.
Thank you, gentlemen.
We are done. This is the end of hackers on planet Earth Day seven. What we've passed we've surpassed all the records at this point, right? We're, we're, we're just cruising towards day nine. Join us tomorrow. We got a lot more excitement. Upcoming and tonight for those of you that are watching this live in about seven or eight minutes, we're going to have a fantastic DJ set and visuals so every reason to stay up late here and hackers on planet earth 2020 Thank you gentlemen. Good night. Thank you. Greetings.