/nesvgm



Video:



Download the player, rombuilder and source code


This is a VGM player for the NES, which allows the NES to play music created for the SEGA Master System and Game Gear. The package consists of some playback code and a ROM builder tool (vgm2nes). The purpose of the ROM builder tool is to unzip the VGM file (if necessary), split it into 16kB banks and combine it with the playback code into a iNES format ROM that you can put on your PowerPak or run in an emulator.

A VGM file is just a log file, created e.g. by an emulator, that contains values to be written to one or more sound chips, as well as the amount of time that should pass between writes. The smallest time unit in a VGM is the sample period, which is 1/44100 s, so that's how fast the playback code needs to be able to run. An NES has a custom 6502 CPU running at about 1.66 MHz (or 1.79 Mhz for NTSC), giving you 38 CPU cycles per sample (41 for NTSC), which a lot of times simply isn't enough. But what matters is the average processing rate; so if one command that was supposed to take 1 sample to complete actually took 4 samples, and the next command should take 16 samples, then assuming that you're able to complete the second command in 13 samples you will now have spent the correct amount of time on both commands on average. Add thousands of commands for a complete song and this evens out quite well.

As mentioned above VGMs can log parameters for many different sound chips (the bulk of the VGM command range covers various FM chips and ADPCM chips). This player focuses on one single chip - the simplest of them all: the SN76489.
The SN76489 was used in the SEGA Master System, SEGA Game Gear, ColecoVision, various arcade machines, etc. It's a very crude sound chip, that provides three square wave channels (with a fixed 50% duty cycle) and a noise channel. The frequency range of the square waves is quite limited since the SN76489 uses 10-bit counters to represent the wave periods (unlike the NES which used 11, and PC-Engine which used 12). This meant that you couldn't play anything below an A-2 without some special tricks.

What special tricks? Well, there are a few of them:
* The noise channel has a mode where its output is changed from white noise to a square wave with a 6.25% duty cycle.
* While the noise channel only has 3 different frequency settings, it's also possible to let the third square wave channel drive the noise channel. Combine that with the tone setting mentioned in the previous point and you can play some nice bassy sounds.
* By using a period of zero on the square wave channels you get a constant high output instead of a square wave. With some closely timed code you can utilize this to do sample playback (not supported by my player).

So to play an SN76489 VGM on the NES you just have to keep reading VGM commands, and emulate the SN76489 using the NES's sound chip, while keeping an average tempo of 44100 Hz. Simple enough.
There are two major problems though: the NES only has two square wave channels, and while the NES's noise channels also has a tone mode like the SN76489 they don't sound alike. Hence we need two more square wave channels: VRC6 to the rescue!

Konami's VRC6 mapper was used by a few japanese releases, and contains - among other things - two extra square wave channels, which conviently supports both 50% and 6.25% duty cycles. It also provides a nice banking setup that allows my player to switch in new VGM data in one bank, PAL/NTSC-specific playback code and data in another bank, and keep common code and data in a fixed bank.
Of course, my selection of VRC6 means that if you want to run the player on a real NES you'll need either a PowerPak or a VRC6 devcart. For expansion audio in general to work on an NES you'll also need to bridge the EXP6 and Audio In pins on your NES's expansion connector with a resistor/potentiometer (you can find guides by googling for it). It might also be possible to use a Famicom, but that's not something I've tested.



References: