NSF Extensions, NSF2 and NSFe (2018)

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
NSF Extensions, NSF2 and NSFe (2018)
by on (#224172)
News:
The proposed NSF2 outlined below is now implemented in NSFPlay 2.4 beta 9, available here:
https://github.com/bbbradsmith/nsfplay/releases


Original proposal below:


So, about 8 years ago kevtris openly speculated about an "NSF 2.0" format that would update the existing NSF format with a few goals in mind:

1. Practical ways of using the IRQ and/or NMI as interrupts.
2. Track times and names, or other non-essential metadata.

I didn't want to continue that thread, as basically nothing ever came of it. Quietust made a Battletoads RIP that relied on the idea of a "non returning INIT that gets interrupted by PLAY", but I think it predated the NSF 2.0 proposal, and wasn't really relying on the whole IRQ idea, just an INIT timeout.

So... now that I'm actively working on some NSF stuff again, I like some of the ideas in that proposal, and I want to make this stuff "real" finally. Here's what I propose to do:


1. Metadata

Kevtris' proposal used the last 3 bytes of the NSF header (previously reserved as 0) to indicate the length of NSF data that follows the header. This means that any metadata appended goes right after the other data. This is good, and I don't think it even requires a version change; it's backward compatible with NSF 1. Any nonzero value in the last 3 bytes should be interpreted as a data length, and indicates the presence of non-essential metadata. (We don't really have the DISKDUDE! problem with NSFs that we did with iNES; the headers are generally very conformant in this respect.)

The other question is what the metadata should look like. Kevtris had some ideas about them, but they weren't very firm. It was some chunked format with basically whatever fields he could think of at the time. My counter to this is: we already have a chunky metadata format for NSFs, called NSFe.

NSFe was Disch's idea, implemented about 15 years ago for his NotSoFatso NSF player. It has always been very extensible (unlike NSF 1), but it never received widespread adoption. Several emulators do support it, though, and I've found a lot of use for it over the last few years. It's existing metadata formats are reasonably parsable by the 6502, IMO. (Emulators can also reuse their NSFe implementation to support both, which is helpful.)

So, in light of this, I see no reason to create a new competing metadata standard. We might as well just merge these two. There's no fundamental incompatibility between the two ideas. So, what I've decided to go with is just putting NSFe chunks (as defined by the NSFe spec) at the metadata location. This does not inclulde the "NSFE" header (unnecessary), and the "INFO"/"DATA"/"BANK" chunks that are normally mandatory in a .NSFe file must be omitted here.

To try this idea out I have implemented exactly this for my most recent beta of NSFPlay:
https://github.com/bbbradsmith/nsfplay/releases/tag/2.4b5

To additionally help test it, I've created this python tool that easily converts NSFe to this NSF + metadata format. Try it out:
https://gist.github.com/bbbradsmith/4bc17ae16b10a9be03e80addfbea5009

Edit: and for the purists, here's a python script to strip that metadata:
https://gist.github.com/bbbradsmith/e225068e750fdb32e59a191a4f6a7e45

I see no reason to increase the version number just for metadata. There is no backward compatibility issue in simply treating a value other than 0 in the last 3 bytes of the NSF header as an indicator for the presence of metadata.

Header change:
Code:
header byte $7D-7F:
    3 bytes - 24-bit size of data following header (little endian)

(Note that the appended data will become part of the ROM image on old players. NSFs should not be relying on the presence of 0 outside their data areas anyway, though, so this is generally safe, and easily fixed with explicit padding in the file.)


2. Non returning INIT, IRQ / NMI etc.

This part of kevtris' proposal was a bit more solid. I have not implemented any of it yet, but I plan to keep most of it. Here's some plans:

1.1. Non-returning INIT is a problem. We need a way to signal to the player hardware when we're done starting up and ready to receive PLAY / IRQ interruptions. (Quietust's implementaion of this is just to "time out" the INIT routine after some large number of cycles. I think GME ended up borrowing this implementation. This worked, but I think we really need an explicit non-arbitrary moment of synchronization here.)

Instead my thought is: the non-returning INIT flag means that INIT will be called twice. The first call is still required to return, but can set RAM variables to tell itself that it's the second call. (The second call does not have to return, of course, as per the point of this.) Edit: The first and second calls will have the argument Y=$80 and Y=$81 respectively to make it very easy to branch to the non-returning code.

1.2. With non-returning INIT, PLAY becomes an "interrupt" that is intended to be driven by the NMI. A hardware player with no PPU can generate an NMI externally, and the player will likely use some sort of wrapper in between NMI and PLAY but that's up to the implementation. PLAY should still RTS, not RTI. The actual timing of PLAY vs the second call of INIT will necessarily be implementation-defined. (Edit: the NMI wrapping PLAY when this feature is used implies an SEI for it that will be reverted after PLAY returns via the wrapper's RTI. This should be fine, but if using IRQ features at the same time it should be considered. Also: the wrapper should disable its own NMI during execution of PLAY to prevent re-entry.)

2.1. IRQ handling: this I want to keep exactly as kevtris proposed. $FFFE-FFFF becomes a RAM overlay, and the NSF code gets direct IRQ control through it, no intermediary. CLI/SEI is explicitly allowed, of course. The DPCM and APU IRQs are also fair game.

2.2. IRQ timer: again, I think kevtris' proposal for an additional IRQ timer is solid, but with one minor change later proposed by B00daW to change the address of its interface to avoid the "test" registers that were discovered later.

Code:
$401B - low 8 bits of 16-bit IRQ timer reload
$401C - low 8 bits of 16-bit IRQ timer reload
$401D - bit 0 controls the IRQ (0 = held in reset, continually reload timer, 1 = enable)

There's more detail about this on the wiki but basically I think the IRQ stuff is good as proposed.

3. NSF2 header change:

Code:
header byte $05:
    byte = 2 - version 2 - indicates we must interpret byte $7C.

header byte $7C:
    bit 0-3 - reserved, 0
    bit 4 - IRQ features enabled
    bit 5 - Two INIT calls, second not required to return.
    bit 6 - Disable PLAY calls (not very useful without bit 5 also set)
    bit 7 - metadata contains a critical chunk*

This is almost what was in the proposal, *except bit 7 was proposed to indicate the presence or absence of metadata. I think it was redundant for that purpose (non-zero $7D-7F already achieves this), but I think we could use it to indicate instead that there is some essential chunk in the metadata that is critical for correct playback.

This basically works like NSFe, in which any chunk FourCC starting with an uppercase letter means it must be parsed to correctly play the file. This allows the NSFe extensions to work as that format intended, and also gives appropriate places for things like, e.g. sample data chunks for new expansion sound devices that need it.

Basically the presence of the version 2 indicator should only be needed for using the non backward compatible features, which are all encapsulated be $7C. Non-essential metadata can be freely included as version 1.

(FWIW, I couldn't find any players that even checked the version number. :P)


Anyway, that's what I'm working on for this. Part 1 is already more or less implemented (see above). Part 2 will take more work, but it's on the way. If you think I've made a critical mistake somewhere, let me know before the world turns to mud.

Edit: Replaced Y init spec with $80/$81 for non-returning INIT sequence that's distinguishable from the usual default.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224196)
rainwarrior wrote:
(FWIW, I couldn't find any players that even checked the version number. :P)

Mine does! It also aborts if the last four bytes are nonzero, so I'm going to have to change that.

The only question I can think of is, what should implementations do if the second INIT does return? Probably nothing, but just for completion...
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224197)
The second INIT returning I think that could be implementation defined, but the simplest would just be to fall back to an infinite loop.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224199)
One thing to note for the non-returning INIT, is that since PLAY is NMI driven in that mode, players that are to run on an NES or Famicom will not be able to use the variable playback rate field to control its rate. (A hardware player with no PPU could have its own NMI timer, though.)

This doesn't affect PLAY without the non-returning INIT though. If you're not letting the NSF run an INIT forever you can just poll for PLAY like the PowerPak does. (The IRQ features are entirely unaffected by this.)

PLAY being NMI driven does give an NES based player a nice opportunity to poll the controller in its NMI wrapper though, so it could still have a responsive menu on e.g. a battletoads rip.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224227)
Why is calling INIT twice preferrable over having two separate functions? One for INIT and one that's expected to be called after init and to never return?
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224228)
I guess it's a debate of whenever we want to add another routine address in the metadata vs reusing resources (address). Either ways looks fine, but the "init called twice", while a bit awkward, has the advantage of being simple, is almost compatible with the existing non-returning NSFs and sidesteps the following questions:
  • Where do we locate this field, in which chunk and which offset?
  • How do we name that field?
  • What are the exact semantics of the call?
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224235)
The question of why we don't add a new routine field for this? Doesn't fit in the existing header. There's no unused bytes left. It's either break potential backward compatibility by expanding the header, or put it in metadata at the end. ...or this third option which adds ~6 bytes of a decision code at the beginning of your INIT. I think that's an easy compromise.

Actually I think I'll add "Y=0" for the first call and "Y=1" for the second, just to get rid of that need to count it internally.


The original NSF2 proposal I think was based on quietust's INIT timeout idea, which I think was partly just a way to sidestep the spec for this. In this minimal way it didn't need a separate function but...

An NSF needs an INIT some some sort before it begins playing, whether or not it's "non-returning". Making it a timeout means the NSF author needs to manage that time to make sure they don't exceed it, and the player author needs to build some sort of timeout interrupt for it (can't use IRQ because that belongs to the NSF now... maybe NMI is viable). Also means every NSF has to have that same delay regardless of how much it uses/needs. Not a good deal, IMO. Returning and calling again I think will make this a lot easier and cleaner.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224250)
I like the merge proposal very much.

While we are on the subject of updating NSF, I would like to request:
  1. A means of indicating the Namco 163 audio volume, similiar to the new submappers, or to the NSFe MIXE chunk. Or shall the MIXE chunk become part of the NSF metadata at the end?
  2. An expansion sound bit for the YM2413. It's only used by one game (a main cartridge, plus four optional dumped expansion cartridges, plus an undumped one), but so is the VRC7.
  3. An expansion sound bit for a second APU, used by a handful of games.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224252)
NewRisingSun wrote:
While we are on the subject of updating NSF, I would like to request:
  1. A means of indicating the Namco 163 audio volume, similiar to the new submappers, or to the NSFe MIXE chunk. Or shall the MIXE chunk become part of the NSF metadata at the end?
  2. An expansion sound bit for the YM2413. It's only used by one game (a main cartridge, plus four optional dumped expansion cartridges, plus an undumped one), but so is the VRC7.
  3. An expansion sound bit for a second APU, used by a handful of games.

The 'mixe' chunk is mostly specified already, I need to write a few test NSFs/ROMs to fill in some of the implementation details in NSFPlay (though it does already parse that chunk, it just doesn't have reference volumes for a few expansions, including N163 yet... next beta I'll finish it soon.) Yes with the merging of metadata this becomes a solution under NSF2 as well.

Edit: I misremembered, I believe NSFPlay 2.4b5 does implement 'mixe' for N163 already.

The YM2143 karaoke thing is on my radar, but I have a bunch of VRC7 work to do before I will think about implementing it (not much of a priority, isn't there already a VGM dump?). In theory I don't see a problem with using one of the (2 or 6) remaining expansion bits for this.

There is also YM2143-with-VRC7 interface, which some people have done with TNS carts. This I don't think would get an expansion bit, since it's mutually exclusive with the VRC7 just uses that bit plus a mandatory chunk to designate replacing the VRC7 with it. (Also related: a 'vrc7' chunk with the built-in patches of choice is another thing I will likely implement.)

You didn't mention these, but for the Moe Pro sports games expansion that needs extra sample data, I think that doesn't need an expansion bit. Since it needs a mandatory chunk for the sample data anyway an expansion bit is unnecessary. Basically anything that needs more info than a single bit shouldn't bother to waste an expansion bit, IMO.

A second APU I don't think belongs under expansion bits. It could easily be accommodated by a mandatory chunk, though. (Easiest thing that comes to mind is just embed a whole second NSF in the chunk. Inception?) Implementing it, on the other hand, will probably be an ordeal...
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224262)
rainwarrior wrote:
One thing to note for the non-returning INIT, is that since PLAY is NMI driven in that mode, players that are to run on an NES or Famicom will not be able to use the variable playback rate field to control its rate. (A hardware player with no PPU could have its own NMI timer, though.)

I was wondering about that.

Cycle-timed music engines can still use a non-returning PLAY, right?

rainwarrior wrote:
Actually I think I'll add "Y=0" for the first call and "Y=1" for the second, just to get rid of that need to count it internally.

That is an excellent idea.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224281)
Rahsennor wrote:
Cycle-timed music engines can still use a non-returning PLAY, right?

That's still a valid idiom, yes.

I'm not sure if there's much advantage to using non-returning INIT as a replacement for that. The point is to have a baseline loop that's interrupted by PLAY. (...or IRQ)

I think non-returning INIT with a PLAY that is just an RTS though would potentially give the player hardware a chance to take input, etc. in its NMI handler but that'd also put small interruptions in the sound at 60hz anyway. (It's definitely a better replacement for the "deflemask trick" though, where it's already simulating interrupting a base loop with an NMI by polling in a non-returning PLAY.)
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224287)
rainwarrior wrote:
isn't there already a VGM dump
Yes, I made it because there was no NSF support. The Karaoke cartridge puts the chip registers at $6000/$6001, but I see no reason to define the chip such that it responds to both $6000/$6001 and $9010/$9030 for the "YM2413 using VRC7 interface". One could further define that the YM2413 shall not respond at $9010/$9030 if the VRC7 bit is also set, in case somebody wants to use both chips at the same time.
rainwarrior wrote:
A second APU I don't think belongs under expansion bits. It could easily be accommodated by a mandatory chunk, though. (Easiest thing that comes to mind is just embed a whole second NSF in the chunk. Inception?) Implementing it, on the other hand, will probably be an ordeal...
You must be thinking of the arcade version of Donkey Kong 3, which has two 2A03 CPUs each with their own sound core,when you suggest a second NSF. I was thinking of the OneBus games, which have just one CPU that has a second set of APU channels. Surely an expansion bit would be practical for those.

I should mention that I would gladly volunteer to make NSFs from the games using these configurations, so you would have something to test with.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224315)
NewRisingSun wrote:
rainwarrior wrote:
isn't there already a VGM dump
Yes, I made it because there was no NSF support. The Karaoke cartridge puts the chip registers at $6000/$6001, but I see no reason to define the chip such that it responds to both $6000/$6001 and $9010/$9030 for the "YM2413 using VRC7 interface".

Yes those are two separate things. One could use an expansion bit, the other I think not.

NewRisingSun wrote:
One could further define that the YM2413 shall not respond at $9010/$9030 if the VRC7 bit is also set, in case somebody wants to use both chips at the same time.

...or did you mean "no reason not to define" above? I'd rather they just be two separate things. I don't really see any advantage in combining them. They both happen to use that chip, but are otherwise completely unrelated.

As far as multichip goes, the prevailing treatment is to ignore all audio mapper writes outside of their canonical address to prevent overlap, and disable FDS RAM. That's pretty much what the TNS hardware that runs it has to do as well. Technically the Karaoke cart itself doesn't even use the expansion audio feedback though, right? ...so whatever mix value chosen for it will be completely fictional. (I guess we could treat it as the same volume VRC7, for the purpose of consistency.)

NewRisingSun wrote:
rainwarrior wrote:
A second APU I don't think belongs under expansion bits. It could easily be accommodated by a mandatory chunk, though. (Easiest thing that comes to mind is just embed a whole second NSF in the chunk. Inception?) Implementing it, on the other hand, will probably be an ordeal...
You must be thinking of the arcade version of Donkey Kong 3, which has two 2A03 CPUs each with their own sound core,when you suggest a second NSF. I was thinking of the OneBus games, which have just one CPU that has a second set of APU channels. Surely an expansion bit would be practical for those.

Ah, I was not aware of OneBus. (How many games is this?) Sure that's a possible expansion bit I suppose. I thought you were talking about either something like DK3 or just having two synchronized NES' (which I've seen people do in the past as well), so maybe again that's a separate possibility.

NewRisingSun wrote:
I should mention that I would gladly volunteer to make NSFs from the games using these configurations, so you would have something to test with.

Sure. New expansions aren't really a priority to me and I've got a bunch of tasks that I would put ahead of this stuff, but if you make the NSFs and can point me to a good spec for emulating something, I'd be happy to implement them when I have a chance.

I could really use a YM2413 for testing though. :( I'm about to rewrite the VRC7 and 5B emulation from scratch for NSFPlay. Every expansion chip that NSFPlay implements is something I've been able to verify and test first-hand, but once we start adding new stuff this isn't true anymore...
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224317)
rainwarrior wrote:
Technically the Karaoke cart itself doesn't even use the expansion audio feedback though, right?
It does return the YM2413 audio to the Famicom's RF modulator, but it blocks audio from the 2A03, so there's ... pedantically ... a balance of +∞ dB :/
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224322)
rainwarrior wrote:
Yes those are two separate things. One could use an expansion bit, the other I think not.
Yes, keep the YM2413 at $6000/$6001 only. It makes the spec cleaner, and those few NSFs that wrote to $9010/$9030 for YM2413 (the VRC7 interface) would need to have their address writes modified. No reason to directly accomodate them --- I view them similarly to those N163 NSFs that play several octaves too low on accurate N163 audio emulators.
rainwarrior wrote:
Technically the Karaoke cart itself doesn't even use the expansion audio feedback though, right?
Right, although for multiple-chip possibilities I would not put that into the NSF spec.
rainwarrior wrote:
I was not aware of OneBus. (How many games is this?)
If you count all multicart games as separate ones, hundreds, but only twenty or so use the additional sound channel.
rainwarrior wrote:
but if you make the NSFs and can point me to a good spec for emulating something, I'd be happy to implement them when I have a chance.
Then I'll get to it. I can add preliminary support to NintendulatorNRS and provide the source. (I already took the liberty of using your FDS emulation core. ;))
rainwarrior wrote:
I could really use a YM2413 for testing though.
Technically, the Karaoke cartridge uses an unlicensed clone of the YM2413, though no sound differences have been discovered.

On a related note, I will have a request for optional even cleaner-than-original-sounding N163 emulation at some point, and can provide source code from NintendulatorNRS for that.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224395)
Sounds great! There is the case of the M50805 and the Jaleco ADPCM sample chip carts for SFX one-hits in the NSF to have expansion bits; and other known expansion audio pirate carts like City Fighter.

The sample data will need to be held within the meta-data at the end of the NSF2. It would also be good to consider a way for a hardware player to access this information from ROM or have it loaded into RAM.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224397)
B00daW wrote:
Sounds great! There is the case of the M50805 and the Jaleco ADPCM sample chip carts for SFX one-hits in the NSF to have expansion bits; and other known expansion audio pirate carts like City Fighter.

The sample data will need to be held within the meta-data at the end of the NSF2. It would also be good to consider a way for a hardware player to access this information from ROM or have it loaded into RAM.

Stuff that can't function without a sample chunk does not need to allocate an expansion bit. The presence of that sample chunk (also marked mandatory by the NSF2 byte bit 7) is enough by itself. I'm trying to avoid redundant/unnecessary allocations.

As far as hardware players go, I don't see any real impediments to that in this file format. I don't know if a PowerPak or Everdrive FPGA has enough internal RAM to handle this stuff, and probably don't have access to an extra piece of dedicated RAM, so they might never be simulate those sample playback chips. A new design certainly could do it, though, IMO.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224398)
PowerPak's FPGA has only 3KiB of internal RAM, much less than the 12 KiB in the µPD7755, (edit:) let alone the 32 KiB of the µPD7756.

A smart-assed design could probably stuff it into CHR and piggyback on PPU fetches, however. (It would have to pre-load fetches during vertical blanking, and stall the first fetches after playback starts until vertical blanking ends)

Everdrive N8's FPGA has 13 KiB.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224399)
Players are allowed to use at least the upper area of the stack page ($01F0-$01FF). From the spec:

The precise position of the stack on INIT or PLAY is not guaranteed, as the NSF player may need to use the top area of the stack for its own internal purpose. Make sure the tune does not attempt to modify $01F0-01FF directly. (Armed Dragon Villigust did, and was relocated to 2xx for its NSF.)
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224416)
All of those Jaleco with the ADPCM use different registers for sample playback. Is there a need to have them use all the different registers or can we just rip them to use one that doesn't interfere with other chips?
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224419)
Well, format wise I think it would only amount to an extra byte or two in the sample chunk to designate how it's wired. Not really a problem for emulators, at least... Since they don't need to take up a (precious?) remaining expansion bit anyway, I don't think there's too much issue here encoding that info.

Like VRC6 chose the most notable game as the standard, and the rest had to be flipped in the rip. (Actually... maybe an NSFe chunk to specify VRC6 swapping would be nice. There have been several times when I've wanted to test VRC6 NSF stuff but on the other board type.)

Though modifying stuff for a rip isn't as big a deal in .NSF as it is in .NES since these are deterministic programs with no user input. It's easy to ensure you got everything, and that there's no unexpected behaviour.

So, I dunno, I'd lean toward adding the extra desgination just because I like the idea of rips that are closer to natural. I don't really mind either way. If you're making the rips I'd say it's up to you. (Also even if it could be specified in the chunk, you could still rip them all at one address if you later decided that worked better anyway.)

...though, by the same token the Karaoke cart could be ripped to use VRC7 registers instead of requiring its own expansion bit, too. I guess that'd be not hugely different than the existing VRC6 situation (just now a mandatory chunk to indicate YM2413, which I need anyway for the TNS stuff that does this.) Maybe that would actually be better, since the NSF would be nicely compatible with the TNS thing, and also not need to take up a new expansion bit.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224587)
rainwarrior wrote:
The 'mixe' chunk is mostly specified already, I need to write a few test NSFs/ROMs to fill in some of the implementation details in NSFPlay (though it does already parse that chunk, it just doesn't have reference volumes for a few expansions, including N163 yet... next beta I'll finish it soon.) Yes with the merging of metadata this becomes a solution under NSF2 as well.

Checking my partial implementation in NSFPlay, I actually did have N163's 'mixe' fully implemented, I think. So technically this already works in NSFPlay 2.4b5, at least for N163.

Going to fill out the rest of the 'mixe' chunk defaults soon though, writing the necessary tests today.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224659)
rainwarrior wrote:
...though, by the same token the Karaoke cart could be ripped to use VRC7 registers instead of requiring its own expansion bit, too. I guess that'd be not hugely different than the existing VRC6 situation (just now a mandatory chunk to indicate YM2413, which I need anyway for the TNS stuff that does this.) Maybe that would actually be better, since the NSF would be nicely compatible with the TNS thing, and also not need to take up a new expansion bit.

Pretty sure the Karaoke cart uses "rhythm mode". VRC7 doesn't support this. Also not certain if there are channel discrepancies, since the YM2413 has more channels. Best just to support it fully. Also we should try to flesh out the K-663A differences from the YM2413. I know that some bootleg arcade machines use the K-663A as well. krzsysiobal said that there is buzz or hum on it.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224660)
B00daW wrote:
rainwarrior wrote:
...though, by the same token the Karaoke cart could be ripped to use VRC7 registers instead of requiring its own expansion bit, too. I guess that'd be not hugely different than the existing VRC6 situation (just now a mandatory chunk to indicate YM2413, which I need anyway for the TNS stuff that does this.) Maybe that would actually be better, since the NSF would be nicely compatible with the TNS thing, and also not need to take up a new expansion bit.

Pretty sure the Karaoke cart uses "rhythm mode". VRC7 doesn't support this. Also not certain if there are channel discrepancies, since the YM2413 has more channels. Best just to support it fully. Also we should try to flesh out the K-663A differences from the YM2413. I know that some bootleg arcade machines use the K-663A as well. krzsysiobal said that there is buzz or hum on it.

When I said VRC7 registers I mean the memory addresses. There will be an NSFe chunk to specify "VRC7 is actually a YM2413" to support NSFs for the TNS cart that has this.

Was suggesting that patching the write addresses in the karaoke NSF would make it completely compatible with this, and not require yet another expansion (analogous to the way we patched 2/3 of the VRC6 games to run on the other VRC6 configuration for NSF).
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224722)
rainwarrior wrote:
There will be an NSFe chunk to specify "VRC7 is actually a YM2413" to support NSFs for the TNS cart that has this.
An extra chunk indicating that a header bit doesn't mean what it's supposed to mean? Please not, that's the epitome of a hackish solution.

If anything needs patching, it's the TNS homebrew cart using a hackish way to achieve something that the NSF spec did not actually support. I still advocate using another expansion bit for YM2413 instead of using an extra chunk to redefine the VRC7 into an YM2413 (as if the YM2413 were a "kind of VRC7"). It's cleaner that way, we've got enough extra bits left in the header (two in $7B, and $7C still has four reserved bits even in NSF2), and it would also allow using YM2413 alongside a VRC7.

rainwarrior wrote:
Stuff that can't function without a sample chunk does not need to allocate an expansion bit. The presence of that sample chunk (also marked mandatory by the NSF2 byte bit 7) is enough by itself.
I agree with that.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224767)
NewRisingSun wrote:
rainwarrior wrote:
There will be an NSFe chunk to specify "VRC7 is actually a YM2413" to support NSFs for the TNS cart that has this.
An extra chunk indicating that a header bit doesn't mean what it's supposed to mean? Please not, that's the epitome of a hackish solution.

No, it's a mandatory chunk that extends and disambiguates the VRC7 bit in header. Not metadata.

NewRisingSun wrote:
If anything needs patching, it's the TNS homebrew cart

You can't patch the cart, it's hardware. It's a real NSF player cart that already implements this, and they've been making it for a while now. NSFs are already out there for it. I'm not going to create some alternative NSF spec that's incompatible with what it already is, that would defeat the point of adding support for it.

If you're complaining about whether a rip of the Karaoke cart should be remapped to this... that's a different matter entirely. A rip can be patched. Family Noraebang is not an NSF player, and doesn't relate with the NSF spec in the same way.

NSF is not like iNES at all. iNES is trying to take a pristine ROM dump and give enough information to run it. NSF has always been about modifying the dump to just play the music. Because NSF programs are deterministic this is very practical, and relatively easy to verify that the modifications were done correctly. Completely different situation. The Karaoke rip can be remapped to this with zero difference in output.

