Need help with an incrementing 16-bit pointer
Re: Need help with an incrementing 16-bit pointer
Indeed - that's my point perhaps better made - it's a personal choice, not a must-have.
-
EvilSandwich
- Posts: 36
- Joined: 13 Oct 2019
- Location: Pennsylvania, USA
Re: Need help with an incrementing 16-bit pointer
Using a combo of BigEd's idea and floobydust's I whittled it all down to 23 bytes. I'm going to try to insert it into my program now! 
Less branching and it only runs three lines of code the majority of the time.
Code: Select all
LDA #$01
LDX #$01
LDY #$00
STX $02
STY $01
main:
STA ($01),y
INY
BNE main
INC $02
LDX $02
CPX #$06
BNE main- barrym95838
- Posts: 2056
- Joined: 30 Jun 2013
- Location: Sacramento, CA, USA
Re: Need help with an incrementing 16-bit pointer
EvilSandwich wrote:
Using a combo of BigEd's idea and floobydust's I whittled it all down to 23 bytes. I'm going to try to insert it into my program now! 
Less branching and it only runs three lines of code the majority of the time.
Code: Select all
LDA #$01
LDX #$01
LDY #$00
STX $02
STY $01
main:
STA ($01),y
INY
BNE main
INC $02
LDX $02
CPX #$06
BNE mainGot a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!
Mike B. (about me) (learning how to github)
Mike B. (about me) (learning how to github)
Re: Need help with an incrementing 16-bit pointer
One unexpected thing for me on this code snippet, as it has developed: my first thought was that the use of X to load and compare a value was not idiomatic - it rather looked like the writer was using all the registers just because they are distinct 'variables' and that's how you'd write something in a high level language. But as it turned out on second reading is that X is used well: Y must be used to index because that's the only addressing mode which fits the bill, and therefore A must be used for the constant value to be written, and therefore X is the right register to use as a working register for the comparison.
Using the right register at the right time is one of the marks of the well-crafted 6502 code... another being good use of the persistence of the flag values.
Using the right register at the right time is one of the marks of the well-crafted 6502 code... another being good use of the persistence of the flag values.
Re: Need help with an incrementing 16-bit pointer
You can shave off one more byte, and a few cycles:
I make that 22 bytes.
Dave
Code: Select all
LDA #$01
LDX #$02 ;; corrected
LDY #$00
STX $02
STY $01
LDX #$04 ;; number of pages to copy
main:
STA ($01),y
INY
BNE main
INC $02
DEX
BNE main
Dave
-
EvilSandwich
- Posts: 36
- Joined: 13 Oct 2019
- Location: Pennsylvania, USA
Re: Need help with an incrementing 16-bit pointer
barrym95838 wrote:
That looks quite nice, but you should replace the LDX #$01 with LDX #$02 to avoid smashing your stack, and you should be able to save one byte and a few cycles by replacing the LDX $02 with INX.
It seems screamingly obvious in hindsight, but I'm just so used to only thinking about the values in the Zero Page and kinda got stuck thinking of the Registers as just middle men to be used and forgotten once the bytes are in the right locations.
BigEd wrote:
One unexpected thing for me on this code snippet, as it has developed: my first thought was that the use of X to load and compare a value was not idiomatic - it rather looked like the writer was using all the registers just because they are distinct 'variables' and that's how you'd write something in a high level language. But as it turned out on second reading is that X is used well: Y must be used to index because that's the only addressing mode which fits the bill, and therefore A must be used for the constant value to be written, and therefore X is the right register to use as a working register for the comparison.
Using the right register at the right time is one of the marks of the well-crafted 6502 code... another being good use of the persistence of the flag values.
Using the right register at the right time is one of the marks of the well-crafted 6502 code... another being good use of the persistence of the flag values.
I often think of registers as "Robot Arms" that grab packets of data and place them in the right memory "Bucket". I often forget that the "Arm" will continue to grip what you asked it to grab until you ask it to grab something else.
I work in a factory as my day job, so it helps me to think of code in assembly line terms. lol
EDIT:
hoglet wrote:
You can shave off one more byte, and a few cycles:
I make that 22 bytes.
Dave
Code: Select all
LDA #$01
LDX #$02 ;; corrected
LDY #$00
STX $02
STY $01
LDX #$04 ;; number of pages to copy
main:
STA ($01),y
INY
BNE main
INC $02
DEX
BNE main
Dave
Now I can cut out the LDX and the CPX!
Re: Need help with an incrementing 16-bit pointer
Here's my 2c worth
Down to 20 bytes by re-using the initial STX in the outer loop.
Code: Select all
lda #$01
ldy #$00
ldx #$02
sty $01
loop2:
stx $02
loop:
sta ($01),y
iny
bne loop
inx
cpx #$06
bne loop2Re: Need help with an incrementing 16-bit pointer
EvilSandwich wrote:
Honestly, I keep catching myself with the exact opposite problem. I have an annoying habit of thinking of the Zero Page and the Flags so much, that tend to forget that there are still values in the Register that I can still technically use until something changes them.
And I see Dave/hoglet has now shown that the normally-idiomatic use of X as a down counter turns out to be another small improvement. And then Martin shows another improvement going the opposite way!
-
EvilSandwich
- Posts: 36
- Joined: 13 Oct 2019
- Location: Pennsylvania, USA
Re: Need help with an incrementing 16-bit pointer
BigEd wrote:
EvilSandwich wrote:
Honestly, I keep catching myself with the exact opposite problem. I have an annoying habit of thinking of the Zero Page and the Flags so much, that tend to forget that there are still values in the Register that I can still technically use until something changes them.
And I see Dave/hoglet has now shown that the normally-idiomatic use of X as a down counter turns out to be another small improvement. And then Martin shows another improvement going the opposite way!
Ask a dozen programmers to solve a problem and you'll get a baker's dozen solutions? haha
And now the age old question. Do I go with Dave to optimize for less clock cycles? Or Martin and optimize for a smaller size?
Both are equally attractive options (and for a mere 20+ byte program is completely meaningless from the point of view of the end user. lol)
Re: Need help with an incrementing 16-bit pointer
There can be no best solution - but this journey has been very informative, I think.
(Edit: I mean to say, it feels like a good thread to be found by future learners getting to grips with the 6502)
(Edit: I mean to say, it feels like a good thread to be found by future learners getting to grips with the 6502)
Last edited by BigEd on Tue Oct 29, 2019 9:13 am, edited 1 time in total.
-
EvilSandwich
- Posts: 36
- Joined: 13 Oct 2019
- Location: Pennsylvania, USA
Re: Need help with an incrementing 16-bit pointer
If nothing else, this thread helped explain something that was REALLY bugging me about branching. Why are there branching opcodes for all the flags except the Zero Flag?
Then you guys told me that was basically what BNE/BEQ was.
That changed a lot.
Then you guys told me that was basically what BNE/BEQ was.
That changed a lot.
Re: Need help with an incrementing 16-bit pointer
floobydust wrote:
BigEd wrote:
That's the spirit! The 65C02's extra opcodes are handy if you have them, but by no means necessary - and of course if you use only the originals, your code will run on either flavour.
-
EvilSandwich
- Posts: 36
- Joined: 13 Oct 2019
- Location: Pennsylvania, USA
Re: Need help with an incrementing 16-bit pointer
I used dave's idea and used it to streamline the confetti draw subroutine as well as the screen fill subroutine.
I am however keeping Martin's version handy in case I need to make it smaller someday. For now, I'll optimize for speed.
Once again, this program is designed to run in Nick Morgan's Easy6502 virtual machine:
http://skilldrick.github.io/easy6502/
I think this is as streamlined I can make the program now.
I also removed the code that initialized Y for the confetti subroutine, since Y will just be set in the main inner loop. I also removed the command to "Pause" the Confetti loop. The Pop Once function does mostly the same thing, so Pause was just redundant.
67 bytes for the whole thing!
I think I should just call this thing complete for now and move on to the next project.
I need to learn how to use the stack effectively. So I'll play around with programs that use the stack next.
I am however keeping Martin's version handy in case I need to make it smaller someday. For now, I'll optimize for speed.
Once again, this program is designed to run in Nick Morgan's Easy6502 virtual machine:
http://skilldrick.github.io/easy6502/
Code: Select all
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Waiting for input ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Press W to Pop Confetti Forever! ;
; Press O to Pop Confetti Just Once ;
; Press Q to End Program ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
idle:
LDA $ff ;reading last keystroke
CMP #$71 ;If Q, End Program
BEQ end
CMP #$6f ;If O, Just Once
BEQ poponce
CMP #$77 ;If W, Pop Confetti! Yay! :D
BEQ poprepeat
BNE idle ;If no input, continue idle
poponce:
LDA #$00 ;clearing last keystroke
STA $ff
poprepeat:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;clearing screen for new confetti ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LDA #$00
LDX #$02
LDY #$00
STX $02
STY $01
LDX #$04
sweep:
STA ($01),y
INY
BNE sweep
INC $02
DEX
BNE sweep
;;;;;;;;;;;;;;;;;;;;;
;Yay! Party Time! ;
;;;;;;;;;;;;;;;;;;;;;
LDX #$01
STX $02
loop2:
INC $02
LDX $02
CPX #$06
BEQ idle
LDX #$20
loop:
LDA $fe
LDY $fe
STA ($01),y
DEX
BNE loop
BEQ loop2
end:I also removed the code that initialized Y for the confetti subroutine, since Y will just be set in the main inner loop. I also removed the command to "Pause" the Confetti loop. The Pop Once function does mostly the same thing, so Pause was just redundant.
67 bytes for the whole thing!
I think I should just call this thing complete for now and move on to the next project.
I need to learn how to use the stack effectively. So I'll play around with programs that use the stack next.
-
EvilSandwich
- Posts: 36
- Joined: 13 Oct 2019
- Location: Pennsylvania, USA
Re: Need help with an incrementing 16-bit pointer
Okay, I lied. That confetti draw subroutine was bugging me and I had to streamline it.
I stole Nick Morgan's idea to use an AND function to mask out all but the two smallest bits and adding 2 to the result so I could get a random number between 2 and 5 for the high byte of the pointer, instead of just incrementing the high byte every time the low byte was randomized 32 times.
Saves me the need to load the draw limit into X three more times.
Also I really need to practice bitwise functions more. I'm still stuck in thinking of operands just as Hex numbers and that's limiting me so much.
Code: Select all
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Waiting for input ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Press W to Pop Confetti Forever! ;
; Press O to Pop Confetti Just Once ;
; Press Q to End Program ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
idle:
LDA $ff ;reading last keystroke
CMP #$71 ;If Q, End Program
BEQ end
CMP #$6f ;If O, Just Once
BEQ poponce
CMP #$77 ;If W, Pop Confetti! Yay! :D
BEQ poprepeat
BNE idle ;If no input, continue idle
poponce:
LDA #$00 ;clearing last keystroke
STA $ff
poprepeat:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;clearing screen for new confetti ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LDY #$00
LDX #$02
LDA #$00
STY $01
sweep2:
STX $02
sweep:
STA ($01),y
INY
BNE sweep
INX
CPX #$06
BNE sweep2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Yay! Party Time! :D :D :D ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LDX #$80 ;set draw limit
loop: ;confetti draw loop
LDA $fe ;Load random byte
AND #$03 ;And with %00000011 to mask out all but the last two bits
CLC
ADC #$02 ;Add 2 to the 1-3 result
STA $02 ;Store into high byte of pointer
LDA $fe ;Load random color
LDY $fe ;Load random low byte offset
STA ($01),y ;Draw pixel
DEX ;Decrement draw limit counter
BNE loop ;If counter no zero, loop again
BEQ idle ;Else, Return to Idle Loop
end:Saves me the need to load the draw limit into X three more times.
Also I really need to practice bitwise functions more. I'm still stuck in thinking of operands just as Hex numbers and that's limiting me so much.
Re: Need help with an incrementing 16-bit pointer
At least Hex is a good starting point! If you work in decimal, the bit patterns are very obscure indeed (other than even/odd or huge/tiny or positive/negative) - whereas in hex, you just need to get a feel for the 16 bit-patterns that you deal with, and that comes soon enough.