 All right. This is not a cool slide. So yeah, my name is Christian. I'm going to be talking about the Nintendo, so I'm from Canada, from Montreal. Thank you. Hello, Livestream. And I am a Ruby developer, so I build web apps full-time, but in my spare time I tend to hack on random stuff because my brain does that. And for the past three months, the random thing I was toying around with is the Nintendo. It's not because I was playing in Nintendo, it's because I want to understand how it worked. So it all kind of started, I guess I was sleeping, and for some reason I thought about the Nintendo and I started asking myself how it worked. And at first I just wanted to understand how all the little parts work together to display pixels on the screen. But then I went down a rabbit hole and I eventually want to display my own pixels on the screen. So here's sort of like the three-month journey that I'll take you on. So to answer my first question, this is what the inside of Super Mario Brothers looks like. They're called ROM boards, and they're called ROM boards because it's basically just two ROM chips, and a ROM chip is read-only memory. So the chip on the right is called the program ROM, and this basically has like machine code, it's actually like the code for Mario. And on the left side you have the character ROM. So character ROM is just graphics for the game. So the first thing I did was I wrote a little program to extract the graphics from a ROM file. And it's actually a really fun exercise. If you want to do it, it's just a very simple binary format, and it's really well documented. It's really fun. Anyway, but not all the ROM boards look like this. So these are a bunch of different ROM boards. So Nintendo, when they built the original Nintendo, they knew that technology would get better over time. So they made it so that the cartridges could take advantage of this advancement. So I don't know if you're not familiar with the Nintendo. The Nintendo didn't have any storage. So the way you would play a hard game is you'd either have to leave your Nintendo on overnight for many days, or the game would provide you a way to input a password. Yeah, a password. A very long password for some games. But then Zelda came along, and Zelda introduced... Zelda's cartridge had a battery in it, and the battery was powering RAM. Just kind of mind blowing to me. And this battery apparently lasts six years. So if you still have Zelda today, well apparently you could just switch out the battery. Really cool stuff. Then I started going down the rabbit hole. So this is my first program. You might look at this and be like, wait, this is not a program, it's a blank screen. I'm like, no, it's not a blank screen, it's a black screen. It actually... I am proud of that black screen. Because that black screen took me a long time. I'm a Ruby developer. I work with high-level languages. I'm a self-taught developer. I didn't go to university. I'd never done assembly before. And yeah, it took me a while to figure out how to display a black screen. Had to read about the NES, which is... So the NES was released in 1985. So just finding information about that was kind of tricky. And then I had to find tools to write assembly for the NES. That was kind of tricky too. Anyway, fun times. So I was learning this with a friend, and he was kind of doing his own thing on his side. I was doing my own thing. I was like, oh geez, this is the wrong slide, it doesn't matter. I was talking to my friend and this, okay, spoiler alert, this was the next milestone. But anyway, I have a ball that's on the screen, and I'm like, oh my god, it works. And he's like, no way, oh my god. And I'm like, yeah, oh my god. And then I was like, wait a minute, is it normal that we're getting excited about displaying a ball? Yeah, totally. So the NES is powered by the 6502 CPU, which is the same thing that powers the Apple II and other retro consoles. So it turns out you can't really use high-level languages for this CPU, because it's two megahertz. It'd be far too slow. So instead, you've got to speak its language. You've got to speak machine code to it. I don't know about you, but I don't want to write hex code all day. I'm used to having a high-level language. So this is where the CC65 tool chain comes into play. So this is basically an assembler and a linker. And a linker will give you NES ROM files that you can then run on emulators. And this allows you to write code. I say code because, well, I mean, it's still super low-level. It's not the code you'd expect for, it's not high-level language or anything. So you can read and write the memory. You can add and subtract. And you could compare numbers. And then you could jump around your code based on those comparisons. So it's very, very limited. And what the CPU will do is it'll essentially just go instruction by instruction. It'll execute your code. And that's what you have to build a game. So yeah, spoiler alert. I showed you this earlier. But this was my second milestone. I managed to display a ball. And it was awesome. I was so happy. So what I had to learn to display this ball is what's called the picture processing unit. And this is basically the graphics card for Nintendo. It's capable of displaying a 256 by 240 pixel image, of which you lose around 5% of the image because of the overscan of the old CRT screens. You can't use RGB. I learned that. So you're actually limited to a 54-color palette. And you can only use 25 colors at a time. So super limited. The NES wasn't powerful enough to let you render one pixel at a time. So instead, the screen is divided into 8 by 8 tiles. So you can actually control every tile. You have two layers. You have a background layer and a sprite layer. And sprites are just 8 by 8 objects with an x, y coordinates. And it turns out to build games, all you have to do is write to the right memory address. Just kind of cool. You don't have function calls. You just write to the right spot. And that's how you display stuff. So milestone number three, sorry. The ball moves and it bounces off edges. I was stoked. So here's my conversation with my friend. I'm like, send him the video. And I wait. He's like, oh, my god. Wait, is that real? And I was like, yeah, that's real. He's like, no way. I'm like, yeah, it's real. So the way what I had to do to get this working is I needed a way of knowing when time passes. So it turns out the NES renders at 60 frames per second. And between each frame, you have what's called a vertical blank. And you have a small period of time where you can prepare the graphics for the next frame. And this will trigger an interrupt. So an interrupt is just a way for something to tell the CPU, hey, stop and go here. So if I have this infinite loop that's just incrementing numbers all the time, and the NMI interrupt triggers, well, it'll bring the program counter to the interrupt. And then I can do my stuff. And then I can return back to wherever I was before the interrupt. So milestone four. Yes, I learned how to read controller inputs. So it turns out controller inputs are just a special memory address that you can read from, which is pretty awesome. And it turns out the Nintendo only had eight possible buttons, which fits really well in a byte. So it turns out when you press a button, it just toggles a bit. And if you press two buttons, well, it toggles both bits. And so what you can do in assembly is you could read the right memory location and then you could do bitwise operators to see if a button's pressed or not. Pretty cool. Milestone number five. I'm playing against a robot. It's a very unfair robot because all the AI does is set the Y position of the paddle to the Y of the ball, so I can never win. But at least I can test my program and make sure, you know, the bounciness works and all that stuff. Tooling. Turns out there's a popular emulator called F-C-U-X. I don't know what that means, but it turns out the Windows version of it has a debugger. I don't have Windows. I run on Mac, so I have to use Wine to run this version of the emulator. And it gives you a really cool debugger. You can set breakpoints. You can watch the memory. So if you see, I don't know if it's clear, but you can see the memory address is changing. That's because the ball is moving around, the paddles are moving. You can see all this really helpful when you're working on assembly code, because you can't do console log or stuff like that, right? Turns out this emulator has support for Lua. So Lua is a scripting language. And you can advance the frame. You can read and write to memory. So you can do cool stuff like you can overlay stuff on top of the UI to help you for debugging. But then I was like, wait, Lua, can't you do unit testing with Lua? Right? So yeah, turns out you can. So I wrote some unit tests to make sure my game works. And as I develop it, I can make sure I don't introduce any bugs. Yeah. Two tests. Yes. All right. So in terms of resources, there's this really great wiki called NES Dev that basically explains everything about the Nintendo. And I found learning assembly was really hard to grasp at first. And it turns out the Nintendo is really old, and there's a whole bunch of different emulators for it, and they're all open source. So I ended up finding a Go emulator. And whenever I had troubles understanding how the 6502 assembly worked, well, I just opened up the emulator code and figured it out, kind of read it. So next steps, well, I want to just improve the game, have a title screen. I eventually want to put it on an actual cartridge. I don't know how to do that yet, but I'll figure it out. I want to open source the game so that other people that want to learn assembly and 6502 can do it. And I'm going to be starting a YouTube channel and really going in depth into how I built this game, really taking the viewers' hands and going step by step on how to build a game like this. So my name is Christian. I hope you like the talk. That was it. Thanks.