So the bottom line is: I'm implementing the VRC7 disambiguation chunk to support the TNS player method of replacing VRC7. It already works, and it's just a continuation of it. Whether or not we think the Karaoke cart deserves an entirely new expansion... maybe up for debate, but I think there's a lot of advantage to reuse this one that we've already got practical implementations of. The rip could run today on existing player hardware. Even for prospective emulators, it's less code to maintain, have bugs with, etc.

As for whether every conceivable expansion has to be made possible as a multichip, I don't agree with that. If it's convenient, fine. If it's not, I think other concerns are more important. The fact that the original 6 expansions were (eventually) made mutually compatible was more of a lucky accident than anything else. We don't have a separate expansion bit for VRC6a and VRC6b, kevtris just remapped that. Much more practical. You could build hardware that lets you stack 6 VRC6es if you want, but I'm not really going to add constraints to my plans to ensure that this is a future possibility. Show me someone actually making multichip music with Family Noraebang and maybe I'd think differently about how important this is.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224803)
That may be the case, but accurate emulation of the expansion sound hardware is why we have such vibrant chip music communities. Might as well shove the YM2413 (K-663A) in NSFPlay and quit whining, bro. :) Also, I think there's some rhythm mode in the Noraebang songs so VRC7 wouldn't work.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224804)
B00daW wrote:
Also, I think there's some rhythm mode in the Noraebang songs so VRC7 wouldn't work.
rainwarrior wrote:
When I said VRC7 registers I mean the memory addresses. There will be an NSFe chunk to specify "VRC7 is actually a YM2413" to support NSFs for the TNS cart that has this.


That said, my personal opinion is that I'd really like to stop the conflation of the YM2413 and the VRC7 ... and per plgDavid's video I didn't even know there were apparently three different versions of the OPLL, all varying just by baked-in patch set: YM2413, YMF281 ("P"), YM2423 ("X").

... it's also not clear that the defined binary interface to talk to the simulated IC has anything to do with preventing this conflation.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224806)
B00daW wrote:
That may be the case, but accurate emulation of the expansion sound hardware is why we have such vibrant chip music communities. Might as well shove the YM2413 (K-663A) in NSFPlay and quit whining, bro. :) Also, I think there's some rhythm mode in the Noraebang songs so VRC7 wouldn't work.

Read what I wrote. I'm not saying to play it back as VRC7, I'm saying to add a disambiguation byte that says which chip goes at those register locations. Basically exactly what the TNS cart that already supports YM2413 does. If you specify YM2413 you get a YM2413. YM2413 has rhythm mode.

lidnariq wrote:
That said, my personal opinion is that I'd really like to stop the conflation of the YM2413 and the VRC7

It's not conflating them, it's just using the same MMIO location to drive either one. The actual chip to use will be specified.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224812)
rainwarrior wrote:
You can't patch the cart, it's hardware.
I meant and should have written "NSF files written for the TNS cart should be patched". It bothers me to reward the TNS makers' non-standard implementation by retroactively standardizing it. It is similar to some people's opposition to supporting MMC3 ROM hacks, as well as Chinese MMC3-clone RPGs, with more than 512 KiB of PRG-ROM as Mapper 4.

But lidnariq's comment has changed my mind: if there are now four different YM2413-like chips (YM2413, YMF281, YM2423, VRC7), each with a different set of default instruments, then I would support renaming NSF header byte $7B bit 1 to from "if set, this song uses VRC7 audio" to "if set, this song uses YM2413-like audio", with the VRC7 variant being the default variant, and a mandatory chunk after the main NSF data indicating YM2413 variants other than the VRC7. This would of course accomodate files for the TNS cart as well. This is basically your plan, but the description of byte $7B bit 1 should definitely be explicitly changed then, otherwise people will start thinking that the YM2413 is a kind of VRC7, when the reverse is the case.

I have no preferences regarding the addresses at which the chip responds; make it just $9010/$9030, variant-specific addresses, or both.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#224823)
NewRisingSun wrote:
It bothers me to reward the TNS makers' non-standard implementation by retroactively standardizing it.

I'm not trying to "reward" anybody. I'm trying to avoid creating new incompatibility in the world. The TNS cart is a real NSF player with a practical way to offer a YM2413, and many of these devices were actually produced. This also conveniently already has NSFs, it's not just theoretical. I want to reuse this existing implementation instead of throwing it away with another arbitrary standard. I don't care whether it's how I would have done it or not; it's here and it works. It wasn't really just the TNS either. Multiple people have been doing experiments exchanging YM2413 for VRC7 for years, but TNS actually made a production of NSF player carts for it. I also think it makes for a succinct and practical implementation.

Similar reason why even though nobody ever used it, I want to keep almost all of kevtris' original NSF2 spec. ...or why I think it's better to keep deprecated submappers and use new numbers rather than reassign them. (As for the opposition to 7-bit MMC3 PRG in iNES mapper 4, I've never really understood that, but I don't really care to argue about it. All I cared about was oversize BNROM. ;P)

FWIW those NSFs do have to be patched with a new VRC7 disambiguation chunk, version 2, and the "mandatory chunks" bit to get it, just the code portion wouldn't need patching.

NewRisingSun wrote:
... the description of byte $7B bit 1 should definitely be explicitly changed then...

I'm not referring to the old NSF 1 specification. This is a new proposal, there is no written definition at this point.

NewRisingSun wrote:
...there are now four different YM2413-like chips (YM2413, YMF281, YM2423, VRC7)

Well, those could get an enumeration in that same disambiguation byte as well if someone wants to use them for NSF. Right now plgDavid seems to be experimenting with them, that's fine, but it doesn't need to be part of NSF yet. The spec can change when it needs to.

NewRisingSun wrote:
I have no preferences regarding the addresses at which the chip responds; make it just $9010/$9030, variant-specific addresses, or both.

Well, it was just the Family Noraebang Karaoke that would potentially move for this, and really my whole justification for that is that we can perfectly accommodate it this way without adding more encumbrance to the specs/implementation.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#225447)
As promised, here are preliminary rips for your testing purposes.

First, from a OneBus game that uses the second set of APU channels (without PCM), plus a very preliminary, unordered and unoptimized rip of Family Noraebang using the YM2413. I took the liberty of using bit 6 of the NSF header's expansion byte for OneBus. For Family Noraebang, I moved the chip writes from $6000/$6001 to $9010/$9030, but otherwise only set the VRC7 bit, because I don't fully know what that disambiguation chunk would look like.

Edit: Converted Family Noraebang's NSF header to NSF2 and added VRC7 chunk.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#225458)
Thanks. It will take me a little while to get to implement these (a lot of tasks ahead of it) but I will make use of them.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#225770)
Could you please provide a preliminary defintion for the YM2413 disambugation chunk, so I can add preliminary support to NintendulatorNRS?
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#225772)
Chunk ID: 'VRC7'
1 byte: chip type (0=VRC7, 1=YM2413, 2-255 reserved)
optional:
128 bytes internal patch set.

If using don't forget to indicate NSF2 and set the mandatory extra data bit.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#225817)
I have added support for OneBus NSFs ($7B bit $40s) as well as YM2413 (using the NSF2 VRC7 chunk) and N163 variable volumes (using the mixe chunk) to NintendulatorNRS. Other NSF2 features are not (yet?) supported, beyond the original Nintendulator's support for non-returning play routines.

I have also updated the Family Noraebang NSF in the above post, and added a mixe chunk to the existing King of Kings NSF for testing, attached. Please look at the three NSF(2) files and tell me if I applied the new features correctly, so I can begin releasing rips.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#226007)
King of Kings:
- the mixe chunk appears well formed. Sets N163 to 18.00dB.
- I would suggest keeping it as version 1 ($05) and not setting the "mandatory metadata" bit ($7C:7) so that it is allowed to fall back to default mix if that's unsupported.

