Page 2 of 2

Posted: Sat Nov 20, 2010 4:30 pm
by Dwedit
If you want to unlock songs from the NSF, not only do you change the Number of Tracks byte, you also need to NOP out the code that selects track numbers from a table.

You'll often see these soon after the Init code, something like

TAX
LDA SomeTable,X

Nop it out, and you can use the real track numbers rather than how the NSF creator decided to order the tracks.

Posted: Sat Nov 20, 2010 4:55 pm
by Exploding Rabbit
I'm still learning how to use a hex editor and that sort of thing. I know how to change the number of tracks but I don't know what it means to NOP something. Where can I find more information about this "Init code" I've been hearing so much about?

Posted: Sat Nov 20, 2010 5:13 pm
by Gil-Galad
NOP is a 6502 opcode. In a hex editor, in the code you type in one or more bytes that are EA. EA is the hexadecimal number for NOP.

Look at the NSF spec for details on how to find the three addresses that you want to know and those are LOAD, INIT and PLAY.

LOAD is the start of the program or music driver.

INIT is the entry point to code where memory and data blocks are allocated and initialized.

PLAY is the main core of the music driver and it is updated often. Usually updated everytime the NMI is called in a game.

You can find the NSF spec at Kevin Horton's website http://www.kevtris.org/ .

Posted: Sat Nov 20, 2010 5:20 pm
by Dwedit
From the NSF Specifications

NSF files have a header.

Code: Select all

0008    2   WORD    (lo/hi) load address of data (8000-FFFF)
000a    2   WORD    (lo/hi) init address of data (8000-FFFF)
000c    2   WORD    (lo/hi) play address of data (8000-FFFF)
The "Load address" specifies where the first byte goes. It is designed so that NSF creators can save space by eliminating unused portions before the music code or data. But in reality, whenever it's not something like 8000 or C000, it's just plain evil. It means you need to do a lot of math to figure out what address is where in the file.
The Init Address is what the game calls to select a tune to play, so the play code can be called later.
The Play Address is what the game calls every frame to update the music.

Addresses are Least Significant Byte first, so an address of 801C would be 1C 80 in a hex editor.

Usually, the Load address is 8000, so if you want to find a file address that corresponds to a NES memory address (like 8123), you subtract 8000, and add 80 for the NSF header, so you'd get 01A3 in the file.

So let's say you want to kill the track selection code that was put onto an NSF rip. Let's say it's blaster master...
Load address is 8000
Init address is 8013
Play address is 8077

Load it up in FCEUX, set a breakpoint for 8013...
we see this...

Code: Select all

00:8013:4C A0 BF  JMP $BFA0
so it's jumping somewhere else (JMP instruction is like a GOTO)
Then we see this

Code: Select all

03:BFA0:AA        TAX
03:BFA1:BD B0 BF  LDA $BFB0,X @ $BFB0 = #$54
03:BFA4:85 E9     STA $00E9 = #$00
03:BFA6:0A        ASL
03:BFA7:4C 16 80  JMP $8016
This is the code that reads from the track remapping table.
TAX means Transfer A to X, it's like "X = A".
LDA $xxxx,X means A = what's what memory address xxxx + X.
There's also a STA $E9 in there for some reason, we'll leave that alone.
Then there's an ASL instruction, which multiplies A by 2.
Then it jumps back to 8016 (which is the address of the instruction right after that first jump)

So if you want to get rid of the relevant code, you would change the three bytes at BFA1 from BD B0 BF to EA EA EA. EA is the NOP instruction, which does nothing.

NES Memory address BFA1 is located at 4021 in the NSF file.

Note that after you take out the track remapping, the tracks may be in a strange order, some tracks are songs, some tracks are sound effects, etc.

Posted: Sat Nov 20, 2010 6:57 pm
by Exploding Rabbit
Thanks guys that is very, very helpful. I'll be sure to start playing around with it when I have some extra time.