6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 9:02 am

All times are UTC




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: Pong game optimization
PostPosted: Tue Apr 09, 2013 2:25 am 
Offline

Joined: Tue Apr 09, 2013 2:15 am
Posts: 4
Hey guys, this is my first post here on the forums, as well as my first program for the 6502. I wrote this with Skilldreck's "6502 Easy" online emulator. So far I just have the player one movement done. Use the W and S keys to move the paddle up and down. The concept works, but I have a sneaky suspicion that the program can be drastically optimized, especially where I do the paddle index increment/decrementation. I also have not yet added code to restrict the paddle from moving outside of the screen boundries (a quick CMP should do, correct?). Let me know what you think. Your considerations are appreciated.
-Daniel
Code:
lda #$00
sta $00
lda #$02
sta $01
lda #$00
sta $03
lda #$02
sta $04
;$00--->low address pointer to paddle index
;$01--->high address pointer to paddle index
;$03--->paddle origin low
;$05--->paddle origin high

loop:
  lda $03       ;reset paddle draw indexs
  sta $00
  lda $04
  sta $01
  jsr drawPaddle
  jsr readKeys
  jmp loop


drawPaddle:
  ldy #0
  lda #3       ;set color of player 1
  sta ($00),y  ;write that bit to display
  lda $00
  adc #$20     ;incr to next pixel of paddle
  sta $00
  lda #$00
  adc $01
  sta $01
  ldx $02      ;incr the counter till 5
  inx
  stx $02
  cpx #5
  bne drawPaddle
  lda #$00     ;reset counter for next run
  sta $02
  rts

readKeys:
  lda $ff
  cmp #$77
  beq upKey
  cmp #$73
  beq downKey
  rts

upKey:
  clc
  lda $00    ;decrement paddle draw index
  sbc #$1f
  sta $00
  lda $01
  sbc #$00
  sta $01
  clc
  ldy #$00    ;clear previous pixel
  lda #$00
  sta ($00),y
  lda $03    ;decrement paddle origin
  sbc #$1f
  sta $03
  lda $04
  sbc #$00
  sta $04
  clc
  lda #$00
  sta $ff
  lda $ff
  rts

downKey:
  clc
  ldy #$00    ;clear previous pixel
  lda #$00
  sta ($03),y
  lda #$20    ;increment paddle origin
  adc $03
  sta $03
  lda #$00    ;increment the high byte of origin
  adc $04
  sta $04
  lda #$00
  sta $ff
  lda $ff
  rts

gameover:
  brk


Top
 Profile  
Reply with quote  
PostPosted: Thu Apr 11, 2013 6:55 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
Hi Daniel -- and welcome!

Nothing like a little game to practice programming skills! I can see you're off to a good start with this.

My first suggestion is that you give symbolic names (labels) to the memory locations you're using, and then always refer to the locations by name. Maybe that seems like more trouble, but once you get in the habit it will pay off in the long run. That's because the code will be much more readable, both to others and to yourself -- and mistakes and opportunities for improvement will become more obvious. For example if you say
Code:
PaddleIndexL    =$00   ;low address pointer to paddle index
PaddleIndexH    =$01   ;high address pointer to paddle index
then later you can say
Code:
  lda PaddleIndexL
  adc #$20              ;incr to next pixel of paddle
  sta PaddleIndexL

  lda #$00
  adc PaddleIndexH
  sta PaddleIndexH
which is much clearer than your original code, isn't it.

I've only looked at the first portion of the program... partly because it's hard to read. (The comments are helpful at least.) Here are a few pointers. First, an addition sequence like the one above usually requires a CLC instruction as a prelude. You can omit the CLC if you know the Carry flag will already be clear, but these sorts of assumptions can cause trouble when you modify the code later, so always include the CLC or at least make an appropriate warning comment.

There's another little bug regarding location $02, which is not initialized to a known quantity before the first call to drawPaddle. The emulator might provide a consistent starting value in $02 without being asked to do so, but the memory in an actual computer is not so obliging! When the program starts (before the first call to drawPaddle) you need to go
Code:
  lda #$00           ;reset counter for very FIRST run
  sta Counter
