Submind YouTube summaries
Thumbnail for How to Code a 6502 Emulator in Python Part 15

How to Code a 6502 Emulator in Python Part 15

Watch on YouTube

Video summary

In this fifteenth installment of the series on building a 6502 emulator in Python, the creator addresses several critical instructions that were inadvertently omitted from previous videos. The primary focus is on implementing the CPX and CPY commands, which compare the X and Y registers against specific memory locations rather than the accumulator like the standard CMP instruction. Additionally, the video covers the INC (increment) and DEC (decrement) operations, allowing values in memory to be increased or decreased by one. The developer acknowledges that while much of the underlying logic can be reused from existing code blocks, these specific commands require careful adaptation to handle their unique addressing modes, including immediate, zero-page, and absolute addressing. The implementation process involves significant code refactoring and debugging, particularly when integrating these new features into the main comparison logic. The creator demonstrates how the carry flag is set if the register value is greater than or equal to the memory value, while the zero flag indicates equality. A notable portion of the video is dedicated to troubleshooting unexpected behavior with the carry flag during testing, highlighting the iterative nature of emulator development where initial assumptions about flag states often need correction based on actual runtime results. The developer also takes a moment to credit a community member named Ray for his contributions and suggestions, noting that Ray has even created an emulator for a Motorola 6809 processor in C++. Throughout the session, the creator emphasizes the importance of writing robust testing code to validate new features immediately after implementation. By loading registers with specific values like one or zero and comparing them against memory locations, the developer verifies that the flags are set correctly and that arithmetic operations wrap around as expected by the 8-bit architecture. Although the creator admits to rushing through some final checks to keep the video moving, they express confidence that the copied-and-pasted logic will function correctly across all addressing modes. The episode concludes with a summary of the implemented commands and an encouragement for viewers to continue practicing their coding skills, acknowledging that while perfection is not guaranteed in every step, the process of learning and fixing errors is integral to mastering emulator development.
Read the full video transcript
Okay, welcome to 6502 emulator in Python part 15. So, today we're going to be moving along here. Um, if you watched the last video, and I hope you did, uh, you real will probably remember, uh, realize I forgot uh, some very important commands. Um, cpx, cpy, which is compare the x register, compare the y register, and increment and decrement. So, add one or subtract one to a particular memory location. So, I'm just going to try and knock these out in this video. So let's go ahead and get to that. Now one of the things is I some of this code exists in some form or another in other you know other commands. So we should be able to just do a lot of copying and pasting and uh updating. So let's hope we can get that right. So just want to show you real quick my uh uh GitHub here. And I was just saying you know there was you know last video I used some suggestions from uh Ray here and Ray's got some really good suggestions. I got to use some in the last video. Hopefully I get to use some more in the future. And also Ray says here he's I'm not new to CPU emulation. So he has created a was it a Motorola uh 689 emulator written in C++ which is really interesting. The uh this is a processor that was used in the TRS80 and Vectrex probably some others but uh those are some classic uh you know computers from the uh 8bit computer and a console from the 8bit era. So check that out if you get a chance. Uh again, thanks to Ray for, you know, taking time and looking at everything. Uh and I just closed that, but it did say that I forgot to do some commands. I still have some commands to implement. So let's go ahead and do that. So we've got uh compare X and let's see where is CPX. CPX. There we go. Now CPX is kind of similar to compare. Let's take a look at compare real quick. Now compare compares values against the uh accumulator. You can see here there's tons of addressing modes here. But if you look at CPX and CPY, there's only three addressing modes for those, which I I thought was kind of interesting. So, I'm going to go ahead and just copy this real quick over to here so I can I don't Well, I guess now I'll do I'll do what I did before. I'll do this. That's probably makes more sense. Um, all that white on the screen is blinding me. So, uh, let's go ahead and just add those real quick. So I'm just going to copy the last one I did and put them in groups of three. So and this is of course the part we got to update. So we got three for CPX copy and three for CPY. And while I'm at it, I'm just going to go ahead and do uh increment and decrement quick just to kind of do this a bit more efficiently instead of jumping back and forth and doing all the same things all the time. So inc. Now they've only got four. So that's going to make things easy. I don't think we've I haven't actually implemented absolute x yet. So maybe we can't do that one. And I think decan has the same oops has the same four, but we'll get to that in a second. So yeah, let's give it a shot here. So, we're going to go back to CPX. And no, we're not CPX. So, let's go ahead and just get our values in. And now, this would actually be something that would be probably useful for uh you know to use uh AI for um immediate. Okay. Because it'll it'll just it'll just shoot this right out. I've I've tried it. um E4 CPX and mode is zero page and last one is absolute. So we got EC and absolute. All righty. CPY is very similar. So let's actually just try it this way. We're going to do CO, C4, and CC. And we got CP1. Get CPY. Try to get this through. And this is not the interesting part of this obviously. Why is there an extra space there? There we go. I always tell my students, look at the pattern. Um, immediate. We've got zero page. Same same things. and absolute. All righty. So, we got CPX and CPY done. Let's go to increment. So, I'm going to do the same thing I did here. I'm going to do uh E6 [sighs] E6 uh F6 E and FE. And this is [laughter] ink. Got zero page zero. We also got zero page X. Got absolute. And oh, we didn't do absolute line. Absolute X. Sweet. I guess we can knock all those out. I probably should have been doing this from the beginning, but you know, that's part of the process is learning how to do a little better. So, it's a little a little challenging to do this and talk at the same time. I know I say it all the time. I know sounds like an excuse, but it is so true. Um, de mode is going to be probably same as above. So, it might have been better just to copy do this first and copy like do ink then do deck but it's okay. Zero. Sorry, my voice is a little little rough here. Um just just dry air. All righty. Now, we're going to need to go through and add the commands. So, we have cmp. I'm going to get out of the habit of putting everything at the end. So, I'm just going to go where cmp is. Should probably put all this stuff in alphabetical order anyway. Um, we're going to do CPX here and we're going to do CPY here because they're going to be very similar. Um, CPY [snorts] and we're going to do uh def CPX self and mode and pass just for now. And then I'm going to go and do the same thing with CPY and to increment should be right here. So I want to put that here ink f in self mode pass and decrement should be remove the exo see self mode. Alrighty. Now we've got now we're now we're now we're cooking. So let's go ahead and go back and do the first one which was cpx. Actually let's just compile this. See if it compiles. That's a good sign. Um let's see if this still runs. Actually I can't because I changed the code. Um I did add testing code. I'll go over that bit with you. cpx cpx cpx yos. All right. So we're comparing the value in the X register to whatever value is coming from the mode. So it's really the same thing as CMP. So I really can just copy this. And we also have the register set already, which is good. So CPX. So all we got to do is check if instead of A, it's going to be X. A it's going to be X. Instead of A, it's going to be X. And instead of A, it's going to be X. That's it. That should do it. Um, so it's nice, you know, when you implement one thing and then you can just kind of Oh, I should change the uh comment too. All righty. You see I have these value equals self Y. I have I have these these things here, but I replaced all that in the last video with self setnz. Um, why is this one so diff? I don't need that anymore. Okay, that's nice. So, carry needs to be done, but I don't need this cuz I have that code. I wish I missed that in the last one. So, I should have deleted that. It's nice. And that's, you know, again, thanks to uh Ray for uh helping out with the code there. All righty. So, let's go ahead and make sure we got self a. This should be x and should Yeah. Is that right? No, I don't. Is that right? Undo all this stuff now. No, I can't delete those. Maybe I can delete this one. I don't think I can delete that one. Um, okay. Cuz it's not based on the value. It's based on where the comparison. Yeah, I do need to keep that. Let's go ahead and put that back. So, I wonder if that's going to cause problems. Yeah, I think that's going to cause problems. And all right, I'm going to undo. I'm going to get rid of this because I'm already setting N and Z based on the comparison, not the value. So, I should not have put that in there. I'm going to say, let's hope. All right. And this should be Y. And this is why you need testing code. um X. Okay. And then now I'm going to go ahead and do ink. So that is C. So I'm just going to copy the what I'm going to do here. I think I need to get the value increment. So based on the mode. All right. Let's see if we can find that somewhere. Um so based on the mode we need to get the value and so we're going to copy that from there. So in C so we get the value and then we'll do here kind of what we did there. So the value plus equals 1 we wrap it value and then we're going to put it back into memory. So say self memory loc equals [snorts] value. Yeah, that should probably work. And then ink this should be value. All righty. So if we have ink is basically the same thing. So I'm going to go decrement that. All righty. You know, I do think that's it. Now, there's probably some other little error we're missing, but we'll find out in a second. I don't know if any of it works. So, I do have some testing code. And so, basically, I'm going to load X with one. I'm going to compare it to one, and I'll debug it and see what see what we see there. Okay. So, we should see equal and not zero. um [clears throat] ldy. We're going to do the same thing with LDY. We're going to load one, compare it to one. We should see, well, we should see the zero flag set, not equal. Um, and then I'm going to load one into the accumulator. I'm going to store that at 4,000. I want to decrement 4,000. And I don't need that there. Well, I'm going to load the accumulator with 4,000. And it should be minus one. It should be should go from 1 to zero. Um, then I'm going to increment 4,00 44. That's not 4,000. Is it 4,000? It should be 4,000. I'm going to Is it 4,400? Okay. 44 44. Doesn't really matter what I do there, but uh the I had 4,000 there. Okay, I switched it. Okay, that was smart. Um, okie dokie. So then I'm going to do the same thing. I'm going to uh increment it and it should go back to one. Let's go ahead and run this. Of course, you got to spell push correctly. You know, I don't edit my videos. I leave this stuff in because I always tell my students, you know, I make all kinds of mistakes. Um, so we loaded X with one. We compared it to one. So zero is one. That means it is uh one there. So that means they're equal. Uh I'm not sure why carry is set. Why is carry set? Oh, that cuz [snorts] or is that when the Why is carry set? Let's go to compare X CPX. Okay, carry set if it's greater than or equal to. Okay, I forgot about that. Okay, that makes sense. Um, okay, so that's fine. So, greater than or equal to. Fine. Um, so what I need to do to test that then is I go back. I would test a not equal value such as two and then we should see oops two not equal and the carry flag is not not set now oh because it's not greater than equal to okay that makes sense and then let's go to zero I know I'm not explaining this very well but I'm pretty tired I just want to get this video done get this part of the thing done so zero U it's greater than or equal to zero should not be one though. Let's take a let's take a look at that parex. Okay. Greater than the value is greater than or equal to the current value. Ah, okay. So, okay. Greater than equal to carry should be set. Why is zero set? They're not equal. The value is greater than self x. Oh, value is greater than self x. Duh. If this was one and this was zero, it would not be set. Why should this stuff when I'm tired? And it's locked up. Annoying. Let's try that again. Okay, so x is one. We're comparing it to zero, so it's not equal and it's not greater than bonsai. All right, I'm going to take that as a win. Uh, let's go ahead and go on to the next part. So, we're going to load y. This should be here. X doesn't really matter, but should be there. Um, we're going to load y with one. We're compare it to one and that should give us uh zero and carry. So we have one. We see zero and carry. That's good. Okay. So now we're going to load the accumulator with one. We're going to store it in 400 0. We're going to decrement 440. Put it matter. Actually I should put a debug in there. Start this over. and one. Okay. So, I've loaded one into the accumulator. I've stored it in 4400. We don't really see that, but I have. Um, so you can see carry set for some reason. Um, sure. I forget what the reasoning. Oh, it's set from over here. I should have cleared carry earlier but it doesn't matter for this one. And 173 not implemented. [sighs] Crl Z. So 173 173 in X. We see AD. Ah AD is not implemented. Okay. learn. It is not there. Okay. Ah, never did that. Well, okay. Let's go ahead and just implement that quick. It's nice now is I can just add commands this way. I'm going to have to go through and add them all. It's going to be great fun. Um should be absolute spell it like absolute the other absolute because I teach kids. All right. One more time. So we loaded X, we compared X, we loaded Y, we compared Y, we loaded A. All right. So now we're here. Uh we loaded A with [snorts] one. We stored that in 4,400. We're at this debug. Now, we're going to decrement 4,400 and load it back into the accumulator, which should give us a zero in the accumulator. Awesome. Now, we're going to increment 4,400 and then load that back into the accumulator, which should give us one. And [snorts] voila, I think we got it. Um, I could sit here and do more testing code, but since I basically copied and pasted everything. It's should be functioning how everything else is functioning in the program. So, I I'm going to call this I'm going to call this I'm going to say this this was what we wanted. U, I do need to do further testing just on everything. Um, cuz I haven't rushing is a strong word, but uh, you know, my my purpose here right now is just more to get kind of a basic thing working. Thank God help me not have to go through and make sure everything's working correctly. Um, so yeah, hopefully that was instructional of some sort that hopefully that had some instructional value for people. Um, so let's go back real quick take a look at this concepts. So we implemented CPX, CPY, uh, inc. So increment and decrement. So let's take a look real quick. So CPX. So we get a value and based from some memory location and we compare it to the x register and just like with the accumulator we set carry if it's greater than or equal to um we set uh zero to true if it's equal. The idea is that you subtract the values and if you subtract it you get [snorts] a zero if they're the same. And then if it's greater than or equal to 128 that tells us it is negative. Um that's cool. So, CPY is the same thing. Everything should be working. Uh, and then, okay, of course, I for switch back to the main screen. Um, so CPX, there it is. You know what I'm talking about. CPX. And then let's go to deck. And so, we get the memory location, we subtract one, get the value from the memory location, subtract one, wrap the value. Did I wrap the I don't have to. and then put it back in there and then set the flags based on the value. And the same thing with inc. So yeah, pretty cool. Um, again, not guaranteed everything's 100% correct, but for now, I think we can go with that. Hopefully further testing will will tell us yay or nay. It's part 15. Thanks for following along. Keep on coding.