I want to get a MIDI output from an NES. I don't mean those MIDI carts, I want to intercept and interpret the sound data from any cart. If anyone knows where to intercept and/or what data to look for, that would be great!
Audio registers on the NES are mapped to addresses $4000-$4017, so you'd have to monitor writes to those addresses. The
wiki documents what each register does. The APU is integrated into the same chip as the CPU though, so I don't know if the addresses and data ever appear on the external busses.
I would assume APU writes show up on the 2A03's external address bus. There's no real reason for them not to, seeing as it always drives this bus as opposed to tri-stating it.
This raises the question of how practical a VGM logging function in a PowerPak mapper would be. If so, VGM to MIDI on the PC side might be doable.
The internal data bus inside the 2A03 is isolated from the external data bus only when reading from $4015. (See Visual2A03 node 13193)
(As long as it's not a 2A03G that has been modified to connect pin 30 to something other than ground — see Visual2A03 node 10839)
Converting NES $400x writes to MIDI data is a bit involved. You need to detect note starts and note ends, and convert the frequency data:
- When a note starts, you need to output a MIDI NoteOn message ($9x kk vv, x=channel number, kk=note key number, vv=velocity), when it ends, a NoteOff message ($8x kk vv). This is easy when a game uses the APU's envelopes, but more involved when it uses software envelopes. If you want sound effects to be output right, you would also have to replicate the APU's Sweep Unit.
- You need to convert the NES' frequency data, which is basically a divisor for the main CPU clock, into note key numbers on a chromatic scale, plus Pitch Bend ($Ex ll mm) values if you want to transmit detuned notes and glissandi as well. Doing this will either require elaborate logarithmic calculations or a rather large conversion atble.
I think Marat Fayzullin's old iNES emulator could log to MIDI, or had a conversion utility to convert from a logged iNES sound format to MIDI. I don't know though if it's open-source by now or not.
Speaking of the address bus --- can a mapper chip see writes to internal CPU RAM at $0000-$07FF and react to that in some way? I suppose it could not add its own RAM, since that would require disabling the internal CPU RAM for reads to be reliable. But could it trigger an IRQ or PRG/CHR ROM switch based on, say, a write to $00EA?
NewRisingSun wrote:
Speaking of the address bus --- can a mapper chip see writes to internal CPU RAM at $0000-$07FF and react to that in some way? I suppose it could not add its own RAM, since that would require disabling the internal CPU RAM for reads to be reliable. But could it trigger an IRQ or PRG/CHR ROM switch based on, say, a write to $00EA?
Yes. (This is part of why zzo38 keeps on liking designs that just decode A15 low and A12 high)
The only thing that the CPU can see that doesn't go over the external data bus is reads from $4015—in that specific situation the buffers that relay the values from the physical pins are disabled, and the internal bus driver is active instead.
So I need to look at addresses $4000-$4017. Would I want to get those from cart pins or CPU pins and which pins would I want? (Yes I realise I might have to be reciving irrelevant data too.)
Trainmaster2 wrote:
So I need to look at addresses $4000-$4017. Would I want to get those from cart pins or CPU pins and which pins would I want? (Yes I realise I might have to be reciving irrelevant data too.)
Either. (They're connected internally)
Here's two pages on the wiki:
nesdevwiki:CPU pin out and signal descriptionnesdevwiki:Cartridge connector
Thanks for all the help so far! Am I understanding correctly thst I need to look for the address in one of the Axx pins and the data in one of the Dx pins?
Just looked a little closer. Do I use the Axx pins together to form a binary signal and do the same with the Dx pins? If so, is there a control pin to know when a signal is sent?
Theoretically, on a rising edge of M2 (or a falling edge of /ROMSEL), the address bus is stable.
On writes, the data bus from the CPU should also be stable, (but krzysiobal has evidence to the contrary, so <Shrug>)
On reads, the data bus from the external device must be stable by the time M2 falls (or /ROMSEL rises).
You're correct that "all" you need to do detect the full set of address and data pins to capture the writes to the APU registers. (Inside the 2A03, there's actually a chunk of logic that specifically detects read and writes to $4000-$401F, and that signal is then used to enable all the individual registers)
The only true MIDI output is from the Miracle Piano Teaching System game, which sends MIDI messages to the piano. And that's not done over an authentic MIDI cable.