This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Sound test idea for future games

Sound test idea for future games
by on (#57082)
Hey. I was thinking of maybe doing one of those things that I saw in that NSF SNES rom where it displays volume and duty cycle info... Also notes, but I don't think I'd bother with that.

Would it just be a simple matter of doing something like this?

Code:
LDA $4000
AND #%00001111   'View volume
;Act accordingly
LDA $4000
AND #%11000000   'View duty cycle
ASL A
ROL A
ROL A   'Move into index and act accordingly!


I thought this might be cool for future sound tests. I just wanted to get input in advance. Thanks.

Also, what would one look at for triangle? Just if something's in $4008?

by on (#57083)
Can you read straight from the APU ports like that?

Even if you can't, your sound engine very likely stores all values to be written to the APU in temporary ports in RAM, and you could do the same thing with those. You isolate the Volume and Duty correctly.

With the Triangle, you'd AND with #%01111111 and if the result is non-zero, it's on/audible.

by on (#57086)
The only readable registers are $2002, $2004, $2007, $4015, $4016 and $4017. Reading any other registers will return you open bus.

by on (#57088)
When using the famitracker driver it's pretty straightforward. There are variables for everything declared at the beginning of driver.s (var_ch_Volume, var_ch_Dutycycle).

MetalSlime wrote:
Even if you can't, your sound engine very likely stores all values to be written to the APU in temporary ports in RAM, and you could do the same thing with those. You isolate the Volume and Duty correctly.


Yeah, and even if it doesn't store any variables (for whatever reason) you could still buffer the writes to whatever APU register you need to access.
e.g. insert this after every write to $4000:
sta var_that_holds_4000_contents



On a related note, does anyone know if there's an emulator or nsf player that can record all writes to APU registers? I've been looking to recreate/modify/investigate sound effects used in other NES games and this would help tremendously.

by on (#57090)
miau wrote:
On a related note, does anyone know if there's an emulator or nsf player that can record all writes to APU registers? I've been looking to recreate/modify/investigate sound effects used in other NES games and this would help tremendously.


I'm not aware of any but I had that same question some time ago. I almost wanted to update one of the player for doing so but gave up because of lack of time ;)

by on (#57099)
miau wrote:
On a related note, does anyone know if there's an emulator or nsf player that can record all writes to APU registers? I've been looking to recreate/modify/investigate sound effects used in other NES games and this would help tremendously.

NESICIDE1 does this...just import a ROM, create a Music object, go to the emulator, select the Music object in "APU Record" combo-box and play the emulator.

Although, it only does it at 60Hz so if there's DPCM twiddling going on it won't see that.

Pause the emulator, go back to the Music object you created and it will import the APU samples and show them. Unfortunately I didn't have enough space in the editor windows so the channel registers are all munged together and look like a 32-bit hex value.

When I port this feature over to NESICIDE2 obviously I'll try to make it more useful.

by on (#57106)
Cool, will need to try it out!

I've whipped up a Lua script for this a while ago. In FCEUX 2.1.2 you can hook writes to hardware registers, but there's no 100% reliable way to tell which value was written. Let's hope NESICIDE will do a better job. :)

by on (#57110)
I wrote that SNES NSF player. What was funny was that I wrote that visualization code on NES originally, ported it to SNES and enhanced it, then later ported it BACK to the NES. Here is a video of the lastest version of it running on NES:
http://www.youtube.com/watch?v=vC5JqM2kEKk

The trick with doing it on NES, in a general-purpose way is to replace every sound register write with a write to RAM. That way you can read it back and send it to the real sound regs at your discretion. I've also done that on existing NSFs from games by replacing the reg writes with JSR to various routines.

by on (#57111)
How would that work with first gen games which use the envelope feature?

by on (#57112)
I see. I guess using the RAM values makes perfect sense. I just thought I could read straight from the sound regs to simplify things.

I'll definitely try some stuff with this in the future. :)

Out of curiosity, was it tough to get the actual notes to appear? Did you need a bunch of lookup tables in ROM?

by on (#57116)
Dwedit wrote:
How would that work with first gen games which use the envelope feature?

The same way it does in PocketNES: software emulates the envelope feature.

by on (#57117)
tepples wrote:
Dwedit wrote:
How would that work with first gen games which use the envelope feature?

The same way it does in PocketNES: software emulates the envelope feature.


Yeah on the NSF player it emulated that in the SPC (it didn't return the emulated volume to the CPU). But I figured it was more NES descriptive to just have it say "DECAY" in the 'effects' field, while the volume bar was just ignorantly showing the decay rate as a volume setting.

by on (#57118)
Sivak wrote:
Out of curiosity, was it tough to get the actual notes to appear? Did you need a bunch of lookup tables in ROM?


Well I had kevtris help me generate a table so I could show the 'note dots' in a linear way (rather than logarithmic). I'd be happy to share those tables with you if it helps.

For the notes, I went the though notetable in NT2 and manually made a table of values that was exactly between each note. So it determines the note by starting out in the middle of that table doing a series of greater-than/less-than checks.

by on (#57139)
miau wrote:
Cool, will need to try it out!

I've whipped up a Lua script for this a while ago. In FCEUX 2.1.2 you can hook writes to hardware registers, but there's no 100% reliable way to tell which value was written. Let's hope NESICIDE will do a better job. :)


Not sure what you mean by "no 100% reliable way to tell which value was written"?

In the breakpoints engine I've implemented in nesicide2 [NOT nesicide1] you can set a "state" breakpoint on hardware registers down to the bitfields within the hardware register. You can, for example, set a breakpoint on when Square wave 1 is set to 25% duty cycle. [In human readable terms, not in machine bits/bytes].

Or, you can set a breakpoint on CPU access to the hardware registers...which is probably equivalent to the hooks of FCEUX but just not programmatically pulled out into an extendable interface such as for LUA.

by on (#57164)
NESICIDE wrote:
Not sure what you mean by "no 100% reliable way to tell which value was written"?

Well, unless I've missed something you can only read register contents in FCEUX's Lua implementation, e.g. in your hook function you can assume that the value you're looking for is always in the accumulator and read that. This works as long as music drivers use STA to write to the APU registers. But yeah, can't rely on that. ;)