Family Noraebang:
- Usage appears correct to me. (i.e. version 2 + mandatory bit implies it's not appropriate to use VRC7)
- VRC7 chunk appears well formed.

Santa Claus:
- Using bit 6 for onebus seems OK to me.
- Keeping version 1 ($05) also seems fine to me, since there is no extra data in $7C.

In general, version 2+ should indicate that $7C should be interpreted, version 1 that it should be ignored (though it should also be $00 for version 1). The rest is backward compatible with version 1, including new use of these last 2 expansion bits.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#226094)
Some questions:

1. The OneBus system is not a Famicom expansion, but a whole clone system where the extra audio hardware is inside the system, not the cartridge?

2. The OneBus has swapped duty on both of its APUs?

3. Aside from the swapped duty, does it differ from the NES APU in other ways? Length counter table? DPCM frequency? Noise frequency? Periodic noise mode? Sweep? Nonlinear mixing? Have any of these things been tested for it? (e.g. not even the MMC5 is a complete APU copy for its square channels, I can't really take any of these for granted.)

4. Does anyone know how to get either the Family Noraebang cartridge, or the OneBus system? Ebay doesn't seem to have any listings for these. I don't know where to look. Alternatively, would someone be willing to lend me these things temporarily?
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#226101)
rainwarrior wrote:
The OneBus system is not a Famicom expansion, but a whole clone system where the extra audio hardware is inside the system, not the cartridge?
That's right.
rainwarrior wrote:
The OneBus has swapped duty on both of its APUs?
The VT02 and VT03 certainly have. It's possible that later ones don't: most of the later ones are used in handhelds with a built-in speaker and no Line Out, so that the sound samples heard in YouTube videos showing them are inconclusive. The development kit for the OneBus famiclones includes the EmuVT emulator however, which does not reverse the duty cycles. I emulate it without swapped duty cycles.
rainwarrior wrote:
Aside from the swapped duty, does it differ from the NES APU in other ways? Length counter table? DPCM frequency? Noise frequency? Periodic noise mode? Sweep? Nonlinear mixing?
Attached data sheet has tables with the length counters and DPCM frequencies (page 33ff). (Annoyingly, the data sheet calls the square wave channels "rhythm".) They sound identical to a normal NES, except for the duty cycles of course, but I have not compared each value. With two output pins, one for each APU, I don't think there is nonlinear mixing.

I have no Family Noraebang cartridge unfortunately, and only one OneBus famiclone (Samuri Star Angel) which I would like to keep, as it is a plug-and play system made of of entirely original games with no cartridge slot. But there are many cheap famiclones using the VTxx chips, so maybe somebody else could spare one.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#226102)
Do we know if any of those cheap ones that run off SPI memory (like this one) have the dual APU ?
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#226103)
The VT36x model is poorly understood, as there is no data sheet publicly available for it, but I have seen no evidence that V.R.T. removed the second APU.

(Edit) I suppose there is no danger in trying out the 101-in-1 (AT-103) multicart ROM on it, which uses the second APU for its menu music. It's likely that the screen will remain black, however, because of the lack of display-specific initialization code. If anybody writes his own test ROM, note that the second APU must be enabled first by setting the correct bit in register $4030.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235229)
Alright, the full proposed NSF2 I outlined in the OP is now implemented in NSFPlay 2.4 beta 9, available here:
https://github.com/bbbradsmith/nsfplay/releases

I made 3 test NSFs to demonstrate the features:
https://github.com/bbbradsmith/nes-audio-tests

One thing that I think I forgot to state in OP is that because "non-returning INIT" implies that PLAY will come from an NMI wrapper, this means that PLAY will implicitly have the I flag set when being used with non-returning INIT. This has consequences if trying to use the IRQ and non-returning INIT features at the same time (though probably easy to understand as long as you're aware that this will happen). This also means that the vector overlay for IRQ should actually extend down to $FFFA so that the player can also control the NMI. (Only $FFFE needs to be writable by the user/NSF though.)

I'll write this up on the Wiki very soon.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235248)
I love your plugin. :) Thanks for all your work on it. Three comments, if I may:
  1. The Family Noraebang NSF is still not loaded, with the error message being "Not an NSF file". Is that as it should be?
  2. I am having the problem with the WinAmp plugin that the settings are not saved to in_yansf.ini, even though both the folder and the file are write-enabled and have all security settings set to allow non-administrator access. What might I be doing wrong? I had to edit the file by hand to change settings, and had to resort to trial-and-error to find out which one of the APU1_OPTIONx and APU2_OPTIONx corresponded to disabling non-linear mixing.
  3. Also, I would like to request a high-quality N163 mode. Right now, it offers serial multiplex mixing (as on the original chip), which is disabled by default. But the "disabled" setting still sounds rather grungy, like serial mixing but just with an additional low-pass filter on top. In NintendulatorNRS, I offer "better-than-original" mixing using the following code:
Code:
uint8_t ChipRAM[128];
uint8_t CurrentChannel;   // Current channel being serviced
uint8_t   PhaseMSB[8];   // Eight more bits of phase position per channel for "clean" rendering.

int   GenerateWaveClean (int Cycles, int ChannelOffset, int ChannelNum) {
   int Channels = (ChipRAM[0x7F] >>4)+1;
   int Phase    = (PhaseMSB[ChannelNum] <<24) | (ChipRAM[ChannelOffset +5] <<16) | (ChipRAM[ChannelOffset+3] <<8) | ChipRAM[ChannelOffset+1];
   int Freq     = ((ChipRAM[ChannelOffset +4] &3) <<16) | (ChipRAM[ChannelOffset+2] <<8) | (ChipRAM[ChannelOffset+0]);
   int Length   = 256 -(ChipRAM[ChannelOffset +4] &0xFC);
   int Offset   = ChipRAM[ChannelOffset +6];
   int Volume   = ChipRAM[ChannelOffset +7] &0xF;
   
   while (Cycles--)
      Phase =(Phase +Freq) % (Length *(65536 *15 *Channels));

   int sample=(Phase /(65536 *15 *Channels) + Offset) &0xFF;
   int output= (ChipRAM[sample >>1] >>((sample&1)<<2)) &0x0F;
   
   // update Phase
   PhaseMSB[ChannelNum      ] =(Phase >>24) &0xFF;
   ChipRAM [ChannelOffset +5] =(Phase >>16) &0xFF;
   ChipRAM [ChannelOffset +3] =(Phase >> 8) &0xFF;
   ChipRAM [ChannelOffset +1] =(Phase >> 0) &0xFF;
   return (output -8) *Volume;
}

int   MAPINT   GetClean (int Cycles) {
   int out =0;
   for (int Cycle =0; Cycle <Cycles; Cycle++)
      for (CurrentChannel =(~ChipRAM[0x7F] >>4) &7; CurrentChannel <=7; CurrentChannel++)
         out += GenerateWaveClean(1, CurrentChannel*8 +0x40, CurrentChannel);
   return out *128 /Cycles / ((ChipRAM[0x7F] >>4)+1);
}
... with "GetClean" being the routine that is called for sound generation, and "Cycles" meaning 1.78 MHz CPU M2 cycles. As you can see, high-quality generation requires more bits of the phase position, which has to be stored outside the N163's normal chip RAM.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235259)
NewRisingSun wrote:
The Family Noraebang NSF is still not loaded, with the error message being "Not an NSF file". Is that as it should be?

I have not implemented the VRC7 chunk, so it is (correctly) unable to play the file. It's on my to-do list, but YM2413 support is behind a larger task of rewriting the VRC7 emulation. I'm still in the research phase of this.

NewRisingSun wrote:
I am having the problem with the WinAmp plugin that the settings are not saved to in_yansf.ini, even though both the folder and the file are write-enabled and have all security settings set to allow non-administrator access. What might I be doing wrong? I had to edit the file by hand to change settings, and had to resort to trial-and-error to find out which one of the APU1_OPTIONx and APU2_OPTIONx corresponded to disabling non-linear mixing.

Hm, I do see this problem happening with Winamp installed to Program Files. I am unable to duplicate the problem with a portable version of Winamp though, or the stand-alone NSFPlay (which is also portable), where it seems to work correctly. I would assume this is a matter of administrator access not being granted to the DLL to write to Program Files, but you have claimed that it should have the right. Where is your plugin located?

I suspect the real solution here would be to save it to appdata. This was just how it was done in the original version of NSFPlay and has never changed over the years. I think I'd still want a portable app to save it next to the application though. I'll try to figure out an appropriate way to make it handle both methods gracefully if I can.

NewRisingSun wrote:
Also, I would like to request a high-quality N163 mode.

Actually already on my to-do list. Funnily enough the original N163 implementation in NSFPlay had accidentally run it at 3x the real samplerate, just due to lack of knowledge about the chip. Several years ago when a lot of the specific details about the chip were finally researched, I corrected this with a new implementation that uses its authentic samplerate, but I do miss the "enhanced" sound it used to have.

NewRisingSun wrote:
had to resort to trial-and-error to find out which one of the APU1_OPTIONx and APU2_OPTIONx corresponded to

Yeah, I never liked the way that was structured, though I don't think I will change this until NSFPlay 3.0, which will be a fundamental rewrite. I want to "finish" NSFPlay 2 with a rewrite of 5B and VRC7, and a few other things that seem reasonable to fit in along with it (NSF2 was a long held goal) but the code is more than 15 years old and has a lot of architectural resistance to a lot of things I'd like to do (e.g. cross platform support). So... config overhaul is something I want to do, but proobably not in NSFPlay 2.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235260)
rainwarrior wrote:
I have not implemented the VRC7 chunk, so it is (correctly) unable to play the file.
It seemed to me that it's complaining because of the version number in the header though, not because of the VRC7 chunk. I base on this on the observation that changing the version number byte to 0x01 loads the file, just plays it incorrectly with VRC7 instead of YM2413, which is what I had expected.
rainwarrior wrote:
Hm, I do see this problem happening with Winamp installed to Program Files.
I do have installed it into Program Files, though I have set all the NTFS permissions of the plugins subfolder to allow my normal user account full r/w access, so I thought that would be enough. But yes, AppData probably seems to be the safer choice, given that WinAmp itself puts its configuration there.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235275)
NewRisingSun wrote:
rainwarrior wrote:
I have not implemented the VRC7 chunk, so it is (correctly) unable to play the file.
It seemed to me that it's complaining because of the version number in the header though, not because of the VRC7 chunk. I base on this on the observation that changing the version number byte to 0x01 loads the file, just plays it incorrectly with VRC7 instead of YM2413, which is what I had expected.

