 All right, I've started recording. Okay, so this is going to be about a similar in general. But as I explained to Julia, the reason that I feel that it probably better to start with an eight bit assembler and I chose 6502 I actually do know to eight bit assemblers which is the 80 and 6502. But I chose 6502 because I find it a little bit easier to handle at the beginning. And I've also used it more probably because it has online resources to use stuff on so if I just want to code something for fun and go to a website and start doing it with Z80 I actually have to start going back to programming the game boy color and that takes forever because I have to set up an environment and everything. But I think it's important to learn a similar it'll teach you more about how computers work. And we'll just go to the next slide. Oh, and I'm Donnie Baker I forgot to mention that I was told to mention that I, I like programming things for fun. Can anyone hear me right now. I just want to make sure. Yeah, we can. Okay. So I think programming things for fun and you know Sunday I hope to make a million dollars so that's all you need to know about me and also, if you guys already are on the telegram, get to the telegram I'm about to get to that's where I just haven't actually, I saw the software I didn't actually get a chance to get to it and sign up yet. Okay, so there's the truth and lies about assembler. And these will help everyone I think at the beginning. But one truth is that you'll get a better understanding of hardware at the low level, and that will make you a better programmer. Another truth is an easy way to gain that knowledge is by learning an assembly language. And in the last lie is you will be more productive if you code everything in assembly language. There's a reason we have abstraction. There's a reason that we love abstraction. But there are certain things that I see over and over again as a programmer where I'm like, I don't know if abstraction is always helping us so it sometimes helps to remember computers are dumb. They don't know the things we know they don't know how to, you know, multiply to 400 numbers without like having to think about it and things of that nature like we. We're better than them. They're faster but we're just better. Not everyone's going to agree with that. This is binary. You guys have probably seen binary before. If you don't do assembly you probably don't use it as much as I do. But maybe you do I don't know what you guys do with your time. You know binary is a base two system so it's places unlike our places go up. One, two, four, eight, 1632, 64, 128, 256, 512, it'd be really difficult to deal with binary like that. We know that the first four digits can add up from the numbers zero to 15. So we separate them into two hex in a bite we separate them into two hexadecimal digits which we call for bits is called a nibble if you've never heard that before now you know it's a nibble we like to be cute and programming world if you if you haven't heard that before. Word by nibble, all those things they're really cool. Does everyone understand this or I just want to make sure that before I go on with this this is going to be kind of important because I'm going to use a lot of hexadecimal, and I'm going to use some binary probably not as much as I use the hexadecimal directly. Right, I do. You do that you don't understand it. Yeah. Okay. And so this is some 6502 a subword that simply is going to check if we have a greater than less than condition, we're going to return zero if we are less than and if we're greater than we're going to return the number one. What it does is compare which is at the very first instruction here is comparing to the memory ad the the number in the memory address 00. So, let me hit this button. What we would do is we would load a number into the accumulator, the number one in this case, we would store that in zero. And then we would load the accumulator with the number a, which is the equivalent of 10 in decimal. And then we would compare those and what a compare actually is is we'll go back to this but I just want to mention it briefly here is a comparison. We're subtracting but we're not actually keeping the result we're just seeing if we're actually going to carry. So if you were to subtract a bigger number from a lesser number a carry would occur, because a bigger number will result in a negative number but not really not in computer world. So we're going to talk about two components, which we won't get into just yet. So what we're doing to do after we do this comparison we're going to compare zero whatever numbers in zero to the accumulator which is a the register a. And in this case the register a is 10 and then the the number and zero is the number one because that's what we put into it at the very top of the code. And then if the carry is set will say that a is greater than one which would be true 10 is greater than one. And we would go ahead and branch if carry set to greater than which is that line. Oh, this is written wrong I forgot I fix this in some code earlier but I forgot to fix it in the PowerPoint, but greater than should be the lowercase G there. I'm going to probably write this code for real later so I can show you exactly what this means if anyone's getting confused at this point, they'll get too confused. The truth is is that I'm all I'm showing at this point is not mnemonics load accumulator with the number in hexadecimal zero one is the first line. So that's all you need to know is that you're loading what's a register. So computers have registers for anyone who's unaware of the situation as of yet. The 6502 computer has only three registers, it has more registers, it only has three user registers, and that's a x and y. It also has PC which is the program counter and flags register which we don't deal with directly as as programmer was a similar but we will use the results like the compare such a flag result called carry. It also can set a flag result called zero because if if you were to compare two like numbers like five and five, you would come up with zero and so you wouldn't have a carry occur because five minus five will produce zero and would not go into the next space and produce what's called a carry. But if you wanted to know whether or not a number was both greater than or zero, then you'd need to compare both the both the flag zero and the flag carry. And so that means that there'd be a branch equals here as well to do the same thing to say greater than equals. If two numbers are the same, they are they subtract to zero, but that also means that they're equal five minus five is zero but it's also there's the same number they're equal to each other. This isn't as complicated as like equality in like triple. What is it triple equals equals equals and equal equals and all that stuff. We're just simply talking about whether number is equal to another number. It doesn't matter where we put it in memory or any of that nonsense. It may matter later, but it doesn't matter. And then all we're doing is we're loading with the accumulator with the zero or one, depending on what our result was so that we can have that returned. What we're going to do next here is to stop here for a second and go out of the share and actually look at this code in the assembler, because I'm probably confusing people right now and I feel that but I'm trying not to. But we'll just put nine there. We don't actually need the greater because we don't look through this or anything so we don't actually need that, but we can put it here, just to have. We can look at the heck stuff of this after we're done just so you guys can see like what. So machine code is just the zeros and ones. This is of course just our convenient way of naming those zeros and ones so that we can kind of know what they mean. I'm sure this is it. We'll just use their for a moment but then we'll just look at this, and this is the heck stump of all those numbers. So you'll see the a nine, and then the zero one, but we have a zero one second so a nine is actually what is low day. So LDA is really just a nine, but no one memorizes all of these numbers to what codes they represent so you generally memorize the codes and, and forget that then that they actually have numbers underneath them. Five zero zero same thing we got stories 00 a nine oh nine we same thing we got load a oh nine. You'll notice that there is nothing here for greater if you. I don't think anyone's going to have any questions about that but if you're if that's confusing or anything. Greaters just telling me where I'm at it's not a thing that the computer cares about it's a thing I care about like I want to know greater. When we jump to greater than later we do actually do that with some stuff and that's going to involve to compliment and other things so we won't get into that just yet. But we're here with the 00 a nine oh nine C five zero zero, which is the compares zero zero, and then be 003, which means we're going to go three bites ahead this is actually fairly easy because we're don't go backwards. So three bites ahead to. So you have three bites ahead would be, we have the load a number 00 and the RTS so that would put us right here where the greater than is or really put us right here where the load a number 00 01 is lost that little pop up. So that's what the three means it just means go ahead three, but we can also go backwards and we go backwards that's going to involve the choose compliment and that's what I was talking about being complicated before, then we'll load with 01 and then we'll also return here. So we can choose either option we want. When we run this in a right here, we get the number one, which means it got down here to greater than. So nine is greater than one. If we did this in reverse and assembled and run is zero. So not one is not greater than nine. Is that making any sense so far. I mean, I know you guys know that one isn't greater than nine I mean the assembly is the assembly making any sense. Yeah, but I just have one question. Did you have to have to remember this command to be able to write it. It's just load and store. Yes, yes, you do. But to be honest, it's easier than you think. It is. There aren't so many, there aren't that many codes and we reuse codes in different ways like earlier I wrote some code here. So we can look at it. So if I want to load a from 00 some part in memory that means it's not a number a number would be this, but I don't want to know from a number I will learn from a part of memory so let's say I want to load from 600. And I want to load a from 600. And then that's all I want to do to be honest. Does anyone know what number that's going to be. Oh no you don't, because I didn't explain that this starts at 600 yet. This starts at 600 does anyone have any idea what that number is going to be. Not at all. It's going to be load a it's whatever load a represents. So low day is a, whoops, run it again. Reset, maybe have to erase it all do it again. Okay, there AD, and now if we do a hex dump here AD is the first part of the instruction it's, and we start off at 600. And this is where I should have probably shown you that we started something earlier. That would have given you the answer probably. So we're doing the instruction AD into a not for any reason we just want to do it for fun, but I don't have to do that I can load real numbers I could just go. This is an eight bit system and it's, it's more eight bit than some other systems because the Z80 is also a bit eight bit was originally defined by databases. But the Z80 had 16 bit. That part's nice it has 16 bit registers. And so you can do things like you can load it with a number that's 16 bits so you can do FFF and you can't do that on 6502, you can load FF. And if you want to load a bigger number if you want to jump to a bigger number. If you want to jump to a bigger number that you would carry in a register you probably you wouldn't carry it in a register you put in zero page which is an architecture thing that I'll have to explain but it's not the most important part at this point to be honest. Like most code you want to see something on the screen you want to get something going. Our comparison where we did greater than less than essentially just a moment ago. Is fun, but it doesn't show us anything and it doesn't it doesn't get anything started so what we'll discuss right now is this particular machine from 0200 to 05FF has that's where that's where your graphics are. That's 1000 that's three FF or 1024 bytes of video memory essentially. So if you wanted to write to the last pixel. You could load a number. It does 16 colors so no matter what you put in this first nibble if you put F E one it doesn't matter they don't read it. The only thing they read is the second number here that that second nibble. This is a flaw of the program in my opinion as it would be much cooler if I could just either write 256 colors or if I could at least like write two colors at once by going like that. That would be complicated and they wanted to keep it simple so they decided that you could only write 16 colors and it would just be the last. The last four bits are all that's looked at. So we load that and then we store a into memory 05FF. And that's going to be this last pixel right here. And so we can assemble and run it and there's a pixel right there if you can see it on the bottom corner right there. It's really tiny probably I can make it bigger. Still tiny though it's 32 by 32 display. This is what it felt like writing and I did write very briefly for the Dreamcast VM use. Me and a friend were writing a race car game for it wasn't very good. But we did write that because it was based off the same processor that they use in the Game Boy Advance. And I'm always amazed by that and I hope you are too that the Game Boy Advance ran on the same processor that they basically used for the VM use for the Dreamcast. Even though they only had a 32 by 32 black and white screen. That's crazy I had no idea about that. So if you want to write to the first pixel you write to 200. So if you want to write up here at the very first part 200. If you want to write right next to it you go 201. And so writing the memory. So far we've just been using a lot of low day story. We'll have compares and the loss of other. So he maybe has a good tutorial part on this. Nope, I don't like that. So there's another assembler just like this and the only reason I'm going to it right now is because in his help section. He has a cruel set of op codes so you can look at all the op codes. This is what you'd have to memorize these these things here. And most of them are the monics there. They mean something so this means add with Karen. This means and this means arithmetic shift left. This means brands carry clear. This means brands carry set. This is branch equal. This is an unused. No, no, I'm just kidding. It's bit, and you'll totally use it. Probably not. Even though he gives a cool little demo in here. Brands. I believe this is branch if minus, like, I don't really remember that one. Brands. Yeah, brands on minus. So that's branch on minus. I don't ever use that. Brands not equal. I'm guessing that's branch plus I also don't really use that break which is for debugging. It's, it's just a way to break in assembler because we wanted to debug back in the day to make sure it's overflow clear. This one's a little complicated just because it's not the oh and I just would prefer it be the oh, but I really hate. We'll get to it. Clear carry clear decimal flag because they have a decimal flag you could do binary coded decimal. No one does so you don't have to worry too much about it clear interrupts clear overflow. The compare operas operation compare X which lets you compare X to something and compare why which lets you do the same thing with why. Decrement decrement X decrement why exclusive or and that should be X or my opinion, but I'm just not a fickle person increment increment X increment why jump. So saving return. That may not be the actual name for the mnemonic but that's what it does it saves the return it pushes the return to the stack. And then it this so jump is your go to statement. This is your, like, essentially a function is jump to sub routine or jump saving return or whatever it is. We'll look it up in a minute it's jump, jump to sub routine is what they say. I mean, I use it all the time I don't like the name of it load a load X load y logical shipped right. No operation the best doc code and all of computer programming do nothing. And I use it all the time. Or a, which is just an order with the accumulator. I think they just wanted to keep them all, at least three characters so they just had to add that a in there, even though they didn't do that with other ones. Okay, post processor, post PC. It's the PC. It's it's where you're at so if you're if you're definitely live. So push. Where's that. They just skipped right by the way, I just missing. Oh there is post processor status. Okay, so those are the status flags those are the actual flags that is pushing. You can see that would be a 16 bit person it can't do that so I don't normally push the flags so I don't know if that would be useful to me at any point but it's not in general. Okay, pull plot processor flags rotate left rotate right, which return from interrupt return from sub routine subtractive carry set carry set decimal set interrupt store a store x store y transfer a to x transfer a to y transfer stack to x stack pointer to the stack in the 6502 is from 0100 to 01 f f, you can use it as regular memory, but if it interrupts like so if you push, whenever you're jumping somewhere if you don't know this already. So, will they numbers. Three. I'd have to think about this code for too long. It's going to take me too long. So, essentially, if I have something on the stack and I loaded it myself and square and excuse to do this all the time and programming in ES games. They used to use the stack as if it was regular memory and do really funky stuff with it, which made a lot of a code really bad written, but no one noticed for many, many years until emulators started coming around and the people are like, oh my God, look at what square makes did. How did this not break the entire program. They used to mess with the stack all the time in general just stay away from the stack don't don't mess with 0100 to 01 ff if you ever do have to code an NES game you know for for fun and profit. Stay away from that. It's not going to be a. It might be a thing you never know, but you're probably going to end up programming just a SNES or NES game look alike if you ever had to do it. It wouldn't have to actually rely on the old systems. I don't remember where we were, but this is stack pointer to x, x to a x to stack pointer wide a. So, for the most part, I know all these teams are transfer. So I just look at the next two letters and they go that's transfer a to x transfer a to y transfer stack to x. I don't know if you can see these right here, not all the seas I guess some of these are clears but I know these seas right here compares and so I don't actually have to memorize all of these but I'm really memorizing is just the ones that are unique. And all these branches are just they operate on some flag and then I need to know what the flags are. So I just look at this up here the decimal mode interrupt flag overflow flag program counter stack times wrap wrap around. And then you can also see the flags. I'm pretty sure you list them somewhere else that I seen in here before if he doesn't then any other 6502 tutorial tutorial will go over it. There it is. No, that's not it. This is what this affects so rotate left affects the. This is the. What's the. So there are so many instructions here and as we mentioned, you don't have to memorize or you just have to be familiar with the most common ones. So it'll be possible. If you can show us a little an example, like, you know, a scenario, how it works underneath, like by putting up all these instructions together and then it can achieve something. Yeah, so that's easy enough, so I can. So first load a with the number zero and this is more of a precaution than anything these particular systems do not assume anything is in Ram. And for the most part, that's a general assumption that a lot of the similar programs used to make. You should not assume that there's nothing in Ram because sometimes you could get corrupted Ram and you could actually have a situation where the system powered off but there was still a value set in the Ram when you started it back on. And so if you assume that it was going to be zero and ended up being something else, your program could either crash or something else could happen something weird could happen. And so you should, what I'm saying here is just I'm going to load it was zero but I don't think I need to because I'm pretty sure that the Ram is already loaded to zero, because these systems are not like a real Commodore 64 where they might still have something in that RAM position. But then I'm going to store that in 00 and then I'm going to load a number shift zero to and I'm going to store that into zero one. And then I can load a number shift FE. This is not number shift. So I don't want to number. So normally in zero page which is Ram from 00 to ff that that's just free Ram that you can use and the beauty of that Ram important importantly for the 6502. The zero page was all of the RAM from 00 to ff at 00 so the actual address would be 0000 so it's a 16 bit address. But what the guys who made the 6502 is they said, Well, we're just going to make some cool op codes that can just work directly on the zero page. So let's say with 00, and we're actually loading from this address without having to use a three bites because this would take three bites if we didn't do it that way if we had to do this. And you can do this by the way, you shouldn't. If you're in zero page you just use the two, the two, the two, the bite, essentially, instead of the two bite, but if you if you like, I'm not always in zero page if I wanted to get. I need to get something from the stack if I wanted to go and get something from the stack I would have to type this. This is a bigger off code, which is the same thing as a mnemonic op code just means operation code. And this is three bites long as opposed to two bites long and it also runs slower, not significantly slower it was one cycle slower than the other way. So if I do this, it's one cycle slower but these computers back in the day, especially the Commodore 64 the big 20 and the NES were very, very slow they were some of them were under a megahertz. And to imagine that today, it meant that you couldn't really do very much with them and this was these were computers that people were using in their homes the big 20. My mom would not buy me a big 20 when I was seven years old I remember it clearly, because all I would do on it was play video games she was sure of it, and it costs $300 which at that time was $800. So she was just like, it was it was $300, but it's the equivalent to $800 in today's money. So she was just like all it can do is play video games and she didn't see any purpose for it in her life. And so in either did I not for not for $300 $800 whatever you want to consider that price I was like, yeah I probably just end up playing video games on it I did program my first game on a big 20 when I was seven years old. And that's how I knew I was going to be a programmer but I did program again until I was about 17 years old so there's quite some time after that until I actually got on a computer program again. So I knew I did actually program something on a trash a TRS 80. Um, but I didn't have a disk drive so I couldn't save it so anytime I pray it was all basic and you program and basic. And I, I, but anyway, these systems costs a lot. They had no power no ram. But we want to. So here we have a zero page, but this is a special zero page so this is a random number generator. So you can use this address FE for random number generation. If you wanted to get a key, you could use this address to get a key from the keyboard. And so these two were added by the people who make these emulators essentially, so that you could easily do things like write a game or something in these little virtual systems, without having to write your own random number generator, which we won't go over right now but you can write your own random number generator. What happens if you try to write to those addresses. I mean, so I mean so something you can write to them just fine. But if you write to them and then try to read from them so like, let's, let's do that. Let's let's have fun. We'll load a with number D nine just some random number. And then we're going to story. D nine there is a constant. Or is that a number. Yeah, it's a constant it's it's something in it's going to be. It's going to be so when we assemble this in our hex dump that D nine is that number right there the D nine. Hold on. I was zoomed into your code. Okay, you got this other window. Yeah, yeah, I see. Yeah. And so that D nine is right there so it's in wrong, essentially. But it could have very well it's just been in memory because I can actually make all this run in memory if I wanted to like I said these these systems are not written to be real computers that made to be something that you can learn on. So now what will happen is we can we'll see this age change, but it won't be denied well it could be denied theoretically it could be anything. But it was easy six and that just means that even though we stored something to it which didn't affect it at all it did affect it at one point there was D nine in there in fact we might be able to check that on this one. Let's run it again. Okay, so going to D nine. So because we got to that never mind let's debug and then do that same thing. And that step. Let's see if we can do that. No. Oh the random generators just randomly generated numbers continue past. Let's assemble that again. And then we'll step. And now D nine is there. Everyone see that. But then if we as soon as we read from it the next line of code. It's 74. And now a is 74. So that's what happens, but it's, you could store things there temporarily as long as you never read from it that'd be fine, but what would be the point. You know what, I do kind of wonder, I haven't ever tried this. What would be a good test for that. I'm wondering whether or not I could store. So what are we were going to do, what I was showing before I distracted myself. Is this okay, low day. Number shift O two. Okay, the O two and zero zero those are important because as I talked about earlier from O two to five FF is where your video memory is. So we're loading that address now that address is loaded in. What is it big Indian or little Indian I can't remember Mike do you know when it's reversed. I don't remember the numbers that that's called something I don't remember what it's called off the top of my head but it's big Indian or little Indian in the IE and not not Indian but Indians. This is similar so we're going to put zero zero into zero and then zero two into one. And if we just assemble and look at that that'll be down here and run. And now we have this, but this is really what the what I'm doing this for is so that I can have an access to a 16 bit address. So we'll be able to access zero to zero zero. This is zero to zero zero right here. It is in reverse order, which looks weird to us, because we're human beings and not silly computers. Hey Donnie which of those is the more significant the zero zero. So, more significant so the zero two is the is the top part of a 16 bit address, and the bottom part of the 16 addresses zero zero. So your yeah so the address there is zero two zero zero so zero two is the more significant. Yeah, that means that this is little Indian, little Indian. Okay. Yeah. Because in a big Indian system, the more significant bites are stored at lower addresses, but this is the more significant by being stored at a higher address. Okay, this is still just storing a but this is obviously not going to be the same as if we store a here, or if we were to store a into a 16 bit address. There are different codes and they're going to have different binary representations in the system so instead of it being whatever it was I think it was AD or something like that earlier. It may not have been I that might have been something else that I was doing that might have been low day. Whatever it is it's not going to have the same bite representation for what this is but for us as human beings, we're going to see all of these a story because that's what they do they store into something. That's all we care about and they store the accumulator into something that's important that's what the a stands for the accumulator is the register that we're working with here, as well as the why register. So notice, I did not actually specify what the why register is, but if we look over here on this system right here is been staying at zero. Theoretically, I should not rely on that either. But again, I'm an assembler programmer and we're wild, we were red gloves. Nice. We do what we want to do. Yeah, just things me and Mike understand. But we're not going to store anything into why though I could I could just say right here, we could transfer a to y, and now a and y will be zero. That's guaranteed now because I've loaded a was zero and then I put a into why a doesn't get anything back from this so it stays as zero as well. So if I was to load a with for a so if we assemble this and run a will be, well, because a gets reloaded here, need to not reload there, and not load here. And this is how you comment code in this assembler. It's not how you code comment code in every assembler. We're on a six hour two for either the Commodore 64, the Vic 20, or any other system I recommend this assembler, which is beyond this is his GitHub page, but the actual page for is here. And this can be for SNES SMS GG, which was the systems game board, which was a custom processor but it's based off the Z80. The PC engine is a system that was based off of the 6502 called Huke 6820. The SNES was a better as a 16. Was it. It was a supposedly 16 bit 6502. It was the big daddy processor next to it on the Apple to me I think ran it as well not just the SNES. I don't want to revisit the whole, whether or not the SNES was a was a bit or 16 bit or or the seven TG tech tribographics PC engine were that I will but I don't want it. But if anyone wants to let me go back to the code. So, we're going to load this with zero zero. And this one with two, and then we have this. And now, if I didn't want to, let's say I'm not going to make these values quite like this I want this to instead be a random value so I could just load a from FE. And then I could and that, because I know that the amount of space that I can write to those from zero 200 to zero F to zero five FF. So I could just and that with the number three. If this doesn't make sense, let me go over this real quick. So if you have any number. A bit number in this case, let's do that number. And then you and something with three, which is this binary number, you're only going to get these two bits because the and only gives you so you know, you guys know the truth tables one and one equals one, one and zero equals zero. Um, one and zero equals zero blah blah blah zero and zero equals zero so we have a bunch of zeros and a one so we're going to get is this part of the number did not mean to back up that far. So, essentially we're going to get this number. And that's the number I want, because if I get a random number I don't care about any of the other bits, I only want the bottom two bits the two's place and the ones place. So in a binary number you have one's place Tuesday's place for space eight space 16 space. I only care about the twos in the ones place two plus one adds up to three so I and by three. It does need to be the number three and not just the number address three. And then, because I don't want it to be just 023. I actually need it to be two to five, I'm going to add the number to to it. So now it will be every number from two to five, because it can be the biggest number it can be as three and if I add two to three I get five, the smallest number it can be as two and if I had two to zero, I can get to. So, this is giving me a random address here. And so if I were to just run this code. Let me load a into something. Now let's just load it into one of the random numbers we'll just do random numbers. And then assemble and run this. Whoops, we need a loop. We'll jump infinite. If you don't like go to this is go to, and I love go to. Okay, okay. And that's how you love go to but you hate this doesn't mean I only love go to because so many people go, it's not needed it's totally needed. How else could I do this. Nonetheless, I don't want to get rid of conditionals. I just don't like the statement if I think it's it causes complications now why it's doing this the only numbers I can have in the beginning of this number are 2345. So that's 2345 that's where those positions are and then I'm rotating random values through them. But I want to do this so I can cover the whole screen so we will change this to this would change the Y position it won't really matter. We won't do that we'll just change that. And we'll just know this is a random number to this we don't care about like we care to hear what would happen if we'll get back to that will assemble that and run this and this just does a bunch of random colors on the screen. So we're loading a random number. So the bottom. So if you watch down here you're seeing everything that's happening right there. And then we're just putting random values into those numbers. And since those numbers are all V brand. Well, it just continues on forever, but if I wasn't to do this like say I just stopped this and got rid of these two lines. Now I could write to anywhere in memory. And that wouldn't be a problem until it was my code until I started writing to 0600 to it's one to this this is two bytes this is two bytes so that's four bytes six bytes seven eight bytes 10 bytes. This is 12 bytes and then this is 15 bytes. So anywhere from 0600 to 06F. Well we're gonna have a problem because going to overwrite my code and then my code's not going to probably work unless I got lucky. I might get lucky a couple times. Theoretically, it could accidentally put cool code in here and we could see any number of things happen. But it continues on until it eventually will write to. Oh my. Is it ever going to write to this guy might have protected his I don't know. I feel like it should have written to it by now. There it goes. See 0600 it wrote over loan a FE. It wrote. We could save that value. And so whatever value this is we can go and store this in 03. So that way we can see what value it actually writes and see what kind of code it was trying to make happen. Well that one failed a lot sooner 0657. Hmm. Maybe I'm misunderstanding something there. I guess that was it. I think it's just, that's weird. I have to think about that too long and I'm not going to. 0657 doesn't actually affect our code so the 57 must have been written after our code was already messed up. My guess is that the that it let it run to that point. 57 must be an opcode. It can also be an undocumented opcode I need to mention those I guess. In a real NES or a real Commodore 64 the run documented opcode that programmers could use but you were told not to use. If you wanted to be an official like software developer for like Nintendo you were not supposed to use these codes because you could accidentally crash your entire game and you, it would just be done. But in reality, they always are where they are. And so for the most part, unless Nintendo changed their hardware, your code would run. There was a case of only one. NES game to know where they actually reminds me of the reminds me of the the chompers and galaxy quest like, Why does this exist this has no, no, no purpose. But um, so you can write to the screen but this is a good point about optimization here let's let's talk about that. This is pretty optimal code. Oh five story. I don't think you can get faster for writing to the screen than this right here. That's very optimal, useless, but completely optimal. Optimal code is is code that generally only wants to do one thing like the best optimization is code that only wants to do one thing. There are system considerations that we could talk about like page boundaries or in more complex systems is a lot more we could talk about but in this particular code right here. The optimization is bad because we're not checking anything we're not and we're not able to use this code for very much like I could theoretically do this and just blink this pixel. These are just labels for addresses that way I don't have to tell it exactly where I want it to run. I might be able to do that though. I think, if I remember correctly I can do this. I know I can do this in WLA DX I don't know if I can do it in this assembler, but I should be able to do this. And that's the same as having. I'm just going back to this address. So rather than, um, than rather than have to put loop here, I if I knew where my address was, I could just go, I want to go there. And it looks like it's going to work. Yeah, same code same same things happening with that code. There's a little blinking dot here if anyone doesn't see it. Um, but as you write longer and longer lines of code you're going to forget where that number is so you want to have a label so you can just go loop, and then refer to that label and then your compiler or your assembler would figure out. Okay, you want to go to there, which is 600, but you don't have to memorize that Oh and you do need that. Otherwise it doesn't work. Um, and same code. Now, we do want to, we want to do that we that was cool that's neat that we can write a bunch of pixels to the screen but we want to be able to write to a particular pixel of screen. Like say I wanted to write to the the x coordinate 15 and the y coordinate 15. And I don't want to have to spend too much time on it. Um, this is going to be easier if I just copy paste some code I think because I could write it but it would, I probably would make a mistake or two that would just annoy me so we'll just copy paste some code I wrote earlier. And so that and not all of it's very clean but we'll do this. Um, I do write quite a few things in 6502 assemble I'll say for fun, not for any real reason, especially like most of the things are right nowadays end up in being in systems like this. The reason I write in that way is because like I like to think through the logic of things. This isn't one of those cases but I just, I do write quite a bit of code in here but you're never going to write code like this for your job I at least I don't think so I would love to have that job if anyone gets that job. But now we can. We could load x with a random number. We want to cap that number. So that it's only a value from zero to 32. We could do number 32, which is not number 31, 1f is 31 because it's 15 plus 16. And we could load why with zero to 31 is 32 numbers that's what that means. And then we could add that by 31 show what this would be if it was hexadecimal. And this is what I prefer working in is hexadecimal so I don't often use decimal, but it may make it easier to read if it's like that. I only want to make sure that the numbers are between zero and 31 so I'm ending by 31 31 has all the bits set so it's just convenient here. Now if I was working on a system that was a 640 by 40 screen. I'm not going to be able to do that same thing there are other tricks I could do but I couldn't do just what I did here. Because there are certain things that it would let me write to if I just ended by 640. That doesn't actually get me anywhere. This is just very convenient because all the bits are set in 1f this is 1f. So that's 16 plus eight plus four plus two plus one. And then I can load a with that the and I don't really care. There, and then we'll jump to pixel set. And we'll after well we'll loop. No. Okay. Okay, and it set the pixel there. I don't see a D nine in there but I guess that gets corrupted here I must not save the registers here I did in a straight line example that I did earlier because you had to make sure that the registers return the same ways. But that's an optimal. It's not as fast so I did not do it when I created the pixel set algorithm so I'm not keeping X and Y what they were. I can change them on the fly. That's right because I do all this logical shift right here. So, one over some of this code. First things first I'm going to push a because I'm going to need it later. But then I'm going to transfer right a B and that's I'm trashing it now because now rise in a and so I need a to come back at some point. Then I'm going to push a again, because I'm also going to need why later and I don't have it right now but for right now I'm also going to take why go ahead. What was your question. I can hear you now yeah. Hey just general question about questions like if we, if we have questions but don't want to interrupt what's the structure of the presentation going to be like do you have an open question at the end or should we interrupt and ask a question along the way. It depends if the questions about what I'm doing right now then go and ask the question down. If you're going to remember to the end that's fine too. Okay, but do remember exactly what we were doing at the time because like it may be hard for me to remember if it gets to that point. I have a question about this or. Well, it's not specifically about that. It's about something that you mentioned along the way, but I think it would be a tangent at this point so I'll hold on to it. That would probably be good. Also, right now I'm sharing my screen I don't often get to see the text. I don't know if I can make that happen. Let me see if I can. Here is the zoom chat. So if anyone else is anyone else in the chat. Yeah, I'm watching Donnie so you're fine just go ahead. Okay, so we could do this here and change this to jump loop. And then come back up here and do another loop and this would do the same thing that we did earlier. So we're using our pixel set algorithm and somehow messed up there still. There are three wars, there are three wars, so the three LS arms, the yellows are four wars. That's okay. That's what it's supposed to be. Oh, because this routine. No, that's fine. Oh, that's fine. Right now there's a bug in my code. That probably would have been easier to see earlier. So if you do this, you get to see what the heck stump is right next to the actual assembler. So that might be easier to see when you're looking at it also notice that little Indian stuff right here. 0611 becomes that so on and so forth. We'll debug this code together. Okay, we'll go over and then we'll figure out what's wrong with it. So we're pushing a because I'm going to need it later but then we're transferring y to a, and I'm still going to need that why again later so I'm also going to go ahead and push it as well. Then I'm going to end by one eight. And the reason that I'm doing that is again I only need the first, the three bites of this number because this number can only be between zero to 32. I want. So right now this number looks like this, it could be any number between zero zero to one F. So it looks like this or this or this or, you know, any number between this and so any of these ones or zeros that I have all as ones right now could be zeros. So all five of these digits here could be zeros, or one of them could be zero so on so forth. But I only care about these two upper parts, because these two upper parts are the only part that are important for whether or not the why is going down on the screen. And so these two upper parts here are what I'm looking for. And then I'm just going to shift right them until they're in the last bit position, and then I'm going to add to guess I could do that once and then add. No that double it be multiplied multiplication it doesn't work. So that's the right way to do it. So then I'm going to shift whatever bits are in here over and then I'm going to add to just like we did earlier. So I can get some kind of form of zero two to zero five there, because these two bits will only be between the numbers one and three once they're shifted right twice shifting means literally shifting so if you shift a number. This number runs over. It's going to go to this number. And then put a zero over. And so whenever you shift over, essentially whenever you shift right you're dividing by two, whenever you go the opposite direction, you're multiplying by two. Is it is it logical shift or arithmetic shift. It's it's a logical shift right. So zero goes in here there's rotation right and then that would put the carry into the position. Okay, so if you're shifting right the right most bit cycles around to the left, or does it fill in with zeros from the left. Okay, so this bit here actually goes into your carry. So this bit here goes into your caring but then logically zeros just come out the other end. Okay, so that would be, I believe that's arithmetic, because that would be like you described that would be a division so you have you have basically the number dot one or dot zero would like your remainder like you're talking about. Yeah. So we can double check. Um, so I don't know to be honest. That's fine. I was just curious. We don't have to know. It sets so it shifts all by right one position zero is always shifted into bit seven and the original bit zero shifted into the carry. So this always has zero to the right for logical shift right. So again, those names could have changed since the 6502 was a popular computer it's only been 40 years. So you're probably right, but I don't know when that change like so this is considered logical at this point in time might not be anymore. But we're using it for here we're not actually using it to divide. All I really want to do is I want to get a number between zero and three. And since I know these two bits right here are those two bits that I want. That's what I'm shifting over and I just don't care about getting rid of these three bits, because I also saved these these bits here and I'm going to use them later. So when we get down here I go and store that into one. So that's very similar to what we did earlier we stored something between two and five into one. And then I'm going to pull a which if you remember, if you guys don't know stack stuff then it's last in first out. Last in first out, that's the right way to say it. And so the last thing I put in was a but it was because there's no way to push why that's the only reason I have to transfer right a and then push a. Some people call this. If you guys haven't learned and we can go over that at some point but in risk computers and reduced instruction set computers, you oftentimes have to do two operations to do one thing, but both of those operations are equally fast. So some people would say about the 6502 back in the day was the first risk computer it's not really, but it shares some similarities in the fact that they cut out off coach just to go. Yeah, it would be simpler to just have a push why, but it would take just as much time because we have to get that why here and or cost more money for us to put a bunch of, you know, silicon on the whole thing. But they didn't want to spend that money and they didn't want to spend that time so they just went. Okay, we're just going to do push a theory that they can also just done macros and just said, if you want to push why we'll just have a macro that says, write a push a and then you could just call it push why and you can do that in real like so wldx which I showed you guys earlier is a macro assembly. So if there's something that you do rather often like say you want to do 16 bit division. If you wanted to do that a lot in whatever code you were writing, you would write a macro for it and then you could insert that macro anywhere in where you needed to use it. You could also just write a function and always refer to the function but anytime you're jumping or jumping saving the return address or anything like that. It's slower. So on machines that ran at less than one megahertz sometimes it was not worth it to do that so you really really have to rewrite the code and every time that's why we had macros and that's why we just type the macro instead of the whole line of code that I wanted to divide the 16 bit number by 16 bit number. So ways to make this easier to their ways to make this not as easy as high level languages, but easier than it was, when we first started off with the idea. I still recommend learning this first before you go into all that because while that can be fun and easy. You're not going to know what it's always doing so if you don't know how to do it yourself then you may not know how it how that works. Obviously, that's the problem I'm having here too. But then we, we have to restore that into a stored a into one, we pop that why, and now I'm going to end it by seven and I'm going to just these last three bits because that's four plus two plus one so I just want to get those last three bits, whenever I end by a number I'm getting those numbers there. And then I'm going to rotate it right through the carry, because I could do this a different way I could do it instead of that I could do this, but if I did that I have to do five instructions of ASL. So I do ASL ASL, this should be functionally the same, but it's one more instruction so I'd rather just rotate through the carry, because I only need these three bits and I just need them in the top position. Now if I rotate if I ship them left five times they'll be in the top position because they're the last three bits so I just want to turn these into this, and I could do that that way. That was just a little hack to try and get some speed out of it but it's obviously not much speed. These are slow computers they're not meant to be speaking. But it's always fun to optimize even when you hate it. Yeah, and that by EO. Why did I end it by you. It's a good question. I don't think that code supposed to be there. It will be EO I don't. Yeah I don't know why that comes out that code doesn't need to be there. Then I'll transfer x to a put a in the Y so x is now in the Y. I'll pull a again, and then I'll stir a and the a from previously was this random number. So I just pulling that random number back out of the stack. We can step through this. Okay. Assembly. Assembly. As there are air. It says, oh, I can't have all that stuff. I mean, I can't just write random things in the code. We can put a comment. And that's, there we go. Okay. And that's all I meant to do though. So we'll raise the line put a line assemble again. We're going to put a random number into X. That's what a three is. We're going to load a random number into Y. That's what D is. Eventually load a random number into a, we're ending all these by three. Oh, oh, that's what I did wrong. So, again, this is how, how drunk I am right now. So what we have to do here, the first things we wouldn't do this, we do this. So that thing I mentioned about risk computers. This is the same situation. I can't and X with number 31. So I need to actually load a with the and 31 and then transfer a to X. And I need to do that same thing to F. And then we're going to put a random number into Y. So then we'll transfer a to Y. And that's where our code broke because I didn't remember that. Okay. Now the code will go smoothly and not stop randomly. Because those numbers do need to be done. But if I didn't want to do that. So I want to comment out these bands anyways. And I just want random numbers to go. Our code will eventually. Because eventually it started to write somewhere where it shouldn't write to. Not to that position. It's fine. It needs to stop. I don't know. I would have to step through it and take forever when you fun. So there are better debuggers out there than this. This is a good debugger for learning on, but this is not great. I can jump to a position, but I can't jump to it. Like citing what I wanted to go through it this many times before I get there. Or can't watch the position for if it changes to the number six. If you guys, you guys do a lot of debugging. Like when variables change or something like that. Maybe in JavaScript or Java. I use lots of print S. Yeah. Lots of print S. No, I'm a fan. That is debugging. It's kind of prehistoric debugging, but yeah. It's not. I mean, so what we did here is so we have an opcode called break. And what break does is what you really just do with it is you would just change any opcode to break. And then it would, this won't work here because this does not actually use interrupts, but then it will trigger an interrupt with that break. And then whatever code you have there in that era. It will, when it returns, it will return one number after this. So it'll return to the TAX. It's really arcade. But that's how you would debug before there were, before there were fast enough computers to actually have debugging on the same computer that you had the program running on. To maybe show this a little bit better. We can, we can do this, we could load X because we know numbers. We could load X with the midpoint of one F is zero F or 10, depending on which way we want to look at that. Or we'll load X with OF, we'll load Y with the same OF. And then we'll load a, doesn't really matter. We can just do a random number. And now it's just that middle pixel. And so we're in the middle of the screen essentially. And so if I wanted to do the bottom of the screen and want to do that same thing, I could write that position there. Whoops. Oh, what's it doing? Oh, it is doing it. I wasn't even paying attention. I just started running. If I want to write 00 here for the X, but I want it at the bottom left hand, left hand side. Left hand side. Yes. Left hand side. It's there. I want it halfway down instead of all the way down. So now I can write to anywhere in the screen. So now I could write a video game. I could take this information and write a video game. I've written with this because I don't know if this pixel set algorithm is actually that optimized. I actually had one. So I had a. Another. Tutorial website thing. I don't know what all that was. So I probably should have had this open. So this was a thing that I wrote like just to do HTML. For a coding thing that I was doing. And it's not all that informative, but it's got some information on it. But I think it's worth going over sometimes. One is that vendor runs on a 6502. And that's important for everyone to know. Because if a computer from the future can run on 6502. Then you know that's, that's going to be a thing. Also the terminator ran on 6502. So, so now you have the terminator and vendor and Kabuki quantum fighter. All run on 6502. And now you guys know that. And in roaring and soaring and all that cool stuff is right here. Does anyone know how to do Zora encryption. So like this. That's enlarge. So you have a value that's 041 and hexadecimal. And then you have an encryption key, which is just going to be in this case, it's F eight. And F eight. So. 65 comes out to this number, which is. That would be C. B. That would be B. Nine. So B nine. So we get B nine. But then if we did that same thing and we did the same thing. And we did B nine versus the encryption key of F eight. Then we get back to 65, which is the letter A. This is a form of encryption. It is by the way, the most secure encryption that has ever existed. And. That's kind of a lie, but it's also not a, not a hundred percent wrong. Like if your key is as large as your encrypted data. It could never be just randomly guessed. Unfortunately, that's not really listed. So if you wanted to encrypt a text document that's 400 pages long, then you would have to write a key that's 400 pages long. And then somehow you'd have to memorize that key for later. So that you could bring it back. And get the document back from the encrypted state. Not the best way to do this. But what we generally do with zero encryption and why it's considered unsafe. Is use normally zero by like a key, like say you have a. Secret secret your key. So you're so encrypt by the word secret, you'll get the binary values for the assi of secret. So you have to use that key. So you have to use that key. So you have to use that key. So you have to use that key. So you have to memorize that key for later. So you have to use that key for the assi of secret. And then you'll so encrypt everything in that document by that. Then it can be found because eventually someone will find something that seems like a word and they will crack your encryption. By looking at that. But this was used for a really long time for just fun reasons, not for any security reasons. Just to encrypt like simple communications and stuff just so that, you know, some level of encryption on things and also it's just pretty much the same encryption you have on your beer right now. So it's fine. Yeah. Oh, there's something. I see that chat has three things. Oh, join the telephone. Okay. I should approach those. Um, so there's that then there's this. This is a part of a half adder. And what this is saying is that the way computers add is they use a Zora gate and an and gate. So if you understand Zora and you understand our exclusive or, and you understand and and is how you get the carry. And S and Zora is how you get the ad. So if you, if you saw one by zero, you get one. So if you saw one by zero or zero by one, you get one. So that would be right for the number adding. But if you then took those same two numbers, they'll say you were doing one plus zero. If you first them, you get one. So that's right. One plus zero is one. There's no carry on it. So it doesn't go up to give it three or anything. But if you did have a carry on it, it's like say the number. So you wanted to add one plus or the number two really one plus two, one plus one. You absorb one by one and Zora is exclusively or since one or one are not exclusive, they're the same values. It equals zero. And then the end value would be for one. So that would set the carry value. You would then put the carry value into the two's place. And that is how computers add. So it's really just, they still do this. It's just, they do it much faster and with much smaller stuff now. But this is how we got to computer world guys. And then multiplication, you do it with a shift. As I explained it, when you shift to the left, you get a multiplication by two. If you then added the value that you originally had to that value, you'd be multiplying by three. So if you wanted to multiply by four, you could shift twice to the left and then multiply by four. So if you shift twice to the left, the number two, it becomes the number eight. But if you wanted to shift by five, you wanted to multiply by five, you would shift to four and then add the number again. So you add the number one again. So if that was confusing, it's, it's not my fault. It is my fault, but stop waiting. We're going to stop that. But what all it's saying is if you have the places. 128 64 32 16. 842 and one, and you have some numbers in these places, zero, zero, zero, one, zero, zero. By the way, if you didn't notice earlier, there is no multiplication on these 6502, there is no division on the 6502. So this is how you had to do it on the 6502. You can also do lookup tables. So another way to do multiplication is lookup tables. Just like you did. Well, maybe I don't know what everyone's school life was like. But when I was younger, they would make you memorize multiplication tables. And that's essentially one other way computers could do it. So lookup a, essentially an array or an area of ROM really, where you could have all these numbers where they're multiple kids of three, and then just go anytime I'm multiplying by three, I need to refer to that array and then just go to whatever position I want to multiply by three. So I want to go to the eighth position and multiply three times eight. The number 24 will be there. So that was one way to do it. But the easier way to do it as far as wasn't necessarily faster. It was just a matter of it was less, it took up less space and computers back in the day also didn't have a whole lot of that. So if you wanted to have all the multiplication tables, you weren't going to be able to store them all in most old computers. So this is what we did. We shifted things. So I have that now and I have the number 16 here, but I could move it over one and become the number of 32. And that's 32, but now if I had that 16 still, and I could bring it back and then go, now I just want to add those two numbers together. 32 plus 16 is 48. And that's multiplying by three. And so on and so forth. So that's how you used to do multiplication. Division was very similar, except for the fact that because we have remainders in division. If you needed that data, if you needed to have that remainder information, you would need to do something a little bit more complex because as numbers decreased in values and remainders were produced, you would have to find those remainders and such. So. There's some good code. There is a lot of websites on the. My computer is just slow now. Sorry, too much 6502 assembler. That's what it is. But. On this. Which I'll share somehow. I don't know. Oh, look at that later. Oh, why did I do that? Okay. I didn't finish this. So there's this website right here. FFD two. Oh my God. Let's just go to it in the actual. So that, that website right there. FFD two. Oh my God. Let's just go to it in the actual. So that website right there. That is a website mostly dedicated to Commodore 64, but it has a lot of information on 6502. When I used to do NES coding. Or even I did program some TG 16 stuff, not games, but like little demos and stuff. I use that website a lot because there's a lot of, like in that C equals hacking, which was a sign back in the day. They had a lot of information about how Commodore 64 coders would code music engines and things like that. And at that time I didn't know how to do any of that. I had been ripping. What we're called NSFs at that point. But I didn't know actually how to make my own. NSFs are in Nintendo sound format. They're similar to chip tunes. If you know what that is, if you don't know what that is, it's like, it's not quite MIDI because you're actually getting like, you'll have three square waves and a, and a noise channel to make your music. And with the NES, if I remember correctly, it was two square waves, a triangle wave, and a noise channel. And you can make your, you can make your music. You can make your music. You can make your music. You can make your music. You can make your music. You can make your music. You can make your music. You can make your music. You can make your music. You can make your sound waves, a triangle wave and a noise channel. And you can make your beautiful music with that. And I love a lot of Nintendo tunes. But I grew up in that era and not everyone knows him as much as I do. But I knew how to rip those. And I also knew how to, when I was writing my own code, I could take someone else's music from a game I love, which one of my favorite games to rip off was the Goonie soundtrack. Because I just love the cover of Cindy Loppers. And I would put her thing in almost every demo I released. It would just be the Goonies theme song playing over and over again. If you never play the Goonies, it's an excellent game. But if you've never heard Cindy Loppers, good enough for you. Are you good enough to be a Goonie? I think it says that in the name on the music video for her. It's awesome. You should check it out. But that website's also good to check out. It's a good resource of six 502 stuff and it has. Great. Algorithms for like, if you want to know how to multiply by six, 16 bit number by 16 bit number and get a 32 bit number. Which is not. It's not a hard task, but it's not a trivial task in. Six 502 assemblies compared to a modern computer that actually has multiple location. It has information on that it has other algorithms that are really cool stuff like that. Next we'll write a star field. So in, I'm not really going to write this. I didn't actually think about writing it, but I didn't actually write the code before I got done and it would take me a while to figure it out again. I've written it before though. You know, right at 3D star field. By taking. Sorry to interrupt. Donnie, you're breaking up. I'm breaking up. It might be my headset style. Yeah, something. I'm sorry. No worries. Are we ready to do. I have to go down to see the code. So. You want to see this code or which codes did you want to see the. I don't know. I felt that it's kind of like too abstract. Like it's going really, really abstract, but I, I'm losing myself. I didn't see a few slides that you showed early, which is the mapping of Java code or C plus first to the instruction to the assembly. I think that's more sensible. Okay. So yeah, we can go back to that. We'll start at this slide here. So that's the six 502 stuff. It's going to take a second. There we go. Yeah, this is more human friendly. I don't know if this is any more human friendly to me, but it's a, it is. There's not supposed to be that a squirrelly bracket right there guys. I don't know why that's there. I must have accidentally typed it when I've typed in this stuff. But this is everything to the left of that squirrelly brackets. Fine. And this is that same function, essentially. So the reason that the move L RDI ECX stuff, which those are registers in the, in the actual x86 computer, which is mostly computers work familiar with, which is the PC computer. The reason that's separated is that's actually how you're getting the values to compare. So all it's saying is you're going to get ECX and EDX from RSI and RDI. So I'm going to start with x86 assembler for one, I don't code in x86 assembler almost ever. It is helpful to be able to read x86 assembler. And I do feel that knowing any assembler, whether it be Z 86 502, even ship eight, which is not a real language. It's a fictional computer esoteric language. Because of its similarity or similar will make reading this stuff easier. But I'm going to go back to this. I'm going to go back. So they're just like we did in the six 502 earlier. And then if we if we. If we find out that one is. Producing a carry. They did name. These, these, uh, mnemonics better here, it says Joe, if greater to greater. One of the reasons I really do like six final two, it's similar though is because. carry occurred. That's true here too. Carries are still used in x86 December, but they just went on. Human beings aren't thinking like that. They're not thinking about the subtraction or anything. It is useful to know that that is how a compare is done. But this just says jump with greater to later. And so we go to greater. And we get the number one and we put it into al, which is the bottom part of the x86 accumulator x86 accumulator scope. It's a h for the high bit of a al for the little bit of a, which is the eight bit parts of a 16 bit address called a x, which is the 16 bit accumulator and then the 32 bit accumulators called eax, which is enhanced eax. And I remember what it goes on from there. Um, it's been a while since I've even looked at a co chart. But this is that same code in C. Over here. This is probably going to be part of this is going to be part of this code. I don't know why that isn't selected. Ah, go back. There we go. Okay, so this says the same thing as that assembler code. Um, it says, says it with an if statement, which we won't discuss right now. But I really want to if a is greater than B return one else returns zero. Um, again, this is just showing that knowing x86 assemble or knowing 6502 assemble or any eight bit assemble or similar would be advantageous to knowing how to read this code, which could be useful, not in this particular case, because this code's fairly simple and not not that big of a deal. But it could help you with understanding a how to optimize, though this is not the most optimized version of this code either. Um, but a how to optimize, but again, optimizations often not as important as what we used to think, because we can just make faster computers every year. We've broken the the laws and everything that we can. We'll never run out of RAM guys. Um, but anyway, unless you have a program, you know, we'll just download more. Um, but uh, also the video game developers, they'll run out of RAM, like they're dating new consoles every every day, apparently. Because they're like, we can't write real video games anymore. And I'm like, what do you mean? And they're like, we only got four gigahertz of power. That's not enough for a real game. I'm done with them. Uh, so and this is bytecode. This is not assembler. This is, um, bytecode, JVM, the told Java virtual machine uses the stack for everything. Um, it really, it loads the values from the stack. So it gets the value zero and one from the stack. These values actually have legitimate values put in them. But essentially the way you should think about it is it's very much just like the other example where those values are that A and B. So it's loading A and B, then it's comparing A and B, but it's also doing the branch in the same place as it does the compare. And it says, if, if the compare is less than or equal, we're going to go ahead and go to seven and return zero. But if it's not, we'll go ahead and return one. So that's all it's saying there's it's saying if it's less than or equal, um, then we'll go ahead and go to seven. And that's the seven down there. Um, this will then get turned into whatever the Java virtual machine wants to turn it into. These machines are very optimized. Especially the Java virtual machine, as everyone knows it's perfect and cannot be questioned. And it really is. I honestly, I think most of this works okay. And the only thing is is you see sharp. Um, I love Java actually, but it's fun. It's fun. I won't crowd down. Ew, why? Why? Yes, Java and JavaScript is the future. Um, I'm fine with Java actually. I like Java. I don't hate JavaScript anymore. I was right there with you, Mike, for a really long time. But I think it looks so much prettier now. It's so bad. Don't use it. But in the future, what we actually have is something called, um, and we have it right now where we just don't use it. It's called WebAssembly. And if you guys have been paying attention to the the internet stuff, um, that also would be easier to read if you had some experience with assembler. I will tell you it won't be that easy to read because they've tried to simplify it and make it more human readable. Um, to me, it actually makes a lot less human readable. But the bonus of this is that they do expect that most people are still going to program in high level languages, compile to WebAssembly, and then just use WebAssembly through a JavaScript front end. So if you needed like a high, a really fast 3D app on the web, um, then you could go ahead and write that whole thing in whatever language you wanted to compile to WebAssembly. All the mission critical stuff would be right there, and then you would just load it with some JavaScript and you're off and running, and then you have code running. Um, I doubt anyone will ever really write WebAssembly by hand. You can. They have, uh, compilers on the internet very similar to, um, those CSS and JavaScript testing things. So if you want to learn how to write WebAssembly, you can. But I will say that the way they tried to fix it into being human readable to me is less readable than any other language I've ever seen. So I just, I mean, it's fine if all you want to do is return a value of 42. I can show you guys what this looks like. I don't really remember if I have it bookmarked, but, uh, I'm sure I could find it pretty fast. Oh, that's probably right there. WebAssembly concepts. What is WebAssembly? WebAssembly goals. How does WebAssembly fit into the web platform? WebAssembly key concepts. How do I use it in? Oh, there we go. That's what I was trying to remember. Fiddle. So it's like JavaScript Fiddle or CSS Fiddle, and you can come in here and you can write code, and then you can look at it in various formats. We'll run it first, build it, and then run it, maybe. Yeah, there it goes. This is the text format of it, which yeah, I don't like. It's okay. It's just not as easy to read as I think it is. And then you also can look at Firefox x86, which just puts it directly to x86 or their version of WebAssembly. And there's some other stuff here. This doesn't look like anything to me. It does have that 42 at the end there. There's the binary code for it. But I wouldn't know how to use this to write a 3D game in WebAssembly. I could return 42. Where I could return? I could return any number. I can return 64. Maybe I'll read more about this and find a better example that looks prettier. But the outcome of this is still this. And well, this isn't that dissimilar from what we just saw in the Java version machine. And it actually works very much the same as well. To me, this is much harder to read than anything I've ever seen output by the Java version machine. Maybe it has some advantage somewhere else, but I doubt it. I think they were intending this to be easier to read by programmers. And if you guys could read that, then more power to you. I don't think it's as easy to read, but it also doesn't explain to me how I'm going to do a division later. Because I want to do a division or a compare. And I even haven't found, I haven't looked that hard, but I haven't found a good opcode list for all of this stuff. Because for the most part, like they say, they're sitting here going, you're going to just be putting this stuff into whatever language you like and then just compiling it to WebAssembly. So you don't have to actually write WebAssembly at any point in time. A lot of people, not unpopular people, say that this is the future of the web. And for like 3D apps and like whether or not your game is going to run all in your browser and stuff, it may be the future. It has a human readable text format. I don't agree. All right, Dany, are you ready for questions? Yeah. Question and answer. Mike, you got a one? I got a human engineer. Sure, I can open the questions. So for people who have experience in whatever language, but experience doing software engineering, we have like IDEs and test methodology and test frameworks and all of this kind of stuff, like a whole kind of sophisticated tool set and whatever higher level language you're using. What's the code organization like for assembly and do they have similar sorts of things at the assembly level? So I would say not what you're talking about. You can get WLADX to run in VS code. You can compile to it and everything. You would have to then have a target machine and you'd have to run on the target machine. So you could use VS code for all of your coding. You could then use something like NoCast, NES or NoCast Game Boy. I just don't remember his address all the time. This guy is famous. Sorry. I was just going to say, do they not usually bundle a test suite with their code or something like that? Because normally when you would go and look at, say, some open-source package or the library or something, like you could download and compile it. Yes, but you could also run all the tests for it. Like I'm picking unit tests, integration test, functional test, whatever kind of test. I don't know what that looks like at the assembly level. So there's a lot of things that will make assembly easy for you, easier for you, assembly is never going to be the easiest. Like I mean, in testing is complicated too. But there is, so on this webpage right here, this is a guy who made emulators for a really long time. I paid for his 8-bit Game Boy emulator debugger back in the day and it was awesome. It's amazing. It's got so many features and it was really easy to debug my code. If something broke, I could find it really fast. I could watch for anything I needed to watch for, but it is very much assembly debugging. It's not like test-driven development. There'd be a lot of overhead to, like if you were for a real computer that runs these kind of, these type of systems, there'd be a lot of overhead. Now, in x86 land, if someone is suicidal, I mean, committed to doing x86, I'm sure by now someone has come up with test suites and things like that that are much better suited to it because a modern computer could handle that. But most of the stuff I deal with is older computers and there's just not any way that I would include a bunch of, like I would include very much what the guy said before. I would include some way to print something if something went wrong. So that way I could test, oh, something went wrong there, right? Like, and I could get all the values back and all that stuff. So if I could return every value that I possibly had, as long as I didn't run out of RAM or something, I can store those values in RAM. And then when the system crashed, if I was right about where I thought it was going to crash, then I could at least look at those values and go, oh, that's why it crashed. This number should have never been that number. But there's not test driven development like there would be in modern language, like high level language, which is running on a computer that is much more powerful than these computers. This is the closest you would get. You would get a good debugger. The only thing I need to mention here, because we are talking about the 6.502, for the most part, is he used a completely different syntax for everything he did with NoCast NES, which is his NES emulator. And so if you ever look at his code, which I did earlier today, because I was, we'll save it here. I don't want to, no, I don't need to save it. Because I just need it to show up down here. And then we'll look at his code. And he also has a assembler inside of his system. Now everything I talked to you about loadA, stuff like that, like he's, first thing he's putting. So I don't know what all these names mean. And this is a problem in programming in general, but in particular, it looks like he was a little lazy with some of these names. Some of them I could guess what they mean, but I don't know what all these names mean. But these are just places that he's putting this from memory. So he can go, I need this to be here. I need this to be here. I need this to be this value. I need this to be this value, things like that. And then he's coming down here and eventually he gets to the code. Most of this is just space that he's dedicating to things that he can use for later. And come on down here to where he's actually got some code. And earlier, when we did a shift right, it was logical shift, right? So LSR, but he does shift right and then you have to have the A there. He also does, rather than do a branch, he does a J E, which is a jump if equal. He's also comparing, and he has to specify A before he compares it to the V bank link count plus zero. This is not what I'm used to looking at and also not what 6502 assembler looks like. He does a move A here. This is similar to, I don't know what it's most similar to. It's similar. It's not completely unfamiliar if I was coding in Z80, which is his best emulator. His best emulator is the Game Boy, the Game Boy emulator. And his Game Boy emulator was really easy to read and of course was the same syntax that I'm used to. As far as I know, and I have tried looking into this a lot, I don't think anyone else uses the syntax but him. So unless you want to dedicate yourself to this syntax, unfortunately, he's not great for 6502 assembler. WLDX Compile 6502 assembler would let you do a lot of the shortcuts that are there, but he doesn't have a debugger anywhere that would be useful to you. So he doesn't have anything that would be that good. He does write symbol files, which are for debugging, but he only writes them for the no-cast SNES, which I haven't looked at the syntax for no-cast SNES, but I assume it's almost probably going to be as horrible as the no-cast NES. I also know that he had a problem because he called his emulator no-cache and he got in a little trouble because eventually he said, I would like donations. Like I'm still going to give away the emulator for free, but if people donate, they'll get it a little bit sooner and I will include the features that you need for debugging games and stuff. And not everyone needed that. So it wasn't that big of a deal. And a lot of people did, well, not a lot of people, but I paid, some other people surely paid. And but he did get upset because a lot of people basically wrote debt threats to him at that point in time. Oh my God, you just ruined my life because now I'm going to have to kill you because you decided to charge for something that you worked really hard on. At that point, I have a feeling that he probably got pretty pissed to the community. And so later on, when he wrote no-cast SNES, that might just be him going, if you want a feature here, I'm going to give it to you for free. It's going to be the version I want. And then he probably does, because normally back in the day, he would sell this to companies who were trying to make these games. And there were still companies out there making SNES games, not a lot of them, but there are people that are getting together and are like, I would love to make an SNES game. About a year ago, there was a Genesis, brand new Genesis RPG released and stuff like that. So that happens almost every other year. And so he might have that way, so that way people would pay for the option that he could change the language support. But I haven't ever found anyone else who uses his syntax. But yes, that's how you would do it. You would do it with a debugger, and it would not be the same as test-driven development. To write test-driven development in 6502 Assembler or Z80 or any other 8-bit Assembler, you would have to commit a good amount of your processing time to checking all of this stuff. And if, just like normal, you don't want your tests getting into your production, but it would be very hard to, you would need to make sure that everything's not coupled and things like that. And I just don't think it'd be very easy to do on older processors like this. So are there good ways though? But learning to debug is actually a good thing to do as well. Learning to debug assembler is also a good thing to do because sometimes you won't need to do that, and you'll just need to check variables and things like that and use a good debugger for a high-level language. But there are occasions when people have been completely confused about why something's going wrong and ended up being because they didn't know how something was working down at the lower levels. Does that make any sense? Yeah, yeah, sure. I have another question, but I want to yield and get someone else has a question. So like I said, yeah, I think you're good to go. Yeah, I know a lot of this was confusing, but like I said before, if you come to this website here, his tutorial starts off with, so just to reload it real quick, so it does have all my code all over it. His code literally just starts off with, he's going to draw three colors to the screen in order and he'll go over it piece by piece here. I think a lot of the stuff that we've been talking about today will make more sense when you read through this. I hope so at least. Like I said, I haven't read through all of it myself. I did different tutorials back in the day, so this wasn't available to me when I was... Yeah, I haven't read through it yet obviously, but I'm also kind of curious what guidelines, if any, exist out there for how to organize assembly code, because there's like coming from a Java background, there's Java very strong conventions about how you organize your code. And you have interfaces and implementations, you have classes, you have packages, you have all this kind of sort of organizational framework, and you have similar kinds of things with like Python and JavaScript has different kinds of require, whatever, but like how would he talk a little bit about how code is organized? Is it basically up to each author? Are there guidelines that... It is within, it is generally... I mean, so there were some things that people would generally say are true amongst all communities, but it was generally up to the author, and more than likely, if there were more than one or two people working on code, it would have to be... There'd have to be some kind of rules set. They'd have to say, don't do this, don't do this, or if they wanted to make sure that things were organized in a certain way, so that the guy who's doing the sound part doesn't have to worry about what the guy who's writing the rest of the game is doing. Those two people might have to work on something that they're going to say, you can't do this, or I need this much space or things like that. It's not quite the same as what we're... A lot of what I dealt with was the NES and how to program the NES. The Commodore 64 or the Big 20 might have been different in that regard. For one, you did have people who wrote code... Sorry, sorry, but let's talk about the NES a little bit then, because you're more familiar with that. Do you organize it into directories based on stage? Do you have sprites and graphics in one directory? How do you... It's a huge... It seems like a huge undertaking. How would you even go about organizing the group? So you're going to have your sound code. Just like you said, it's going to be separated into what I actually need it to do. So if I was to write an entire... Like if I'm writing a demo, I'll be honest, I don't organize anything. It's all the same thing. It's very linear code, just like horrible JavaScript code back in the day. One big file. If... Big file, big file. But if I'm writing something and I'm like, oh my God, I want to make this... The greatest game that's ever been made on a system that's really, really old, then I would separate it out. And I do know that in fact, several of the people who have finished their games, of course, also did that. If you guys haven't ever seen D-pad Hero, I recommend D-pad Hero. I'm a show for all people who make cool things on the NES, by the way. But you have D-pad Hero, NES. I thought it had videos or something on it, but it maybe it doesn't anymore. Well, it does have the music and you can also play it on Spotify. I don't know if this is... I'm hoping this is the actual music from... Because I have Spotify, but... No, this is just Michael Jackson's bad. I don't care about that. I want you to actually... So, we'll do the worst thing in the world to do, especially right now, because guys, I went to something and watched something on something, and so if this ends up being something crazy, I don't see anything crazy here. I mean, I don't know why that girl always shows up, but other than that, I'm not too disturbed by all of this. My ad blocks aren't good. But D-pad Hero is good to our Hero, if you guys haven't guessed that already. But, and yes, I love this music, but we'll fast forward through some of it. So that's how you play the game. But these guys came up with this game. They would have separated it out and stuff, even though it would have been a simple game, to be honest. They really focused mostly on the audience reaction stuff and of course the music, which we can talk about trackers later on, guys. Okay, that's enough music, because I know you're all enjoying it, but not as much. So yeah, I would separate it into files. I don't think it's, I don't think anything's changed. I mean, we've learned more as we've gone along and such, but I also would do functions, like I would do my pixel set function, and on my pixel set, unlike, well, I'm not sure I agree with high level languages and commenting. I don't mind commenting occasionally, but sometimes I read some comments and there's too many of them. And I'm like, I won't ever read your comments anymore because your code should explain your comment, if I have to read a book about how your code works, then write your code in a way that I can tell what it's doing. But that wasn't that easy to do here, but we did get something. So I could do this, this assembler is not great for anything, other than learning. I do think it's great to learn on this because it's going to be simple. You can watch memory, you can do several little things, but it doesn't have cool features that like WRDX would have or anything, but I can do this and say, I want that address, but what I want to be at that address is called, what do we say it was the least significant? So least significant, we're going to name it horribly. I don't like that either. Least, I don't know how big I can make the name. But I have a question following up. So Mike mentioned that if you have any organization for large, honestly, I don't think there is, but you said you can do your files on these simple tricks, like you did with text, but what if you're building a really complicated and sophisticated app, like a game app, and then the line grows to more than 5,000, then how are you going to trace it back? So the first thing is you look for what your program is actually doing at the point when it crashes. So to give an example, the only thing I can think of that's really relevant a lot that I did is when we used to, when, so a guy named Kevin, Kevin Horton came up with this concept. He was going to make chip tunes for the NES and they were called in Nintendo sound format, which is NSF. To find out where the code for the music engine started, all you had to know was that within the NES, and I could be wrong about these numbers, but the all of the registers for the sound parts of the NES are from 4,000 to 4,017, maybe higher than that. I can't really remember. And so you look for any writes to 4,000 essentially, and particularly those sound registers. And as soon as you found those, you would trace them back from there to find out what had happened. Now, all you have to do is, if your code crashes, like say, if it crashes inexplicably, you're probably right. Like, I mean, 6,000 lines of code, it's going to be really hard to go through all 6,000 lines of code and find out what's wrong there. More importantly, all the time, games did ship with what were unknown bugs. I mean, everyone knows about the zero level in Mario, Super Mario Brothers. Everyone knows about the ability to walk through walls in Zelda for the Game Boy Color or Game Boy. There were other hacks there as well. As I mentioned, someone had accidentally put in an unsupported opcode into an NES game. And it was unsupported, but it worked. So that wasn't really a bug. Like, nothing actually broke because of it. It just wasn't supposed to use it. And it could have broke if at any point Nintendo released a new version of the system and said, that unsupported opcode doesn't exist anymore. And instead, what we'll put there is just a return. And if they just put a return in that space instead of a no op, which is no operation, then that code would have broke completely. And then your game would no longer work. And people would be mad at Nintendo probably because they bought a new Nintendo and their favorite game doesn't run on it. But in general, you can find... Like, so you will find something where you're like, okay, well, we got to this level and at this level, this game just crashed. Yes, I have 6,000 lines of code, but it's got to be something related to this level. So I could watch the memory. I can do that. I can watch the memory and go, what's going on in memory that looks odd? Like, I know I only write to a couple addresses at this point. Like, I only care about like, is it when I pick up the Apple that something goes wrong? If it's when I pick up the Apple that something goes wrong, I could put a trace on that and go, if this variable changes, like once this variable changes, I want you to stop and then I could trace back from that point and see if it... I'm a stooge. I'm a stooge. I was just saying. Say that again? I know I said that. I understand. Yeah, we understand. Sorry. Yeah. Yeah, I just, I think of the example, like one of the biggest, like most unbelievable, it's almost like Ripley's Believe It or Not, that game by Chris Sawyer, Rollercoaster Tycoon. The original Rollercoaster Tycoon was written completely in assembly. Yeah. Crazy. I can't imagine. And it wasn't that buggy, to be honest. I mean, considering that the kind of game it was and everything, it wasn't, it wasn't unpolished. It wasn't, you know... So you can test each piece of code, like so once... Oh, sorry, John. Like, go ahead. I hate to interrupt, but we have too close. I mean, we can stay, but it's already a part 12. And now anyone who are in rush for something else, feel free to draw. But yeah, we can stay. Do we want to stop the recording at this point then? Yeah. I think we shall. And I shall start recording now.