Recently I've been going through a bunch of NSF files from games contemporary to the Famicom/NES's lifespan and digging up their pitch tables—usually by opening the file open in a hex editor and searching for bytes or pairs of bytes that tend to come up (e.g. "00 FD" or "00 FE" for A440Hz). I'm interested in seeing what sorts of discrepancies exist among developers, or even in the music of the same developer, in the early days of the system.
After looking over doppleganger's disassembly of SMB, I was able to find the lookup table in the NSF and make some edits (changing a few notes to make the music play back in C minor instead of C major) to confirm that I was looking at the right thing. I've since been able to do the same with several other files; there have been some differences in ordering of pitches, and some developers prefer putting the most significant byte second, rather than first (David Wise, for example), but nothing too taxing to figure out. I haven't seen any examples in older titles that put all of the most significant bytes in one group and all of the least significant bytes in another, but I'm aware of that possibility.
Then I started looking at Donkey Kong 3, and I couldn't make heads or tales of it. I'd play the NSF back in NSFPlay and see everything playing back correctly—"Oh, there's the pitch 00 FE—440.4 Hz, and there it is showing up at the proper place in address space in 'Memory' mode"—but a search through the hex file didn't yield any instances of "FE" that seemed to correlate to the structures of pitch tables I had seen elsewhere. Some bytes associated with certain pitches weren't even showing up at all!
Given my *very* limited knowledge of 6502 assembly (knowledge of a few opcodes and a rudimentary understanding of program flow), in addition to some web searches I've done (which led me back to these forums for the first time in years), I'm thinking that one of a few things could be happening:
*The developers are not using a "complete" pitch table; they are only including part of an octave and doing bit-shifting or some such to calculate the other pitches
*The bit order of various pitches may be reversed in some playback engines
*There's some other means for calculating pitch that I haven't accounted for yet
Nuts and Milk and Championship Lode Runner have posed the same issues; strangely, Lode Runner uses a more "conventional" lookup table, whereas Championship Lode Runner uses some other structure (and different frequencies for the pitches themselves—00 FE, rather than 00 FD, for the A above middle C) despite being almost the exact same game.
My question, then, is this: how should I go about my search for lookup tables (or alternate means of pitch calculation) that differ from the "norm" I've seen in other NSFs so far? I know I could just open a file in NSFPlay and transcribe the hex values of pitches as they appear, but I'm interested specifically in how these things are laid out in code, and not just in the pitches themselves. I was just reading the FCEUX help files and came across the section about setting breakpoints... forgive me if I sound like an idiot for asking this, but if I run the original ROM for a game in FCEUX, set a breakpoint to watch for writes to addresses $4002/3 and $4006/7, analyze the surrounding code, and compare this to the analogous code in the NSF (which is basically just the audio portion of the original ROM data with a header at the beginning), am I likely to turn up anything useful?
After looking over doppleganger's disassembly of SMB, I was able to find the lookup table in the NSF and make some edits (changing a few notes to make the music play back in C minor instead of C major) to confirm that I was looking at the right thing. I've since been able to do the same with several other files; there have been some differences in ordering of pitches, and some developers prefer putting the most significant byte second, rather than first (David Wise, for example), but nothing too taxing to figure out. I haven't seen any examples in older titles that put all of the most significant bytes in one group and all of the least significant bytes in another, but I'm aware of that possibility.
Then I started looking at Donkey Kong 3, and I couldn't make heads or tales of it. I'd play the NSF back in NSFPlay and see everything playing back correctly—"Oh, there's the pitch 00 FE—440.4 Hz, and there it is showing up at the proper place in address space in 'Memory' mode"—but a search through the hex file didn't yield any instances of "FE" that seemed to correlate to the structures of pitch tables I had seen elsewhere. Some bytes associated with certain pitches weren't even showing up at all!
Given my *very* limited knowledge of 6502 assembly (knowledge of a few opcodes and a rudimentary understanding of program flow), in addition to some web searches I've done (which led me back to these forums for the first time in years), I'm thinking that one of a few things could be happening:
*The developers are not using a "complete" pitch table; they are only including part of an octave and doing bit-shifting or some such to calculate the other pitches
*The bit order of various pitches may be reversed in some playback engines
*There's some other means for calculating pitch that I haven't accounted for yet
Nuts and Milk and Championship Lode Runner have posed the same issues; strangely, Lode Runner uses a more "conventional" lookup table, whereas Championship Lode Runner uses some other structure (and different frequencies for the pitches themselves—00 FE, rather than 00 FD, for the A above middle C) despite being almost the exact same game.
My question, then, is this: how should I go about my search for lookup tables (or alternate means of pitch calculation) that differ from the "norm" I've seen in other NSFs so far? I know I could just open a file in NSFPlay and transcribe the hex values of pitches as they appear, but I'm interested specifically in how these things are laid out in code, and not just in the pitches themselves. I was just reading the FCEUX help files and came across the section about setting breakpoints... forgive me if I sound like an idiot for asking this, but if I run the original ROM for a game in FCEUX, set a breakpoint to watch for writes to addresses $4002/3 and $4006/7, analyze the surrounding code, and compare this to the analogous code in the NSF (which is basically just the audio portion of the original ROM data with a header at the beginning), am I likely to turn up anything useful?