Video summary
In this installment of the 6502 emulator series, the creator returns after a brief hiatus due to illness to tackle two new topics: implementing the BIT instruction and defining indirect addressing modes involving X and Y registers. The BIT command is introduced as being nearly identical to the previously implemented AND operation, with the sole distinction that it performs a bitwise AND between an operand and the accumulator without storing the result back into the accumulator; instead, its purpose is solely to update processor flags such as Negative (N) and Zero (Z). To achieve this in Python, the developer copies the existing logic for the AND instruction but introduces a temporary variable to hold the calculated value before setting the appropriate flags, acknowledging that handling the Overflow flag remains an issue for future updates. The implementation covers both zero-page and absolute addressing modes by adding corresponding entries to the command dictionary with their specific opcodes.
The video then shifts focus to the more complex indirect X and indirect Y addressing modes, which operate exclusively within the zero-page memory range from 0x01 to 0xFF. These modes function similarly to standard indirect addressing but include an offset added either before or after retrieving a pointer address. For Indirect (X), the process involves taking a base value stored in zero page, adding the current X register value to it, and then using that resulting sum as an index into memory to fetch two bytes of data; specifically, the least significant byte is located at the calculated offset plus one relative to the start of the pointer block. The creator implements this by modifying existing helper functions to handle these specific offsets, ensuring the logic correctly navigates zero-page boundaries where necessary.
Conversely, Indirect (Y) follows a slightly different sequence where the base address in zero page is first retrieved and interpreted as an offset into memory without adding Y immediately; instead, after fetching the two bytes at that location to form a full 16-bit pointer value, the current Y register is added to this complete address. This distinction highlights how X modifies the initial lookup while Y modifies the final target address derived from the data found in zero page. The developer proceeds to update the command dictionary with opcodes for LDA and other instructions that utilize these modes, carefully correcting an earlier mistake regarding opcode values before compiling the code. Although testing is deferred due to fatigue, the structural logic appears sound as it compiles without errors, setting the stage for future verification steps in subsequent videos.
Read the full video transcript
Okay, welcome to 6502 emulator in Python
part 17 with Tokyo EdTech. That is me.
If you've been following along from the
beginning, uh I know it's been a bit of
a gap since my last video. I've been
kind of sick. Uh nothing serious, but
just, you know, flu, CO, who knows? Uh
off and on for the past couple weeks.
So, you can probably still hear it in my
voice. Anyway, let's get started. Uh
today we're going to be taking a look at
the bit instruction which is very
similar to and it just has like one
important difference that I know of and
then we're also going to try and create
the addressing modes for indirect X and
indirect Y and they are a little bit
different and you'll see that today. So
let's go ahead and get started. Uh I'm
not going to do any testing code today.
Sorry. I just didn't have time to put it
together and I just really wanted to get
back on the back on the horse and ride
here. So let's go ahead and take a look
at bit. So I'm going to go ahead and I
think I have it up here. Um so it says
here it's very similar to the and
command which we've already done. So the
main difference is that the and
instruction performs a bitwise and with
the accumulator and stores the result
back in the accumulator while the bit
instruction performs a bitwise and with
the accumulator but does not store the
result. Um, it's just used to set the
processor flags. Um, so
basically what that tells me is I can
just copy the bit command and yeah, I
just copy it and just make a couple
changes. Again, I'm not going to do any
testing code. Just not in the mood, I
guess you'd say. Um, so let's go ahead
and find the and command here. And so
I'm just going to go ahead and just copy
this.
And uh I think again there's still some
of the the flag stuff is still missing
but let's just go ahead and live with
it. So I'm going to do bit and so
basically what we're doing is we're
going to still get the value like we did
before and we need to do the the and
now in the previous version uh this was
compared to the accumulator which we're
still doing but the result was stored
back in the accumulator. So I'm going to
go ahead and put a temp variable there.
And then we set the N and Z flags based
on that. So that should be all I have to
do. Now, if I was looking back at the uh
description here, it says I'm setting
the NV and Z flags. So I think Oops. I
think I'm only setting the N and Z
flags. I'm going to deal with that some
other day. Uh again, just trying to get
move forward here and trying to, you
know, push through this last part of the
um uh of this, you know, this project
that I've been kind of, you know, got a
little derailed on. So, I do apologize.
Reasonably confident this would work.
Don't know until I test it. Um but let's
just go ahead and make sure we throw
that in there somewhere. So, let's uh
find the bit command. And it only has
two modes. So, I guess we can just go
ahead and just throw that in there
quick. Um,
let's see here. So, let's go up to our
commands. Scroll up instead of that.
Yeah. So, let's just go ahead and plot
this in here. And doop. And so, we're
going to go ahead and copy that.
And we're going to paste that twice. So,
this one is 44. This one is going to be
bit and the mode is zero page. All
right, zero page. And the second one is
2C
and this is also going to be bit.
And the mode here is absolute. So it's
really all we need to do to implement
bit. Again, I know the V flag is
missing. We're going to just come back
to that some other day. Uh, I'm just
going to be confident. I'm going to hit
compile at least. See if it compiles.
I'm going to call that a win. So, um,
yeah, feel free to play around with
that. And if you see any problems, let
me know. Uh, the next part I think is a
little bit more interesting. Um, is the
addressing mode. So, we're doing
indirect X and indirect Y. Uh, and they
are a little bit different, at least
based on what I've been able to find.
So, let's go ahead and take a look at
the description.
And I found a really good description
here on this website uh mass work and it
has a really good explanation of it. So
basically what it is it's very similar
to zero page x u but because it's
indirect
um has a it's similar to the indirect
mode actually but it's like indirect
zero page x if you can think of it that
way. Um so this instruction here this or
sorry this chart here is really great.
So let's say we have LDA uh $1.70X.
Okay. So this this is a two byte
instruction. So it's only going to work
with zero page. So that's 0 to 255 the
the first you know area of memory. Um so
in this example we have A1 which is
going to be the uh op code for LDA
indirect X and then the value is 70.
That's the memory location. And in this
particular example X is five.
So what we do is we add five to 70 that
gives us 75.
Then we look we take the value of the
bytes that are at that location. So
remember it is uh you know the most
significant bite is second least bite is
first. So the memory location is 3023.
It takes the value in that memory
location and adds it to the accumulator.
In this case, LDA or okay, but the point
is the value comes from the location
plus X.
Look that up. Get the data and put that
into whatever we're going to do with it.
So, the value comes from here. So, let's
go ahead and see if we can implement
that. Um, so first thing we got to do is
create the mode here. So, I'm going to
do indirect
x equals auto.
I'm just going to do indirect y while
I'm at it, just since I'm here, so I
don't have to keep jumping around. So,
we're going to do that one next. And
then I'm going to scroll down
and in my get location by mode.
Okay. Um, let's see here.
Okay, get location. So, this is going to
give us the location of where that is
found. So,
we're going to do l if mode equals mode
uh indirect x.
[Music]
So, the location.
Okay. So, I'm just going to go ahead and
copy this um because I think this is
going to help us. Um
so, location is going to be
uh location. Yeah, we're going to need
that actually. U that's indirect.
Uh actually, that's not the Okay, we're
going to go jump back here. Um so, let's
go ahead and
How's this going to work?
C++ one. Yeah. Okay. So, I'm going to
use the zero page.
Actually, it's I can just use zero page
X here. Um because it's basically the
same thing. So, I'm going to do the
least significant bite is self memory
self PC but + one.
Okay. Now, it's zero page. So, I don't
really have to do anything else. Um and
then again, I'm going to add same thing
here. I'm going to add the X to that.
Now, in the zero page X,
we would just get the value. That would
be the memory location. Okay. However,
um actually this is not quite right. Um
okay, I got it. I think plus X.
Okay. Okay, the MSB would equal L
self.mmemory
self.pc
+ 1
plus actually plus two. No, no, no, no.
Plus one
+ one. Okay, I think that's right. I
I'll explain this in a second. Um, so
then the location is going to be this
thing.
Okay, the location
and then that's where the
jump address is. So it looks very
similar to this. So I think that's
one plus one. Yeah. Um
yeah, that's correct. And then the jump
I can just call this. So this not the
jump, it's going to be the location.
So now
Yeah. So now we're going to change it to
that second set. Yeah, that's it. Okay,
we're done. Um
yeah.
Wow, that's pretty that's pretty pretty
funky. Um so let me explain that um now
that I think I figured it out. So if you
remember, let's take a look at indirect.
Um, so this is where we're jumping to a
memory location that's stored in another
memory location. So our least
significant bite comes from, you know,
where the instruction is plus one. That
tells us the memory block um that that's
going to be in. And then
self-memory.
Yeah. Um but in this case it's you know
it's in the same section of the code but
what this does is it tells us so we're
going to get the one. So in the case it
was 70 in the example and then it's 70
+ one
no 70 plus it's going to be plus two I
think.
And
I got to think this one through here.
Um,
we need
Yeah, cuz it's zero page.
All right. So, I'm going to copy that
again.
And
I should have done some testing code
anyway. So it's self-memory PC + one and
that's the location because the most
sign by going to be zero because it's in
the zero page. Okay, I'll I'll take
that. Then
the least significant bit of where we're
going comes from this location which
would be 75 in the example and then 76
which is that + one. Then we get the
location the new location which is the
the real yeah which is stored in the
memory and then
we go
I'm happy with that. I think that's
correct. Um if anybody watching at home
says hey that's wrong let me know. Um
let's go ahead and try and do why uh
which is a little bit different. Um
you'll see that you'll see the
difference here uh in a second. So let's
go back to here. I'm fairly certain this
is going to work. I should have done
some testing code, but except I'm a
little tired today. I apologize. Um, so
this is similar except that we look up
the address first, then we add the Y.
Okay, so with indirect X, you know, we
were given location 70, we added five,
took the two bytes. This would be 7576
and then we get the location from that
um or we get the location. And then from
there we get the you know we get the
data from that location. Um in the case
of y and notice you can tell because
it's because of the way it's written. Um
here the x is inside the parenthesis so
it's applied to the memory location.
Here it's outside the parenthesis. So
it's applied to here the lookup value.
Um so if we get 3543 we add 10. That
gives us 3553.
Again, I know I'm not dealing with, you
know, kind of overflow stuff, but we'll
deal with that's that's a problem for
another day. Uh, yeah. So, let's go go
ahead and just see if we can code that.
Um, so basically what I'm do is I'm just
going to copy this because they're very
very similar. Um, I probably should
comment this better, but
have one of those days. So, this should
be Y. And so, that gives us the memory
location. And then actually that's not
that's not what we want. The y doesn't
go there. Once we get the location,
we add the y location plus equals y.
So we get the initial location. Uh so
that in the example here what was it? Uh
it was 70 as well. Okay. Then from
there we get the
least significant bite the most
significant bite transfer that to the
relative. So that's the location of
where that points to that gives us this
and then we add y to this location
and then that's it. Um
yeah that's it. Command S or control S.
See if it compiles. It's a good sign.
Um, again, I have haven't done any
testing code, but I I think this is
pretty close to what we want. Let's just
go back real quick and see if we can
find a command or two that has that. Uh,
sorry, an instruction. I know I was I
was chastised for using command. Um, but
an instruction that has indirect X. So,
what does L does LDA have that? That's
always a good one to play with. Yeah.
So, let's go ahead and just implement
the LDA version of this. And uh then
we'll call it a day.
Okay. So, let's Where's our LDAS at?
There we go. So, let's go ahead and pop
that in there. Going to go ahead and
copy this a couple times.
And again, I know I should do some
testing code, but uh it's just not in
the card today. Again, I apologize. Um
44.
Uh nope, sorry. This should be A1.
Excuse me. A1 and B1.
And
this should be
I didn't mess that up. Indirect
X indirect Y. Yeah, I'm thinking about
doing a whole video on just testing this
uh thing, but uh haven't quite decided
yet how far I'm going to go with that.
We'll see. So, I'm not super concerned
about the testing. Um, so yeah, that's
that should do it again. Let's see if it
compiles. That's a good sign. Um, I'm
going to go back down here, make sure I
didn't mess this up
bit thing. So, let's go back and see if
we can find bit again.
Um,
so it's 24 and 2 C because I think I
used 44. Um, 24 and 2C. I should have
known. They're so different. Okay, so
those of you watching home that were
like probably like, "Dude, you just
messed that up." Um, yeah, I caught that
hopefully here at the end. Uh, again,
there's going to be a lot of like
testing and verifying that this is doing
what it's supposed to. Uh, yeah, that's
that's a big project in and of itself.
Uh, something I didn't think about when
I started this. So, uh, going back to
coding concepts, uh, what we did was we
implemented bit, which is very similar
to an. So, I was able to just copy and
paste that code and just make the change
where we didn't store the value into the
accumulator. Again, I know I got to go
back and do the uh V flag, I think it
was. Uh but yeah, that's a problem for
another day. And then the addressing
modes, uh we talked about indirect X and
indirect Y. Uh again, X uh is added
before you get the data of the jump
address or the you get the address that
you're the indirect address you're
referring to. And then in the case of Y,
you get the address and then you add the
Y to it. So um so the X in X it's
applied to the zero page location in Y
it's applied to the location that's
returned uh from the data that's in the
zero page if that makes sense. So uh
yeah, thanks for watching and uh as I
like to say, keep on coding.