Page 1 of 1

APU $4002

Posted: Thu Oct 25, 2018 9:11 am
by battagline
So I was curious to see if I could change the tone of the square wave by using inc and dec on $4002. I kinda expected it to either not work at all, or cycle the tone down until $4002 hit 0 then pop the tone back up as the next decrement would set it to 255 and cycle back down again. Instead it just dropped the tone once and stopped, which was not at all what I was expecting. The code is super simple, I just call this procedure when someone hits down on the gamepad:

Code: Select all

.proc tone_down
    dec $4002
    rts
.endproc
The tone up call, which does the same thing except increments $4002 is even weirder. It pops the sound up a bit then stops playing the tone.

Anyone willing to explain to me what's going on here?

Thanks

Re: APU $4002

Posted: Thu Oct 25, 2018 9:21 am
by tepples
The inc and dec instructions read an address before writing out the updated value. So do asl, lsr, rol, and ror.[1] But most audio registers are write-only. Reading a write-only address will not do what you might first expect.[2] You have to keep track of the current period in a variable in RAM, and then copy that out to $4002 and $4003 whenever it changes.


[1] As well as six unofficial instructions that combine one of those six with an ALU operation.
[2] If you're interested in what actually happens, see "Open bus behavior" on the wiki.

Re: APU $4002

Posted: Thu Oct 25, 2018 9:32 am
by battagline
tepples wrote:The inc and dec instructions read an address before writing out the updated value.
I thought that might be the case, but I guess I was expecting it to fail and not do anything. What do you get if you try and read from a write only address? Was just getting back garbage?

Thanks

Re: APU $4002

Posted: Thu Oct 25, 2018 9:39 am
by tepples
battagline wrote:What do you get if you try and read from a write only address? Was just getting back garbage?
Yes.

The 68000 waits for the memory controller to acknowledge or the read or reject it as a bus error. The 6502 does not have a concept of "bus error", instead reading whatever voltages are left over on the data bus. The exact nature of the garbage you get depends on the address you read, as I mentioned in a footnote to my previous post. The PPU returns the last value read or written on a PPU register (with bits 7-5 updated in the case of $2002), and most everything else usually returns the high byte of the effective address.

Re: APU $4002

Posted: Thu Oct 25, 2018 9:46 am
by battagline
Ok, so keeping a separate variable for the lower tone bits worked like you said it would.

Here's the working code:

Code: Select all

.proc tone_down
    lda sq1_tone_low
    sec
    sbc #1
    sta sq1_tone_low
    sta $4002

    rts
.endproc

Re: APU $4002

Posted: Thu Oct 25, 2018 2:02 pm
by unregistered
battagline wrote:Ok, so keeping a separate variable for the lower tone bits worked like you said it would.

Here's the working code:

Code: Select all

.proc tone_down
    lda sq1_tone_low
    sec
    sbc #1
    sta sq1_tone_low
    sta $4002

    rts
.endproc
If you replace the first 4 lines of tone_down with

Code: Select all

dec sq1_tone_low
lda sq1_tone_low
that should reduce the replaced code by 3 bytes and 3 2 cycles if sq1_tone_low is zeropage, I think. :)


edit: corrected mistake (see number next to strike) :)

Re: APU $4002

Posted: Thu Oct 25, 2018 2:52 pm
by battagline
unregistered wrote:If you replace the first 4 lines of tone_down with

Code: Select all

dec sq1_tone_low
lda sq1_tone_low
that should reduce the replaced code by 3 bytes and 3 2 cycles if sq1_tone_low is zeropage, I think. :)
At the moment I'm just trying to get things to work. I'll worry about optimizing once I understand what I'm doing ;-)