The header you put on it is correct. It goes like this:

Version 2 = intepret $7C
$7C bit 7 = there is a mandatory (uppercase) chunk in the NSFe suffix
'VRC7' chunk is currently unknown by the player

If you set it to version 1, it ignores byte $7C, so even though it will parse the NSFe suffix it will not consider anything in the stuffix to be mandatory, so it will load despite the unknown chunk.

Sorry there isn't any descriptive information about why a file fails to load. That's another thing on my to-do list, along with other NSF validation tools. The only way to determine how it's failing currently is by using a debugger on the loading.


Maybe better behaviour, besides just reporting the error better, would be to play it anyway. The header correctly makes it clear that there's something important in the suffix without which this NSF can't be played properly, though. Like some visible warning but an attempted play would probably be better than refusing it outright, but that's more thought in the validation tools category I guess.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235286)
I've finished updating the wiki with the specification.
http://wiki.nesdev.com/w/index.php/NSF2
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235294)
So byte $7C bit 7 is now described as "if set, the appended NSFe metadata may contain a mandatory chunk required for playback". Before that, it was just "if set, a metadata block follows the NSF data". I understand this to mean that I need to change all my Namco 163 .NSF files with the mixe chunk to clear bit 7, because the mixe chunk is not a "required chunk". Is that correct?
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235296)
NewRisingSun wrote:
So byte $7C bit 7 is now described as "if set, the appended NSFe metadata may contain a mandatory chunk required for playback". Before that, it was just "if set, a metadata block follows the NSF data". I understand this to mean that I need to change all my Namco 163 .NSF files with the mixe chunk to clear bit 7, because the mixe chunk is not a "required chunk". Is that correct?

Sorry, but there is no "before", but I realize it was confusing that someone put it up there on the Wiki for so long. That spec was never implemented by anybody anywhere, and there was no firm definition ever given for the metadata it referred to. When I defined it as referring to NSFe metadata in this thread, I outlined the same usage as it has now.

However, yes, I don't think bit 7 should be set for N163 mixing, but if you set bit 7 and then don't add any allcaps fourCC chunks it will have no effect. 'mixe' being lowercase doesn't count as mandatory, in the same way that, e.g. 'tlbl' doesn't count as mandatory. So... you can change them if you want, but it doesn't actually have an effect unless you used an allcaps fourCC for something in there.

NewRisingSun wrote:
I am not happy with the statement "The older NSF1 had no specification for string encoding. UTF-8 is the standard for NSF2, but for backward compatibility only ASCII should be used". It allows but discourages the use of Kanji and Hanzi characters, so I either have to renounce backward compatibility, or never use Chinese or Japanese characters.

I don't see how I could say anything else about this. Old players use native codepage, so ASCII is the only option for backward compatibility. I'm not happy about it either, but it's still the truth.

To clarify, though, I added to that line: "...should be used for the fields in the header. An NSFe 'auth' chunk can be used to override the header's title/author/copyright with UTF-8 strings."

All NSFe fields are explicitly UTF-8 encoded, this was assumed some years ago (since all existing NSFe up to that point were ASCII, mostly due to NSFe being an obscure format), though I'm not sure if any existing player actually supports it. NSFPlay doesn't support UTF-8 yet, it is non-compilant in that respect, and unfortunately that's not going to change until NSFPlay 3 with a complete rewrite of the UI. (NotSoFatso, where NSFe came from is way too old of a program to have had UTF-8 in it.)

NewRisingSun wrote:
define "foreign script" text fields (ftex for text flbl for tlbl, ftau for taut, faut for auth), that are explicitly UTF-8-encoded and contain the same content but in the original script. For example, auth would contain in its first string "Zelda no Densetsu", while faut would contain "ゼルダの伝説". This is the way things are handled in the .VGM format's [url]GD3 tag[/url] --- both a Latin and a "Japanese" field (the latter also used for Chinese and Korean script), with the player allowing the user to switch between the display of the two, and it has worked very well for them. (This also implies that only the NSFe chunks could have non-latin characters.)

I never liked VGM's explicit preference for Japanese, but sure, multiple language set chunks are a possibility, maybe with a 16-bit enum to specify which language at the start of the chunk?

This isn't something I'm prepared to work on until I am also ready to support UTF-8 properly. It also really needs playlist UI to be able to support it, and that's planned, just not in the immediate future. So... it's something I will keep in mind when I get around to designing that.

FWIW the NSFe spec is pretty easy-going because of the chunks. At least adding new stuff doesn't tend to break old things or compete for the same space as other stuff. However, people aren't really even using NSFe that much yet. I am hoping my merging it into NSF will help increase its popularity though. Some others seemed to be providing the metadata through M3U playlists and stuff like that instead of using NSFe. If something starts supporting other chunks in the mean time, at least if they're non-mandatory they'll still play. If someone implements new stuff ahead of me I'll catch up to it eventually.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235297)
Here's a thought, though, instead of defining new chunks for different languages...

Maybe just a 'lang' chunk that contains a single utf-8 string for the language name, and this sets a language group that all subsequent text chunks will belong to. (Order is already important for some existing chunks, so it doesn't seem too out of line with the existing stuff to me.)

So you could have 'lang' 'tlbl' 'lang' 'tlbl' and that would create 2 different 'tlbl' sets belonging to each language.

It also works for just clarifying what language a single-language NSFe is using. (Otherwise I guess it gets assigned to an unspecified/default text group.)


If there's a preferred language, I would guess that it would be best to put it last, for the sake of older players... depends on whether a second tlbl will replace an earlier one or be ignored, but I expect the latter behaviour would be more compatible. (I don't really know of many NSFe players anyway.) Should check later and see what happens with NotSoFatso.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235306)
Not languages, scripts. "Zelda no Densetsu" and "ゼルダの伝説" are the same language, one in romanized script, one in original script. That would limit us to only two cases that need to be distinguished. One can indeed use the same NSFe text fields twice with some kind of distinguishing tag, or "switching chunk", in-between, as you proposed, or one could use a second set of chunks, which was my idea.

A third possibility, which I would also like very much, would be to put both in the same field and include some form of in-field separator, for example a pipe character (|) such as "Zelda no Densetsu|ゼルダの伝説". Romanized text would go before, original script text would go after, the separator. No extra fields or chunks would be necessary, and it would backward-compatible in the sense that legacy software would simply display the entire string with the pipe character, while separator-aware software would offer the user an option to indicate a preference for romanized or original script forms; strings without a pipe character would be displayed in their entirety as before.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235313)
Also, I noticed something odd: on NSF1 files, or NSF2 files with $7C bit 5 not set, the first few milliseconds of a file are cut off in the sound output. Setting the version number to $02 and setting $7C bit 5 to 1 makes them no longer cut off. I have attached both files; just listen to the beginning of the first song.
Attachment:
CutoffComparison.7z [4.77 KiB]
Downloaded 185 times
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235335)
NewRisingSun wrote:
Not languages, scripts. "Zelda no Densetsu" and "ゼルダの伝説" are the same language, one in romanized script, one in original script. That would limit us to only two cases that need to be distinguished. One can indeed use the same NSFe text fields twice with some kind of distinguishing tag, or "switching chunk", in-between, as you proposed, or one could use a second set of chunks, which was my idea.

I think having multiple languages is a valid need, though. Two scripts for the same language can fit into this too, but I don't think that should be the only thing serviced.

What about a file containing...
Code:
'lang' 'Japanese' 'tlbl' ...
'lang' '日本語' 'tlbl' ...
'lang' 'English' 'tlbl' ...

That could accommodate both needs. The ripper can include as many languages and scripts as they want.

NewRisingSun wrote:
both in the same field and include some form of in-field separator ... backward-compatible in the sense that legacy software would simply display the entire string with the pipe character

I think that would be backward compatible only in a very awkward way, like just technically readable I guess. I'd assume that a player subject to backward compatibility here probably doesn't have unicode support anyway, so this would also dump a bunch of mojibake into their fields.

I don't think backward compatibility is super critical for this feature anyway. The number of affected players is so small. It'd be nice if it's reasonable to do, but maybe not a big deal either way?

NewRisingSun wrote:
separator-aware software would offer the user an option to indicate a preference for romanized or original script forms

Having a language preference would apply to any implementation of this, but yes this necessitates having a standardized set of language designators, and allowing the user to rank languages by descriptor.

An English default ranking might have { 'English', 'Japanese' }.
A Japanese default ranking might have { '日本語', 'Japanese' }.

Anything not on the list would just fall back to file's default order. At least, that's how I imagine I'd want to make this preference look to the user in NSFPlay.

