I am playing around with 6502 assembler here: http://skilldrick.github.io/easy6502
I have made this that just puts a random color pixel in a random place on the screen:
LDY #$00 ; Clear Y
loop:
JSR genPos ; Put new position in memory
LDA $fe ; Get random number for color
STA ($10), Y ; Put pixel on screen
JMP loop
genPos:
STA $10 ; Store accumulator in low
LDA $fe ; Get new random number (WHY, oh why?)
AND #$03 ; Mask out low two bits (=numbers 0-3)
CLC ; Clear carry flag
ADC #2 ; Add 2 (= numbers 2-5)
STA $11 ; Store number in high
RTS
I am trying to use as few instructions as possible. My problem is that if I don't put an extra LDA $fe
in the genPos
sub routine the pixels are drawn in a very strange pattern where if I do have the extra LDA the code works perfectly. I can't comprehend why - can anyone give me a hint?
Regards, Jacob
It already is making a fine low byte! This line:
LDA $fe ; Get new random number (WHY, oh why?)
goes on to decide the high byte, and if you don't generate a new random number, the y
value will be dependent on the lowest two bits of the x
value, causing the diagonals you're seeing: the value of x & 3
always equals which segment of screen the value is being drawn on, meaning you get a pattern like
█ █ █ █ █ █ █ █ \
█ █ █ █ █ █ █ █ |
█ █ █ █ █ █ █ █ | x & 3 == 0 in $200-$2FF
█ █ █ █ █ █ █ █ |
█ █ █ █ █ █ █ █ /
█ █ █ █ █ █ █ █ \
█ █ █ █ █ █ █ █ |
█ █ █ █ █ █ █ █ | x & 3 == 1 in $300-$3FF
█ █ █ █ █ █ █ █ |
█ █ █ █ █ █ █ █ /
█ █ █ █ █ █ █ █ \
█ █ █ █ █ █ █ █ |
█ █ █ █ █ █ █ █ | x & 3 == 2 in $400-$4FF
█ █ █ █ █ █ █ █ |
█ █ █ █ █ █ █ █ /
█ █ █ █ █ █ █ █ \
█ █ █ █ █ █ █ █ |
█ █ █ █ █ █ █ █ | x & 3 == 3 in $500-$5FF
█ █ █ █ █ █ █ █ |
█ █ █ █ █ █ █ █ /
The algorithm applied with the LDA is:
[random 1] -> [11:10]
[random 1] -> [10]
[random 2]&3 + 2 -> [11]
(repeat)
If you fail to reload a
from $fe then you're doing:
[random 1] -> [11:10]
[ramdom 1] -> [10]
[random 1]&3 + 2 -> [11]
(repeat)
Therefore both the low and high byte of the addressed pixel is a function of the same random number. They're not independent. That creates a correlation between them. Which manifests itself in the pattern you see. If your pretend screen were 256 pixels wide it'd be a direct diagonal; based on the fact that you see 8 strips I can deduce that your output must actually be 256/8 = 32 pixels wide.
The issue isn't that you're wrong to say that "the random number in the accumulator ... should make a fine low byte for the screen address." it's that you're then also using it for the high byte. You're using it for both. The high byte is a direct function of the low byte. So there are a bunch of high bytes you'll never hit because they don't satisfy the constraint that high=(low&3)+2
. Those pixels remain unlit.
The reason is actually pretty simple. When you load anything into the accumulator, the accumulator is nothing more than a copy of whatever was there at the time. There's a fundamental rule of registers that if you don't change them, their value will stay the same indefinitely.
Although the value stored at $fe
changes every cycle, whatever is in the accumulator after you load from $fe
will not change unless you use another instruction to alter the contents of the accumulator. It's no different from this:
LDA $0200
INC $0200 ;the value at $0200 is now 1 higher than the accumulator.
Because of this, if you never reload the accumulator with a new random value, the value you're storing as the high byte is based on the value you used for the low byte.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With