Edit--Missed a file (git.h)
TL;DR
Find the code for the Miracle Piano for FCEUX at the bottom of this post.
TS;GMUD (Too Short; Give Me Unnecessary Details)
So, a year and a half ago, I was watching TMR (The Mexican Runner) playing the Miracle Piano as part of his goal to beat all the NES games. He apparently had two sections (07.05 and 26.07) that he couldn't complete. I thought I could try and emulate it and figure out why.
On and off for the past year and a half, I've been kicking around with the code to get it work, and tried several different MIDI APIs to do it, including FluidSynth, RTMidi, and WINMM. I'd make progress with each one and then lose interest. A couple of weeks ago, I found out that MESS/MAME had already done it.
So, long story short, I just copied the PortMIDI they were using, and then just copied in the files that were using it into FCEUX. It didn't take too much modifying to get it work.
I've successfully tested it with an actual Miracle Piano connected with a cheap USB MIDI cable (IN=OUT, OUT=IN based on my labels), a Yamaha keyboard with the same cable, and software only MIDI using Virtual Midi Piano Keyboard(VMPK) through MIDI Yoke and MIDI-OX. All three work as expected. Most of the sound (keys pressed and accompaniment/sound effects) comes from the keyboard, so make sure you route the output midi to somewhere if you want to hear anything but the metronome. I routed both the input and the output to the Windows GS Wavetable Synth to hear it when using software MIDI.
There are some caveats. The Miracle Piano doesn't use the standard instrument numbers, so when it tries to set these, they may not match (for example if the game were to try to set the instrument to a pipe organ, most keyboards would set up for a harpsichord. Sound effects similarly won't match.
This could be worked around by using a translation matrix that intercepts these commands and converts them accordingly. I didn't implement this.
I was able to beat 07.06 and 26.08 (and 07.05 and 26.07 - see below) with the Miracle Piano through the USB-Midi cable, so it works well enough to actually play.
With a working debugger, I found that 07.05 does have issues. If you play frame perfectly how it's asking you to, you will fail. Every time it changes the page, it loses time about 1/10 of a note's worth of time (6 frames). In other words, after five pages, notes on the keyboard are received half a note late to the game (about half a second). I wrote a lua script that shows timing that works. Just hit the notes when the carrot moves horizontally. You can block the distracting built-in timer by uncommenting the lines in the script.
I then hooked my Miracle Piano upped to my actual NES and played it while watching the screen on my emulator. I had to press 'A' to start the emulator a couple frames earlier than on the NES to get them to line up (a little bit of lag there-you can tell they're lined up if the emulator screen and the NES TV both flash at the same time when changing pages), but I managed to complete the section successfully on the actual NES by using the emulator's LUA script timing.
The issue with 26.07 is different. 26.08 doesn't have this issue, but on 26.07 the tied notes are not working correctly. If you play them as indicated, you will fail. Instead you should just ignore the tied half notes. This will let you pass. I took what I learned from this and managed to beat all 3 sections of 26.07 (it speeds up after each section to eventually match the speed of 26.08) on the actual NES.
I did manage to beat both 7.05 and 26.07 (all three stages of 26.07) on the emulator. There may been some minor audio/video lag, which will affect how you need to play, but I made it through eventually.
If you want to see my data/notes:
https://docs.google.com/spreadsheets/d/ ... aFyPk0QhvI
These changes are in very rough shape. I got them to work and then stopped. They need serious clean-up/improvement (or even starting over and just using this a reference) before they're ready for merging. The PortMIDI ID numbers for in and out are hard coded (there should be a configure button), and it always attempts to connect. The PortMIDI code is not as isolated as it should be from the input device code like others are. I made the bare minimum changes to the files from MAME to get it work. If anyone else wants to work on it, feel free; it did what I needed, so I'm not planning on improving it.
All the hard work for Miracle Piano was done by the MAME people (R. Belmont and Fabio Priuli I believe). Thanks go to them.
Also, the specs from Nocash were invaluable.
To use these, copy the PortMIDI files from the MAME code into FCEUX/src/drivers/win/portmidi. Build it there (at least the static build).
Then copy miraclepiano.cpp into FCEUX/src/input.
Copy git.h and the correct input.cpp into FCEUX/src.
And copy these files into FCEUX/src/drivers/win:
Midi.cpp/h, input.cpp, miracle.cpp/h, portmidi.cpp, portmidiheader.h
miracle.cpp/h and portmidi.cpp and portmidiheader.h are MAME files that have been minimally edited.
Miracle Piano is connected to Port 1 and a controller is used to control the game from Port 2.
TL;DR
Find the code for the Miracle Piano for FCEUX at the bottom of this post.
TS;GMUD (Too Short; Give Me Unnecessary Details)
So, a year and a half ago, I was watching TMR (The Mexican Runner) playing the Miracle Piano as part of his goal to beat all the NES games. He apparently had two sections (07.05 and 26.07) that he couldn't complete. I thought I could try and emulate it and figure out why.
On and off for the past year and a half, I've been kicking around with the code to get it work, and tried several different MIDI APIs to do it, including FluidSynth, RTMidi, and WINMM. I'd make progress with each one and then lose interest. A couple of weeks ago, I found out that MESS/MAME had already done it.
So, long story short, I just copied the PortMIDI they were using, and then just copied in the files that were using it into FCEUX. It didn't take too much modifying to get it work.
I've successfully tested it with an actual Miracle Piano connected with a cheap USB MIDI cable (IN=OUT, OUT=IN based on my labels), a Yamaha keyboard with the same cable, and software only MIDI using Virtual Midi Piano Keyboard(VMPK) through MIDI Yoke and MIDI-OX. All three work as expected. Most of the sound (keys pressed and accompaniment/sound effects) comes from the keyboard, so make sure you route the output midi to somewhere if you want to hear anything but the metronome. I routed both the input and the output to the Windows GS Wavetable Synth to hear it when using software MIDI.
There are some caveats. The Miracle Piano doesn't use the standard instrument numbers, so when it tries to set these, they may not match (for example if the game were to try to set the instrument to a pipe organ, most keyboards would set up for a harpsichord. Sound effects similarly won't match.
This could be worked around by using a translation matrix that intercepts these commands and converts them accordingly. I didn't implement this.
I was able to beat 07.06 and 26.08 (and 07.05 and 26.07 - see below) with the Miracle Piano through the USB-Midi cable, so it works well enough to actually play.
With a working debugger, I found that 07.05 does have issues. If you play frame perfectly how it's asking you to, you will fail. Every time it changes the page, it loses time about 1/10 of a note's worth of time (6 frames). In other words, after five pages, notes on the keyboard are received half a note late to the game (about half a second). I wrote a lua script that shows timing that works. Just hit the notes when the carrot moves horizontally. You can block the distracting built-in timer by uncommenting the lines in the script.
I then hooked my Miracle Piano upped to my actual NES and played it while watching the screen on my emulator. I had to press 'A' to start the emulator a couple frames earlier than on the NES to get them to line up (a little bit of lag there-you can tell they're lined up if the emulator screen and the NES TV both flash at the same time when changing pages), but I managed to complete the section successfully on the actual NES by using the emulator's LUA script timing.
The issue with 26.07 is different. 26.08 doesn't have this issue, but on 26.07 the tied notes are not working correctly. If you play them as indicated, you will fail. Instead you should just ignore the tied half notes. This will let you pass. I took what I learned from this and managed to beat all 3 sections of 26.07 (it speeds up after each section to eventually match the speed of 26.08) on the actual NES.
I did manage to beat both 7.05 and 26.07 (all three stages of 26.07) on the emulator. There may been some minor audio/video lag, which will affect how you need to play, but I made it through eventually.
If you want to see my data/notes:
https://docs.google.com/spreadsheets/d/ ... aFyPk0QhvI
These changes are in very rough shape. I got them to work and then stopped. They need serious clean-up/improvement (or even starting over and just using this a reference) before they're ready for merging. The PortMIDI ID numbers for in and out are hard coded (there should be a configure button), and it always attempts to connect. The PortMIDI code is not as isolated as it should be from the input device code like others are. I made the bare minimum changes to the files from MAME to get it work. If anyone else wants to work on it, feel free; it did what I needed, so I'm not planning on improving it.
All the hard work for Miracle Piano was done by the MAME people (R. Belmont and Fabio Priuli I believe). Thanks go to them.
Also, the specs from Nocash were invaluable.
To use these, copy the PortMIDI files from the MAME code into FCEUX/src/drivers/win/portmidi. Build it there (at least the static build).
Then copy miraclepiano.cpp into FCEUX/src/input.
Copy git.h and the correct input.cpp into FCEUX/src.
And copy these files into FCEUX/src/drivers/win:
Midi.cpp/h, input.cpp, miracle.cpp/h, portmidi.cpp, portmidiheader.h
miracle.cpp/h and portmidi.cpp and portmidiheader.h are MAME files that have been minimally edited.
Miracle Piano is connected to Port 1 and a controller is used to control the game from Port 2.