On the format side, we just need to keep a list of the language designators people are using on the Wiki. My suggestion to use a single string to designate it was that the string can be displayed to the user, and the player program doesn't really have to know anything about languages, just unicode.

Finally a specified default order would either prefer the firstmost or lastmost language as a fallback where the user doesn't have a preference that applies. (I was suggesting lastmost because that would offer a backward compatibility fallback for NSFPlay, but I need to test NotSoFatso and Mesen and any other current NSFe players.)

NewRisingSun wrote:
Also, I noticed something odd: on NSF1 files, or NSF2 files with $7C bit 5 not set, the first few milliseconds of a file are cut off in the sound output. Setting the version number to $02 and setting $7C bit 5 to 1 makes them no longer cut off.

When you set that bit, INIT is called twice.

In this case you get a sequence of:
  • INIT #1 sets a byte at $F0 to restart the song at next PLAY.
  • NMI is enabled.
  • INIT #2 begins but is immediately interrupted by NMI
  • PLAY #1 begins.
  • INIT #2 resumes, sets $F0 again.
  • PLAY #2 begins, restarts the song.

You can't just enable non-returning INIT on old rips, you need to write a two-stage INIT suitable for this feature.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235337)
ISO 15924 defines four-character codes for scripts. In an IETF language tag, an ISO 15924 script code can be used after a two- or three-character language code from ISO 639. Some examples:

  • English written with Latin characters is en-Latn
  • Croatian (Serbo-Croatian written with Latin characters) is sr-Latn
  • Serbian (Serbo-Croatian written with Latin characters) is sr-Cyrl
  • Japanese is ja-Jpan
  • Japanese without kanji is ja-Hrkt
  • Romanized Japanese is ja-Latn
  • Simplified Chinese is zh-Hans
  • Traditional Chinese is zh-Hant
  • Chinese Pinyin is zh-Latn
  • Chinese Zhuyin is zh-Bopo

Use of these codes would save a parser from having to treat "Japanese" and "Japonais" as equivalent codes.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235339)
I strongly feel that that is not problem worth encumbering a player with having to implement this massive ISO spec.

Those codes aren't human readable. They're maybe human guessable, but at the very least the player would have to provide a big list of strings to map these technical codes to a more suitable language name to show the user. Then of course you'd ask them to do it in every possible language. Maybe there's a library that does this... but then you're asking the player to depend on a library...

...to solve an insignificant problem. Just let the ripper put the language name in the file, show that name to the user. Simple. We're not the unicode consortium here, we're just annotating some video game music files.

If you wanna bikeshed about the best name for a language/script combo, go ahead I guess, but I'm just trying to implement a player and format, and this ISO spec does not belong here. Rippers who want to make multi-language NSFe annotations can collectively decide on language strings to use, I don't need to participate in this.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235354)
HA HA HA so after checking every NSFe player I could find (there were a few more than I expected), all but one of them will replace 'auth'/'tlbl' when the chunk is reached, so last one prevails...

...but unfortunately the one player that does something different is NotSoFatso, and what it does is fail the whole file if a second 'auth'/'tlbl' is found! If it was a more obscure player I'd maybe not care, but NotSoFatso is the original NSFe player, and I don't think I should go against it.

So... can't just reuse 'auth' or 'tlbl'. Multiples of these produce an invalid ffile. The other text chunks ('taut', 'text') are newer than NotSoFatso and AFAIK NSFPlay is the only player that listens for them, so they aren't a problem if duplicated. (I don't know if anyone has ever used them in an NSFe except me.)

We're back to having new chunks for additional 'auth' or 'tlbl' at least. This does mean that 'auth' and 'tlbl' will specify the default language set, so I guess that question is answered. Might as well just say that the first language set is the default, and that it should use 'auth'/'tlbl' and not 'autx'/'tlbx' for that first one. While 'taut'/'text' don't technically need a new chunk ('taux','texx'?) the might as well get equivalent ones anyway. In a parser they can probably be easy aliases to implement. I guess it should also be specified that 'auth'/'tlbl'/'taut'/'text' must all belong to the same language group, and be the first language group, whether named by a preceding 'lang' or not.

Otherwise, I still favour a language/script state chunk ('lang') as described above, since this can optionally add a language descriptor to the default set too, and avoids having to add extra information to the other text chunks.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235356)
rainwarrior wrote:
You can't just enable non-returning INIT on old rips, you need to write a two-stage INIT suitable for this feature.
Explain (again) what the point of the double-init is? That means I definitely have to write a different INIT routine for NSF1 and NSF2, which is a bit annoying.

rainwarrior wrote:
When you set that bit, INIT is called twice.
Okay, but why are the initial milliseconds cut off (on all files)? I find that sounding quite objectionable.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235357)
NewRisingSun wrote:
rainwarrior wrote:
You can't just enable non-returning INIT on old rips, you need to write a two-stage INIT suitable for this feature.
Explain (again) what the point of the double-init is? That means I definitely have to write a different INIT routine for NSF1 and NSF2, which is a bit annoying.

The end of the first INIT is to give the player a signal that it is ready to begin PLAY (i.e. turn on NMI). The point is that from the second INIT you don't have to return. The proposal was for modelling things like Battletoads' intro where it loops samples in the main thread, but interrupts with music playback via NMI.

Of course, between the time it was proposed and now someone found a better way to support Battletoads (though not all NSF1 players support it):
https://forums.nesdev.com/viewtopic.php?p=198697#p198697

Battletoads itself is just one example, though. This has other uses. But... if you don't need this, you shouldn't use the flag. It is not backward compatible, it's a whole new behaviour that is entirely optional. There is no reason to write two different INIT routines.

NewRisingSun wrote:
rainwarrior wrote:
When you set that bit, INIT is called twice.
Okay, but why are the initial milliseconds cut off? I find that sounding quite objectionable.

Nothing is cut off. In the example you gave the song is restarted one frame after beginning. If you compare you will see that the restarted song is playing at a one frame delay, after the initial first frame is messed up by the restart.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235358)
Yes, it is cut off, on a all files. Let me post a few examples (later).
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235359)
From the original NSF file (not the NSF2 hack). First is NintendulatorNRS, second ins NSFPlug. Notice how the initial parts of the square wave envelope are cut off in NSFPlug.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235361)
Okay, so this isn't a report at all about the non-returning INIT flag.

I'll look into what you're describing. If something is being cutoff, I would assume it applies to all NSFs played. Is this something new in this version of NSFPlay, or always?

You've mentioned NintendulatorNRS a few times, but I am having trouble finding any information about it. Where is it kept, and is its source code available?
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235363)
Yes, I initially misattributed it to the init issue, but now noticed that it is a separate issue. I will have to check previous versions of NSFPlug tonight.

NintendulatorNRS is my fork of Nintendulator. I originally just added support for a few more mappers, but over time, the changes have become so numerous that it has become a fork. There is no official release yet, I only post builds when we dump a game that uses a new mapper. Source is available... from me, until I make an official release.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235368)
Thanks for noticing that. It was a new bug I introduced with 2.4b9, and I've now committed a fix. I'll post a beta 10 build soon to correct this, since this is a bad bug IMO.

If you want to know the specific details: in the first frame, PLAY was getting called, then getting called again immediately as soon as returns. So both frames worth of PLAY were executed, but the first one wasn't being given much time to make sound.

Edit: fixed in 2.4 beta 10
https://github.com/bbbradsmith/nsfplay/releases
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235369)
Thank-you.

I understand now how it works, but am still having trouble applying this to concrete cases. Take the recently-posted Skate or Die! 2 rerip NSF, for example. Most songs, including the title screen, have a normal returning Init/Play combination, but a few are just speech samples that apparently play the full sample in init, and do not play correctly in most players. What is is the correct set-up for these in NSF2?
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235371)
NewRisingSun wrote:
I understand now how it works, but am still having trouble applying this to concrete cases. Take the recently-posted Skate or Die! 2 rerip NSF, for example. Most songs, including the title screen, have a normal returning Init/Play combination, but a few are just speech samples that apparently play the full sample in init, and do not play correctly in most players. What is is the correct set-up for these in NSF2?

I'm not sure what that Skate or Die rip is supposed to do. What player does it actually work in?

The non-returning INIT process might be used for Skate or Die samples like this:
  • INIT #1 you set up everything that needs to be set up. As soon as you return from this, the PLAY routine is going to start getting called at 60Hz.
  • INIT #2 this can play samples in a locked loop and never return (make sure it was ready after INIT #1), PLAY will interrupt it to do whatever PLAY needs to do.

A long time ago quietust made a hack experiment for "non returning INIT" which was done by just timing out INIT after some arbitrary number of cycles had passed. This was used to create a Battletoads rip that did more or less that, an INIT representing a main thread sample player, and PLAY representing a periodic interruption (i.e. NMI) to handle the other music and triggering new samples.

The hacky part was making it an arbitrary timeout. That's what I was attempting to resolve with the 2 INIT calls. The length shouldn't be arbitrary, the NSF should be able to clearly signal when it's ready to begin. I think only 2 players ever implemented this (Nintendulator and GME/GEP).

