Nes Tempo / APU Frame Counter

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
Posts: 38
Joined: Sat Apr 27, 2019 11:56 am

Nes Tempo / APU Frame Counter

Post by xamboni » Mon May 20, 2019 10:04 pm

I am getting a bit lost when trying to understand the tempo setting of the Taito audio engine I am working with. The things I have found out so far are:
  • There is a byte in the header of every channel's data which specifies speed.
    This byte is usually 0x07. When I decrement this value the corresponding channel speeds up.
    Famitracker documentation states 150 bpm is the standard on NTSC APU's.
    Sheet music states my games main song is 120 bpm so I am guessing something changed along the way to accommodate this.
    The only store I see on $4017 is 0xc0 at the .nsf's entry point.
I am not sure how to confirm beats per minute given the game's songs I can play in nosefart. It would be a great start if I knew 0x07 was 120 bpm and 0x06 increased things to 150 bpm as some of the music I am attempting to port has sheet music listing 150 bpm. Is there some math I am missing which I can use to confirm these values? For example in the notes section for both the square and triangle waves I could pinpoint their delay register values and use f = CPU / ( (16 or 32) * (t + 1)) to confirm I had things right.

Any help is appreciated or if I've missed a forum post in searching let me know.

Posts: 9417
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Nes Tempo / APU Frame Counter

Post by lidnariq » Mon May 20, 2019 10:20 pm

The standard Protracker terminology assumes 64 rows and four measures in a pattern, so one 16th note is one row. With the NTSC 60Hz timebase, and a "speed" of 6, this sets the 16th note duration to 100ms (6 ÷ 60Hz), a quarter note = 400ms, and (60 seconds/minute)÷(0.4 seconds/quarter note) = 150bpm.

Still assuming one row = one sixteenth note, you'd need a speed of 7.5 to get exactly 120bpm (120bpm = 500ms/quarter note = 125ms/sixteenth note; 125ms x 60Hz = 7.5). Some playback engines let you alternate automatically between 7 and 8; in other places I've seen the composer have a channel contain nothing but an endless stream alternating between setting the speed to 7 and 8.

Posts: 21985
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)

Re: Nes Tempo / APU Frame Counter

Post by tepples » Tue May 21, 2019 6:15 am

These are considered the "standard" tempos for sixteenth-note rows if your driver doesn't support in-between tempos:

900/5 = 180
900/6 = 150
900/7 = 128.6
900/8 = 112.5
900/9 = 100

Lidnariq is correct that some audio drivers can play at an in-between tempo, with one drawback being slightly uneven row lengths. I'm not familiar with what FamiTone2, GGSound, and classic era commercial games' drivers can and can't do tempo-wise, but Pently can hit any number of rows per minute, with a couple modes for making the tradeoff between even tempo and ability to hit all the in-between tempos.

Posts: 38
Joined: Sat Apr 27, 2019 11:56 am

Re: Nes Tempo / APU Frame Counter

Post by xamboni » Tue May 21, 2019 8:16 am

Woah, these responses were quick and great. I went straight back to the .nsf and with a few changes confirmed a few things.

Due to a table of 8 values in one of the games looping note functions I erroneously thought 0x07 was the highest possible in my first RE pass. After seeing the previous two posts I tested out 0x08/0x09 and sure enough the tempo changes in the direction expected. This is a pretty basic engine based on most of my RE observations so I am fairly confident you guys' math is spot on and sheet music I found online is at 120 for convenience.

For reference on what threw me off here is the table of values I was trying to construct a pattern from:
  • 0x103
Since some of these values were multiples of each other I thought something related to time signature was going on. Furthermore a subroutine which retrieves channel/note data gets the index into this table ready.


Post Reply