How execute a program loaded into the APU?

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
How execute a program loaded into the APU?
by on (#232967)
So I'm writing a program in python to convert NSF files into a more readable format, with the information about each sound channel at each audio frame displayed (similar to FamiTracker, but as a csv) but I ran into some issues with executing the program once it has been loaded into ram.

I've loaded the data from the file into my emulator correctly (as checked by NSFplay), and I setup all the registers according to the nsf documentation, but now I don't know how to execute the program properly. When I try, either nothing changes or it doesn't change correctly (depends on the nsf file).

I'm using py65emu, and I know it works because of this article.

What am I doing wrong? Code and test nsf linked.
Attachment:
File comment: The python script (save as .py)
nsf_reader.txt [6.04 KiB]
Downloaded 239 times

Attachment:
File comment: My test nsf. Just plays one note in the first pulse channel endlessly.
test1.nsf [5.77 KiB]
Downloaded 233 times
Re: How execute a program loaded into the APU?
by on (#232969)
If it helps as an example, here's an NSF analyzer I wrote using py65emu:
https://github.com/bbbradsmith/zensf/blob/master/nsfspider.py

Alternatively, you might try the old NSF Importer fork of Famitracker that breaks NSFs down into tracker data. You could then use the Famitracker text export to get a text file version of it. (Unfortunately the NSF Import fork was before the text export so there'd be an extra step to save and run the text exporter from a later version.)
http://rainwarrior.ca/projects/nes/nsfimport.html
Re: How execute a program loaded into the APU?
by on (#233074)
rainwarrior wrote:
If it helps as an example, here's an NSF analyzer I wrote using py65emu:
https://github.com/bbbradsmith/zensf/blob/master/nsfspider.py

Alternatively, you might try the old NSF Importer fork of Famitracker that breaks NSFs down into tracker data. You could then use the Famitracker text export to get a text file version of it. (Unfortunately the NSF Import fork was before the text export so there'd be an extra step to save and run the text exporter from a later version.)
http://rainwarrior.ca/projects/nes/nsfimport.html


Thanks! You're code and work has been a huge help!
As for zensf, I had a about the code, why can't you read at addresses $4000 - $4013 in the ram? Aren't those the addresses for the sound channels?
Re: How execute a program loaded into the APU?
by on (#233075)
Most 2A03 APU ports are write-only. Only $4015 (length counter status) is readable.
Re: How execute a program loaded into the APU?
by on (#233089)
$0000-$07FF is RAM. The APU registers don't map to RAM.
Re: How execute a program loaded into the APU?
by on (#233110)
StarCaptain524 wrote:
why can't you read at addresses $4000 - $4013 in the ram? Aren't those the addresses for the sound channels?

These addresses are not RAM, they're memory-mapped registers. The way these work is that the CPU intercepts accesses to certain special addresses and redirects them to the appropriate devices, and, in this case, the device is the APU. Read and write operations are treated separately for memory-mapped registers (e.g. the same register could even access completely different devices depending on whether you're writing or reading to/from that register), so even when reads are supported, that doesn't mean you'll get back what you wrote, you'll get whatever the device that's responding sends back.
Re: How execute a program loaded into the APU?
by on (#233948)
StarCaptain524 wrote:
why can't you read at addresses $4000 - $4013 in the ram? Aren't those the addresses for the sound channels?

Why do you want a read from $4000-$4013 after all???
Re: How execute a program loaded into the APU?
by on (#233949)
If APU registers were readable (which they aren't), then reading $4003 or $4007 would allow a program to not trigger phase reset unnecessarily during vibrato or portamento without having to use a separate variable to keep track of the last written value.