6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Mon Sep 23, 2024 7:27 am

All times are UTC




Post new topic Reply to topic  [ 65 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next
Author Message
PostPosted: Tue Oct 29, 2019 6:15 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10938
Location: England
Indeed - that's my point perhaps better made - it's a personal choice, not a must-have.


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 29, 2019 6:26 am 
Offline

Joined: Sun Oct 13, 2019 6:20 am
Posts: 36
Location: Pennsylvania, USA
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! :)

Code:
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


Less branching and it only runs three lines of code the majority of the time.


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 29, 2019 6:36 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1948
Location: Sacramento, CA, USA
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! :)

Code:
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


Less branching and it only runs three lines of code the majority of the time.

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.

_________________
Got 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)


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 29, 2019 7:04 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10938
Location: England
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.


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 29, 2019 7:51 am 
Offline

Joined: Sun Jun 29, 2014 5:42 am
Posts: 352
You can shave off one more byte, and a few cycles:
Code:
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

I make that 22 bytes.

Dave


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 29, 2019 8:17 am 
Offline

Joined: Sun Oct 13, 2019 6:20 am
Posts: 36
Location: Pennsylvania, USA
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 never even occurred to me that X and $02 would have the exact same values.

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.


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.

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:
Code:
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

I make that 22 bytes.

Dave

Oh, that's a cool idea. It lets me eliminate the Compare command completely! As well as the need to load the high byte into X (like how Barry suggested swapping LDX $02 with simply INX.)

Now I can cut out the LDX and the CPX!


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 29, 2019 8:34 am 
Offline

Joined: Sat Jan 02, 2016 10:22 am
Posts: 197
Here's my 2c worth
Code:
lda #$01
ldy #$00
ldx #$02

sty $01
loop2:
stx $02

loop:
sta ($01),y
iny
bne loop
inx
cpx #$06
bne loop2


Down to 20 bytes by re-using the initial STX in the outer loop.


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 29, 2019 8:39 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10938
Location: England
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.

Interesting insight!

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!


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 29, 2019 8:54 am 
Offline

Joined: Sun Oct 13, 2019 6:20 am
Posts: 36
Location: Pennsylvania, USA
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.

Interesting insight!

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!


What was it someone said on the first page of this thread?

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)


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 29, 2019 9:03 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10938
Location: England
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)


Last edited by BigEd on Tue Oct 29, 2019 9:13 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 29, 2019 9:12 am 
Offline

Joined: Sun Oct 13, 2019 6:20 am
Posts: 36
Location: Pennsylvania, USA
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.


Top
 Profile  
Reply with quote  
PostPosted: Tue Oct 29, 2019 1:59 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
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.

A very true statement, however, I decided to use nothing but the CMOS version decades ago. I still have the pair of Rockwell R65C02P2 processors I purchased back in the 80's and the original datasheet. One of those chips is still in my original Vic-20 and the other in my original 1541 diskette drive. I haven't written any NMOS specific code since then. Now that you can still get Rockwell CMOS chips at fairly cheap prices (for older hardware replacements) and new WDC chips, I can't see any reason to use the older NMOS chips. That's just my personal view of course, so all of my code since then requires the CMOS processor.

In my case, I have one project which by its nature has to be able to run on an NMOS CPU - the 6502 Fake Finder. I have an NMOS chip on hand for when it comes time to test that. I think nearly everything else I write will be for 65C02 or 65C816.


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 03, 2019 2:40 am 
Offline

Joined: Sun Oct 13, 2019 6:20 am
Posts: 36
Location: Pennsylvania, USA
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/

Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 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 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. :)


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 10, 2019 2:42 am 
Offline

Joined: Sun Oct 13, 2019 6:20 am
Posts: 36
Location: Pennsylvania, USA
Okay, I lied. That confetti draw subroutine was bugging me and I had to streamline it.

Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 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:


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.


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 10, 2019 8:16 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10938
Location: England
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.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 65 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: