Reading the controller?

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

User avatar
Bregalad
Posts: 7891
Joined: Fri Nov 12, 2004 2:49 pm
Location: Chexbres, VD, Switzerland

Post by Bregalad » Tue Feb 26, 2008 9:03 am

In fact any code that when executed takes two "RTS" in a chain is unoptimized.
Also, it's possible for subroutine to call themselves (this often isn't very usefull), or to call the latest part of themselves before they return, and this can proof usefull if the end should be done a couple of times instead of just one, this can make a shorter loop.

User avatar
tokumaru
Posts: 11771
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Tue Feb 26, 2008 9:19 am

OK, let's explain all the tiny assembly tricks to the newbies and confuse the hell out of them from the start, shall we?

I'd rather present the usual way of doing things to people who are just starting, and eventually they'll learn these tricks by themselves. Of course there are several ways to call a routine, but as long as a beginner sticks to JSR, they should be safe.
Bregalad wrote:IAlso, it's possible for subroutine to call themselves (this often isn't very usefull)
Recursiveness can be very useful, although probably not in a NES game.

tepples
Posts: 22019
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Tue Feb 26, 2008 5:19 pm

tokumaru wrote:OK, let's explain all the tiny assembly tricks to the newbies and confuse the hell out of them from the start, shall we?
My point was that "can't ever" is a strong word.
tokumaru wrote:Recursiveness can be very useful, although probably not in a NES game.
Flood fill is commonly implemented as a recursive algorithm, and I can think of a few places where flood fill would be useful, but I'll leave those alone for now.

User avatar
Laserbeak43
Posts: 188
Joined: Fri Sep 21, 2007 4:31 pm
Contact:

Post by Laserbeak43 » Tue Mar 04, 2008 12:06 pm

well, i've gotten the code to work, long ever since. but i'm experiencing delays(latency) between button presses and short envelope times. i was wondering if the line "lda #$9F" was just a short envelope time, so under it i tried lda FF in what i thought was square 2:

Code: Select all

right_is_pressed: ; play sound when right arrow is pressed. 

	lda #$01   ; Enable square 1 
	sta $4015  ; this register gets written to first to enable sound channel. Then come the other registers
	lda  #$02  ; Enable square 2?
	sta $4015	
	lda #$9F   ; Envelope 
	sta $4000 
	lda #$FF
	sta $4004
	lda #$21   ; Start tone 
	sta $4003 
	lda #$FF
	sta $4007
                rts 
	
same result.
Noob sticky!!
Please document this part of the NESdevWiki!! XD
YOU NEED A RETROMACHINESHOP!!

User avatar
Disch
Posts: 1849
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch » Tue Mar 04, 2008 1:10 pm

Laserbeak43 wrote: lda #$02 ; Enable square 2?
sta $4015
This is enabling square 2 and disabling the other channels. If you want to enable square 1 and 2, write $03 to $4015

Or... what I'd recommend is just write $0F once to $4015 at startup to enable everything (note that no channels will play any sound until prompted to do so, even if you do this), then you can forget all about $4015 completely (unless you want to use the DMC)


Anyway I don't see what could be causing latency. What might be causing a problem though, is the sweep unit. Even if you disable sweep, it can still silence low notes unless you switch it to 'negative' mode.

Here's a quick example:

Code: Select all

lda #%10011000   ; 50% duty, decay disabled, volume=8
sta $4000

lda #%00001000  ; disable sweep, set it to negative mode
sta $4001

lda #$FD   ; period = $FD -- concert A (440 Hz)
sta $4002

lda #%01010000 ; high bits of period=0, set length to play for half a second
sta $4003
This should work.

How I usually approach problems like this is I look at a technical doc covering the register descriptions... then just write to every register setting everything to a specific value.


If by "short envelope time" you meant the note was cutting out early, that likely was the length counter. Both %00100xxx ($21) and %11111xxx ($FF) -- the values you were writing to the length counter reg -- are both short values. %00001xxx ($08) is the longest you can set the length counter to. Or, you could disable the length counter via $4000.5 to have it play indefinately.

User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg » Tue Mar 04, 2008 3:03 pm

I bet the latency is because the sound is effectively starting when you release the button. To test this hypothesis, try holding the button for a while before releasing it. Does the sound begin when you press or release it?

User avatar
Laserbeak43
Posts: 188
Joined: Fri Sep 21, 2007 4:31 pm
Contact:

Post by Laserbeak43 » Wed Mar 05, 2008 6:47 am

blargg wrote:I bet the latency is because the sound is effectively starting when you release the button. To test this hypothesis, try holding the button for a while before releasing it. Does the sound begin when you press or release it?
i hold down the right button for 5 seconds or more, release it and nothing happens. i press the left key rapidly and stop, and it after i let go, it beeps a few times.
Noob sticky!!
Please document this part of the NESdevWiki!! XD
YOU NEED A RETROMACHINESHOP!!

User avatar
Laserbeak43
Posts: 188
Joined: Fri Sep 21, 2007 4:31 pm
Contact:

Post by Laserbeak43 » Wed Mar 05, 2008 7:00 am

Disch wrote:

Here's a quick example:

Code: Select all

lda #%10011000   ; 50% duty, decay disabled, volume=8
sta $4000

lda #%00001000  ; disable sweep, set it to negative mode
sta $4001

lda #$FD   ; period = $FD -- concert A (440 Hz)
sta $4002

lda #%01010000 ; high bits of period=0, set length to play for half a second
sta $4003
This should work.

How I usually approach problems like this is I look at a technical doc covering the register descriptions... then just write to every register setting everything to a specific value.


If by "short envelope time" you meant the note was cutting out early, that likely was the length counter. Both %00100xxx ($21) and %11111xxx ($FF) -- the values you were writing to the length counter reg -- are both short values. %00001xxx ($08) is the longest you can set the length counter to. Or, you could disable the length counter via $4000.5 to have it play indefinately.
the docs just leave me lost. i must read most of both blargg's and brad's yesterday. but i'm still confused on how to program them. I mean. the docs tell you registers need to be manipulated. but not the syntax needed to do that. and i haven't read a tutorial that has made that very clear either. to the point that i could look at the reference then look at a tutorial and learn how to write to that register.
Noob sticky!!
Please document this part of the NESdevWiki!! XD
YOU NEED A RETROMACHINESHOP!!

tepples
Posts: 22019
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Wed Mar 05, 2008 7:21 am

To write to a register:

lda #value
sta register address

What kind of "manipulation" do you need help with? Or is the problem just that there is no 6502 tutorial on nesdevwiki yet?

User avatar
Laserbeak43
Posts: 188
Joined: Fri Sep 21, 2007 4:31 pm
Contact:

Post by Laserbeak43 » Wed Mar 05, 2008 7:38 am

tepples wrote:To write to a register:

lda #value
sta register address

What kind of "manipulation" do you need help with? Or is the problem just that there is no 6502 tutorial on nesdevwiki yet?
lol no i wasn't sure how to load values into registers.

quick question, the number value loaded into the register determines what feature will be used?

so if #$01 loads a black hole
and #$03 loads my ninja turtles dvd
will:
lda #$03
sta #$4014
load my ninja turtle DVDs while running a black hole?
Noob sticky!!
Please document this part of the NESdevWiki!! XD
YOU NEED A RETROMACHINESHOP!!

User avatar
electro
Posts: 132
Joined: Tue Jan 29, 2008 11:12 am
Location: New York

Post by electro » Wed Mar 05, 2008 8:03 am

I hear what you're saying. Not how to load numbers in the sound registers, but which numbers. And then what effect would those numbers have on each sound register.

I have been wondering that too. It would be great to have a list of the effects that can be produced with each useful binary number on each sound register.


T

User avatar
Disch
Posts: 1849
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch » Wed Mar 05, 2008 9:08 am

I share the same confusion tepples does. There's no manipulation here other than writing values (writing = STA, STX or STYing).

The bits in the value you write set (or clear) the specific bits of those registers. The bits of those registers control what the system is doing -- so in effect, the value you write determines the behavior of the hardware.

Example:
blargg's APU doc wrote: $4000/4 ddle nnnn duty, loop env/disable length, env disable, vol/env
period
The high two bits of the value you write to $4000 set the duty.

Bit 5, when set, will disable the length counter and set the envelope unit to looop. When clear, it will enable length, and the envelope won't loop.

Bit 4 disables (when set) or enables (when clear) the envelope generator

and the low 4 bits set the fixed volume and envelope speed.


So if you want:
- 50% duty (%10xxxxxx)
- disabled length (%xx1xxxxx)
- disabled envelope (%xxx1xxxx)
- a volume level of 8 (%xxxx1000)

then you write %10111000 to $4000:

LDA #%10111000
STA $4000
Laserbeak43 wrote:quick question, the number value loaded into the register determines what feature will be used?
Yes. Whatever value you set the register to determines what the hardware does.
so if #$01 loads a black hole
and #$03 loads my ninja turtles dvd
will:
lda #$03
sta #$4014
load my ninja turtle DVDs while running a black hole?
This example doesn't make any sense. #$01 doesn't "load" anything, it's just a number. When you write that number to a register, the effect it has depends on what the register does.

$4014 is kind of tricky, because it's not really an actual register -- it's more like a CPU macro. I don't understand your whole ninja turtle/black hole metaphore but basically $4014 works like this:


low level:
writing to $4014 starts a DMA transfer. Bytes are read from $nn00 (where 'nn' is the value written to $4014) and written to $2004 (which puts that byte in OAM). So for example, if do:

LDA #$03
STA $4014

that is basically the same thing as:

Code: Select all

LDA $0300
STA $2004
LDA $0301
STA $2004
LDA $0302
STA $2004
...
LDA $03FF
STA $2004
Only much faster because the CPU doesn't have to fetch opcode and address bytes repeatedly. Plus it's much smaller code.



high level:

Writing to $4014 copies a 256 byte page to OAM. So if you write $03 to $4014, then the page at $0300-03FF gets copied in full to OAM.

User avatar
Laserbeak43
Posts: 188
Joined: Fri Sep 21, 2007 4:31 pm
Contact:

Post by Laserbeak43 » Sat Mar 29, 2008 2:23 pm

this post has been in the back of my head since your reply. i'm gonna get to it over the weekend hopefuly, thanks.
Noob sticky!!
Please document this part of the NESdevWiki!! XD
YOU NEED A RETROMACHINESHOP!!

User avatar
electro
Posts: 132
Joined: Tue Jan 29, 2008 11:12 am
Location: New York

Post by electro » Tue Apr 08, 2008 11:44 am

Difference between using AND and CMP.

I noticed that this:

Code: Select all

;Check the state of the right key 
   lda button_state 
   cmp #key_right           ; compare
   bne right_not_pressed  ; branch if not equal to zero
   jsr right_is_pressed 

right_not_pressed: 

Does the same thing that this did;

Code: Select all

;Check the state of the right key 
   lda button_state 
   and #key_right              ;mask
   beq right_not_pressed    ;branch if equals zero
   jsr right_is_pressed 

right_not_pressed: 
Is the bit of code that uses the mask and beq better, or more efficient? Or are the essentially the same thing?

Thanks,
T

Roth
Posts: 399
Joined: Wed Aug 03, 2005 3:15 pm
Contact:

Post by Roth » Tue Apr 08, 2008 12:01 pm

I'm not sure if either one is better than the other or not honestly, but I _think_ the same amount of cycles are being used in both of those snippets of code.

Post Reply