rainwarrior wrote:
NSFe deliberately removed the playback rate feature because the original spec had suggested 60.0hz instead of the real NES rate of 60.1Hz. As such, basically every NTSC NSF rip inaccurately specifies 60.0Hz. Disch thought it would be better to remove the field entirely than obey the existing field that was normally slightly inaccurate.
I've never seen a game rip that required a custom playback rate. Many NSF players don't even support this feature. (I think I saw one game rip with a 30hz rate once, but I think it should have been ripped with a small piece of code to just run every second frame at 60hz instead.) More recently people making new NSF music have been using it for musical effects, as well as other things like enabling multiple expansions at once, etc. Whether you want to support that kind of stuff is your own decision.
Thanks. I guess I'll make this an optional feature that defaults to the actual NTSC/PAL rates unless the user demands otherwise.
zeroone wrote:
However, I don't know what you mean about SMB. The first instruction in the PLAY routine is LDA $0770, which sets the Z flag. It's not relying on the prior state of Z at all?
That's a good point. I forgot that LDA does that. I'll review my issues with SMB.
zeroone wrote:
I'm also unclear what you mean about FCEUX interjecting code? If I use the debugger to step in, execution begins at INIT, or PLAY, and there's never an opportunity to see any code run that's not from the NSF itself. What are you describing with that code block? Where did it come from?
The source code of nsf.cpp found in the fceux-2.2.2.src package contains a comment at the top and a block of hex:
Code:
//mbg 7/31/06 todo - no reason this couldnt be assembled on the fly from actual asm source code. thatd be less obscure.
//here it is disassembled, for reference
/*
00:8000:8D F4 3F STA $3FF4 = #$00
00:8003:A2 FF LDX #$FF
00:8005:9A TXS
00:8006:AD F0 3F LDA $3FF0 = #$00
00:8009:F0 09 BEQ $8014
00:800B:AD F1 3F LDA $3FF1 = #$00
00:800E:AE F3 3F LDX $3FF3 = #$00
00:8011:20 00 00 JSR $0000
00:8014:A9 00 LDA #$00
00:8016:AA TAX
00:8017:A8 TAY
00:8018:20 00 00 JSR $0000
00:801B:8D F5 EF STA $EFF5 = #$FF
00:801E:90 FE BCC $801E
00:8020:8D F3 3F STA $3FF3 = #$00
00:8023:18 CLC
00:8024:90 FE BCC $8024
*/
static uint8 NSFROM[0x30+6]=
{
/* 0x00 - NMI */
0x8D,0xF4,0x3F, /* Stop play routine NMIs. */
0xA2,0xFF,0x9A, /* Initialize the stack pointer. */
0xAD,0xF0,0x3F, /* See if we need to init. */
0xF0,0x09, /* If 0, go to play routine playing. */
0xAD,0xF1,0x3F, /* Confirm and load A */
0xAE,0xF3,0x3F, /* Load X with PAL/NTSC byte */
0x20,0x00,0x00, /* JSR to init routine */
0xA9,0x00,
0xAA,
0xA8,
0x20,0x00,0x00, /* JSR to play routine */
0x8D,0xF5,0x3F, /* Start play routine NMIs. */
0x90,0xFE, /* Loopie time. */
/* 0x20 */
0x8D,0xF3,0x3F, /* Init init NMIs */
0x18,
0x90,0xFE /* Loopie time. */
};
I didn't study the source very much. I just happened to notice that at the top and I assumed that is what they did.