So... in NSF2 you could do it this way with the non-returning INIT, though you could also turn it upside down and play samples from an IRQ instead. You'd probably want to use whichever will reproduce the original game more faithfully. The IRQ can be used for a bunch of other things, like Blargg made a DPCM IRQ saw wave. You could also combine IRQs with the non-returning INIT and a lot of the utility here is just providing access to NMI and IRQ timing like you would in an NES ROM (...no PPU or controller though).

The other thing that this helps is situations where a non-returning PLAY was used for sample playback (SuperNSF, Deflemask, MUSE Tracker). This would play in most NSF players, and even in hardware players, but in hardware players it left the player program with no way to respond to user input. You'd start a track and it would keep playing until you reset. No way to have more than one track, and it was pretty inconvenient. Using an IRQ instead, or using a non-returning INIT both give a hardware player a place to take input again, and could allow this kind of technique without that problem.

So... that's some of the reasons why Kevtris had proposed NSF2 several years ago, and reasons why people have been bringing it up since then.

Like the other Battletoads rip I linked a couple posts back, this uses the "deflemask" technique of non-returning PLAY. This worked in many more players than quietust's hack did, and you could even play the first track on a PowerPak. However, if you wanted to switch tracks on a PowerPak... that's still out of reach for this. Doing that will require NSF2 for PowerPak.


Edit: found a working link for Blargg's saw test
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235372)
I only got it to play correctly in FCEUX.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235373)
Oh, okay. That Skate or Die 2 rip is using the PPU to generate an NMI (i.e. writes to $2000).

That's... exactly the kind of thing NSF2 was designed to make possible. (Except you're still not allowed to write to the PPU. NMI is provided for you.)

Edit: As an experiment I decided to turn it into a valid NSF2 rip in that thread.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235415)
Now that I see it in action, I am thinking that one could increase the compatibility of such NSF2s by changing the spec to call for Y having the values $80 and $81 instead of $00 and $01. That would tell the init routine that the player does support that feature and act accordingly, while any other value would indicate that the player does not support the feature, and the init routine can then act like NSF(1). So in that file, instead of
Code:
   CPY #1
   BEQ L1
   RTS
L1:
   JMP $D017
one would have:
Code:
   CPY #$80
   BNE L1
   RTS
L1:
   JMP $D017
and be compatible with both NSF(1) and NSF2 players.

Apart from that, good job fixing that file. I had yesterday posted my own attempt at fixing it, but deleted it once I learned that I did not implement the non-returning init feature correctly.

Edit: I have tried NSFPlug beta 10, and the beginnings now play perfectly. Thank-you for correcting this.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235464)
I like that idea. Gives the option to try to provide a fallback if you want one.

Y on entry to INIT wasn't guaranteed to be anything in NSF1, so there's no guarantee that players aren't using $80 or even a consistent value, but I do think most players probably do use 0, and at any rate $80 is much less likely to be used than 0. PowerPak's NSF player source looks like it will enter INIT with Y=3.

Gotta update the beta and that Skate or Die 2 test, but I will do that soon.

Edit: Beta updated to version 11.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235576)
Just to follow up, wrote a simple NSF to play an 8 bit beep to let me know what players use for Y on init:
https://github.com/bbbradsmith/nes-audio-tests/blob/master/build/nsf_init_y.nsf

NSFPlay: 0
PowerPak: 3
Mesen: $0F
VirtuaNSF1060: 0
Foo_gep: 0
VLC: 0
Nestopia: 0
Nintendulator: $0F
VirtuaNES097e: 0
FCEUX: 0
NotSoFatso: $CD (default) or 0 (user setting)
NEZPlug++: 0
G-NSF: 0

I'll keep checking others, but so far $80 seems safe.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235730)
Found a working link for Blargg's DPCM saw test. This is a candidate for NSF2 features. I might try porting it at some point, if nobody else does:
http://blargg.8bitalley.com/misc/nes-saw/
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235860)
NSFPlay 2.4 beta 12 adds some better error messages about NSFe files that fail to load, and also cleans up some of the IRQ/DPCM implementation (better CPU synchronization, fixes some bugs that were exposed now that IRQs work, etc.):
https://github.com/bbbradsmith/nsfplay/releases

I also ported Blargg's saw wave demo to NSF2: thread
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#235991)
I ended up pushing the VRC7/5B rewrites to 2.5, and just cleaned up a bunch of smaller tasks to finish out 2.4. Beta 15 might be the last beta before I call it stable and move on to 2.5:
https://github.com/bbbradsmith/nsfplay/releases

I added "quick" support for YM2413, i.e. just sort of turning it on with the existing YM2413 emulator in there, but I'm not certain if it works correctly. It will run that Family Noraebang NSF, and I think there's percussion in there, but I have nothing to compare against to know how it should sound. (The whole VRC7/YM2413 will get rewritten for 2.5 anyway...)
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#236001)
Cool.
rainwarrior wrote:
tI will run that Family Noraebang NSF, and I think there's percussion in there, but I have nothing to compare against to know how it should sound.
First, the YM2413 needs a much lower gain than the VRC7. Right now, the audio is horribly distorted. And yes, the percussion channels are missing. As a reference, you could download a current build of NintendulatorNRS here, which plays the file correctly, or you could listen to MLX' recording from actual hardware (ignore the footage from another cartridge in the first few seconds). The hardware recording is rather muffled; this may be the result of filtering by the cartridge itself (to hide the YM2413's quantization noise) or by the console.

Edit: if you have a VGM-format player installed, you could also download my Family Noraebang VGM pack.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#236006)
NewRisingSun wrote:
First, the YM2413 needs a much lower gain than the VRC7. Right now, the audio is horribly distorted.

If you've got the cart to measure you modify the reference test for its register locations and put an appropriate value into a 'mixe' chunk.
http://wiki.nesdev.com/w/index.php/NSFe#mixe
Edit: There's nothing to measure, is there. See next post for a different recommendation.

That video and VGM will help with reference, thanks.

As for percussion not working properly... I'm not sure what I want to do about that. It seems to be making some sounds, but not all of them. I'm rewriting the entire VRC7 emulation for the next version, so I don't really want to labour to understand and fix the old inherited implementation for 2.4. If there's a small code change you can see that would fix it, I could put it in, but otherwise it might just have to wait for the rewrite.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#236007)
Or wait, this cart doesn't even connect the 2A03 audio, right? Then there's nothing to measure...

Lagrange point tends to put its loud channels at 10-12. The Family Noraebang is always at 13-15. I guess equivalent headroom would be -9db?

The Lagrange point default mixe is 1100, so -9dB would be 100.

Edit: having an arithmetic fail. 11-9=2.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#236018)
When krzysiobal took a look at the K-663A he said that it was a bit noisier than a YM2413 anyway.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#236021)
Alright, I figured out where the rhythm mode output had been disconnected and hooked it up, so that should be working in 2.4 beta 16.

B00daW wrote:
When krzysiobal took a look at the K-663A he said that it was a bit noisier than a YM2413 anyway.

Well, this is a practical headroom issue rather than an accurate mix issue. Because of NSF's fortunate/unfortunate multi-chip accident, everything has to be relative to the 2A03's range, and there's only so much that's practical in 16 bits here. The relative mix for each cart is important, but this cart has nothing else to be relative to, so we can set an arbitrary volume for it. I think the most practical thing is just give it a 'mixe' at -9db and let that put it in line with expected range for VRC7 usage. I.e. if the player already has headroom for Lagrange Point, it will automatically accommodate this as well at that relative volume.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#236054)
Wonderful.-9 dB is 0x7C 0xFC in the mixe chunk, right?
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#236055)
It's a signed 16-bit integer in units of 1/100 db, and the reference level for VRC7 is 1100, so the value should be 1100 - 900 = 100. ($64, $00)

Edit: having an arithmetic fail. 11-9=2.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#236094)
I still don't get it. If the default volume of the VRC7 is +11 dB, meaning 11 dB louder than the APU square wave, or 1100 dec, and we want 9 dB less than that, why is it 100 and not 200? 1100-900 is 200, not 100, after all.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#236095)
Yes that's correct, I made a mistake in my arithmetic. Twice. Ha.

1100 - 900 = 200.

Though really an extra dB or two wouldn't hurt here. The VRC7 is the loudest relative expansion, aiming a little lower is probably closer to the average loudness of things. Even 0 could be a good value to use here.
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#236109)
Given the current schema, is VRC7+K-663A multichip NSF a thing since y'all are lumping them together?
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#236110)
No you don't get two. The 'VRC7' chunk replaces the VRC7 with a variant (same as that TNS cart with a YM2413 would do).

Is K-663A a meaningful variant of YM2413 or is this just somebody else's name for an identical part?
Re: NSF Extensions, NSF2 and NSFe (2018)
by on (#236111)
As far as we can tell, it's just a Korean clone of a real YM2413.