I thought I would try my hand at making this happen in a real NES ROM, and maybe even get it hacked into Zelda II. Staring by looking at Zelda II, it seems that its title screen music engine runs from a call to ROM address $18000 once per frame, and is controlled by RAM address $EA. Normal game has its own music engine entry point located at $19000.
Infidelity has hacked Zelda II to run on MMC3 already, so it seems following his changes tweaked to VRC7 should be approachable.
Disch has hacked Final Fantasy I with a FANTASTIC Namco-163 music engine. So to get things started, I decided to write a music engine similar to Disch's for VRC7. And here we are with a demo:
I wrote the score using FCEUx, which sounds considerably different than Mesen. I am thinking Mesen is probably the more accurate one... So in this case you will want to use FCEUx to listen to it. I will tweak it to sound best on a real cart eventually, which would likely to match Mesen.
- Similar music score format as Disch's
- All Pulse, Triangle, and FM channels supported
- Playing all notes at all octaves, register values in ROM tables
- score loops and gotos
- Envelopes for pulse channels via table
- Arbitrary length envelopes
- Envelopes can stop or loop back to an arbitrary index
- Constant volume for pulse and FM channels
- Vibrato for pulse channels via table of deltas
- Vibrato pulse period MSB register update using the sweep trick
- Vibratos can stop or loop back to an arbitrary index
- FM sustain enable/disable
- Pulse duty cycle
- Main program can start and stop song writing to RAM location $EA
- Snap-to notes, i.e. new frequency but envelope does not restart (not demonstrated, not found anywhere it sounds good)
Not supported yet:
- Noise channel (at all)
- Envelopes for FM channels (could be interesting)
- Vibrato for Triangle or FM channels (needed)
- Writing to the FM custom patch (needed)
- Music scores stored on additional ROM pages, will be necessary if doing multiple songs.
I wanted to share and get some feedback. I am new to writing 6502 ASM, wondering if my code could be more efficient. It is a lot of code but only small chunks of it should run at a time. I made a circular buffer for sending FM commands to the VRC7. I find that simply checking and updating the buffer provides the necessary delays -- that doesn't say much for how efficient it is. :S
I think it could be interesting to hack Zelda II with this. Personally, and I don't mean to offend anyone, I found Zelda II to be flop, with the exception of the title screen. Is anyone else interested in seeing this happen? At the very least, I think this is becoming a good FM engine.