(Notice I've chosen a name for the memory location.)

Care to polish up your code and post it again? Then we can advance from bug fixes to some potential optimizations! :D

cheers,
Jeff

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 14, 2013 11:31 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Hi Jeff, (and Daniel- welcome)
unfortunately Nick's mini-assembler in easy6502 doesn't fully handle symbols in the way we normally expect an assembler to. So your suggestion would need to be modified to use this trick:
Code:
*=$00
PaddleIndexL:   ;low address pointer to paddle index
*=$01
PaddleIndexH:   ;high address pointer to paddle index

*=$600

My fork of the easy6502 simulator does a slightly closer approximation to a symbolic assembler, which will accept your suggested syntax: see
http://biged.github.com/6502js/

Cheers
Ed


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 14, 2013 3:08 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
Thanks for the correction, Ed. I had a feeling I might be on shaky ground with that. :) I'm aware that syntax can vary but I didn't look into the specifics in this case.

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 22, 2013 12:17 am 
Offline

Joined: Tue Apr 09, 2013 2:15 am
Posts: 4
Yes, i was going to say that Nick's version didn't implement any symbolic labels for addresses... except for JSR (I contacted him, and looked through his source code to find some possible methods, but no success) Thanks BigEd I'll have to check out your version of the assembler/emulator. I have added portions to the code that restrict the movement of the paddle within the boundraries of the screen, as well as cleaned a few other things up. Hopefully I will port my code to BidEd's emulator and see if I can fully utilize labels, and repost the new code.


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 22, 2013 1:06 am 
Offline

Joined: Tue Apr 09, 2013 2:15 am
Posts: 4
Okay, I've labeled all of my memory locations, and have commented a bit more thoroughly. Here's the code, and please assemble it using BigEd's version of 6502easy.
BigEd's 6502easy: http://biged.github.io/6502js/

Code:
paddleIndexL  = $00
paddleIndexH  = $01
paddleOriginL = $03
paddleOriginH = $04
loopCnt       = $02


;$00--->low address pointer to paddle index
;$01--->high address pointer to paddle index
;$03--->paddle origin low
;$04--->paddle origin high
jsr init
jsr loop

init:
  lda #$00
  sta paddleIndexL
  lda #$02
  sta paddleIndexH
  lda #$00
  sta paddleOriginL
  lda #$02
  sta paddleOriginH
  lda #$00
  sta loopCnt
  rts

loop:
  lda paddleOriginL  ;reset paddle draw indexs
  sta paddleIndexL   ; because they are modified
  lda paddleOriginH  ; by the drawPaddle routine.
  sta paddleIndexH   ; Must be set back to "origin"
  jsr drawPaddle
  jsr readKeys
  jmp loop


drawPaddle:
  ldy #0
  lda #3       ;set color of player 1
  sta ($00),y  ;write that bit to display
  lda paddleIndexL
  adc #$20     ;incr to next pixel of paddle
  sta paddleIndexL
  lda #$00
  adc paddleIndexH
  sta paddleIndexH
  ldx loopCnt  ;incr the counter till 5
  inx
  stx loopCnt
  cpx #5
  bne drawPaddle
  lda #$00     ;reset counter for next run
  sta loopCnt
  rts

readKeys:
  lda $ff
  cmp #$77
  beq upKey
  cmp #$73
  beq downKey
  rts

upKey:
  clc
  lda paddleOriginL ;****see if paddle near edge****
  adc paddleOriginH ;add the hi and lo of origin
  cmp #$02          ;is origin at top of screen?
  clc
  beq onEdge

;decrement paddle draw index
  clc
  lda paddleIndexL
  sbc #$1f
  sta paddleIndexL
  lda paddleIndexH
  sbc #$00
  sta paddleIndexH
  clc
;clear previous pixel
  ldy #$00
  lda #$00
  sta ($00),y
;decrement paddle origin
  lda paddleOriginL
  sbc #$1f
  sta paddleOriginL
  lda paddleOriginH
  sbc #$00
  sta paddleOriginH
  clc
  lda #$00
  sta $ff
  lda $ff
  rts

downKey:
  clc
  lda $03     ;****see if paddle near edge****
  adc $04     ;add the hi and lo of paddle origin
  cmp #$65    ;is origin 5 pixels above bottom
  clc
  beq onEdge
 
  clc
;clear previous pixel
  ldy #$00
  lda #$00
  sta ($03),y
;increment paddle origin
  lda #$20
  adc paddleOriginL
  sta paddleOriginL
;increment the high byte of origin
  lda #$00
  adc paddleOriginH
  sta paddleOriginH
;clear the keyboard buffer
  lda #$00
  sta $ff
  lda $ff
  rts

onEdge:       ;returns program when paddle reaches
  rts         ;the edge of the screen

gameover:
  brk


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 22, 2013 3:03 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8545
Location: Southern California
Quote:
but I have a sneaky suspicion that the program can be drastically optimized

Even if you have an NMOS 6502 (not the CMOS one with more instructions and addressing modes, especially in this case the STZ which allows you to store zero in a memory location without first loading it into the accumlator), you can still shorten things up. With just a quick look (and not delving into the actual operation of the game):
Code:
init:
  lda #$00
  sta paddleIndexL
  lda #$02
  sta paddleIndexH
  lda #$00
  sta paddleOriginL
  lda #$02
  sta paddleOriginH
  lda #$00
  sta loopCnt
can become:
Code:
init:
  lda #00
  sta paddleIndexL
  sta paddleOriginL
  sta loopCnt
  lda #2
  sta paddleIndexH
  sta paddleOriginH

Code:
  lda #$00
  adc paddleIndexH
  sta paddleIndexH
can become:
Code:
  bcc 1$
  inc paddleIndexH
1$:

Code:
  ldx loopCnt  ;incr the counter till 5
  inx
  stx loopCnt
  cpx #5
can become:
Code:
  inc loopCnt
  ldx loopCnt
  cpx #5
but it doesn't look like you're using the actual X value, just using it to count; so it would be more efficient to load it with the number first, then count down instead of up (since there's an automatic compare-to-zero built into so many instructions), and just do:
Code:
  dex
  bne drawPaddle

Code:
  lda paddleIndexH
  sbc #$00
  sta paddleIndexH
can become:
Code:
  bcs 2$
  dec paddleIndexH
2$:

Code:
;clear previous pixel
  ldy #$00
  lda #$00
  sta ($03),y
can become:
Code:
;clear previous pixel
  ldy #$00
  tya
  sta ($03),y
to save a byte.

Code:
;increment the high byte of origin
  lda #$00
  adc paddleOriginH
  sta paddleOriginH
can become:
Code:
;increment the high byte of origin
  bcc 3$
  inc paddleOriginH
3$:

and in
Code:
;clear the keyboard buffer
  lda #$00
  sta $ff
  lda $ff
the lda $ff is redundant and unnecessary because you'll load the accumulator with the value it already had anyway.

I have more program tips at http://wilsonminesco.com/6502primer/PgmTips.html

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 22, 2013 3:28 am 
Offline

Joined: Tue Apr 09, 2013 2:15 am
Posts: 4
Woah thanks a lot GARTHWILSON. Just the kind of stuff I was looking for. I'll have to look through most of this some other time, but its a start. Hopefully by next weekend I can have an improved version. I can see how most of my code was redundant and therefore hogging up clock cycles.


Top
 Profile  
Reply with quote  
PostPosted: Mon Apr 22, 2013 7:53 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
That's quite normal for a first attempt! In fact I helped Nick tidy up some of his code for the "snake" game in his tutorial. I'm sure there are still a few non-idiomatic bits of code in there.

Of course, getting it right first is a good idea... then doing the peephole optimisations. Over time, you become more fluent and your first effort will be more idiomatic.

Cheers
Ed


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 19 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: