Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

6502 assembler random number problems

Tags:

assembly

6502

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

like image 405
jriff Avatar asked Jul 23 '15 19:07

jriff


3 Answers

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
   █   █   █   █   █   █   █   █  |
   █   █   █   █   █   █   █   █ /
like image 174
Lynn Avatar answered Nov 13 '22 11:11

Lynn


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.

like image 45
Tommy Avatar answered Nov 13 '22 13:11

Tommy


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.

like image 1
puppydrum64 Avatar answered Nov 13 '22 13:11

puppydrum64