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.