Emulating the NES in Reaktor, Part I
In this series, I hope to build a decent audio emulation of the Nintendo Entertainment System. I get a fair number of questions about emulating various pieces of old hardware, and the NES seems as good an example to use as any – it has a fairly recognizable sound, is well documented, and decent MIDI files are available for most of the popular games for easy testing. The fact that it was my first gaming system as a child also makes me a little biased.
This tutorial is for users who are familiar with Core. We have some introductory tutorials on Core here.
In order to emulate an older machine such as the NES, first, you must make sure there is good documentation available – old systems often used a variety of strange methods and tricks due to the limitations of hardware at the time. Fortunately, the NES has a massive cult following among gamers – in fact, there are people still producing new cartridges for it!
As such, there is an almost overwhelming amount of knowledge available about the 2A03, the chip used to create audio in the NES. For the purposes of this tutorial, I’ll be using the NESdev wiki, specifically the Audio Processing Unit (APU) Page.
When creating an emulator, the choice is yours with how accurate to be – there are often frustrating limitations with the original hardware that can easily be overcome with the processing power of newer systems.
For instance, the old Atari 2600 is notorious for having terrible tuning – the developers of the hardware being seemingly disinterested from the audio aspects of the system. It would be easy to fix this problem in an emulation, however, keeping this poor tuning can, in my opinion, help to retain the character of the system when emulated.
There are other times, such as with the pulse wave generators on the NES, where making an exact replica of the sound wave is far more work than simply using a Primary Pulse Oscillator module, yet gives little improvement over sound or quality.
Nonetheless, the point of this tutorial is mostly an academic exercise on doing our best to emulate a system, as precisely as possible. To that end, I’ll do my best in this series to implement an exact copy of the internal workings of the NES.
CREATING A CLOCK
The first problem we encounter emulating the NES is the CPU clock. This clock has a speed of 1.78977267 MHz – that’s over 40 times faster than the default system clock of 44.1 KHz in Reaktor!
This in itself can be a real problem – we certainly would rather not iterate through a function 40 times every sample clock. Let’s set aside this problem for now and focus on calculating at each sample tick in Reaktor, how many NES CPU clock ticks have happened since we last checked.
Here’s a structure to achieve this goal:
This is not so tough. We calculate the number of NES sample ticks for each Reaktor clock – using a sample rate of 44.1KHz, this ends up being around 40.5844. We also have a stored value that stores any fractional clock ticks – since the NES clock speed and the Reaktor clock speed are not evenly divisible, there is an extra little bit of time at each sample tick equal to 0.5844 ticks of the NES clock.
After adding together the new NES clocks to anything left over from last time, we use a Mod1 macro (which I’ll show below) to strip out the decimal values, sending the integer to the output to be processed, and storing the decimal to use for next time.
Here’s the Mod1 macro:
This is a simple method to separate the integer component from the decimal component of any number. For instance, if the input is 6.7, we want to send a 6 to the top input and a 0.7 to the bottom. This macro only works for positive values, but since there is never a time when the value will not be positive in this particular instance, this is fine – just a warning to anybody who wishes to reuse this macro for something else.
The Int macro is simply a macro to round to the nearest number:
It doesn’t get much simpler than that!
Okay, so our clock macro outputs two values – the first is a constant, the NES CPU clock speed, which we will use later on with our oscillators; the second is a number of NES CPU clocks to process, and a new value (either 40 or 41) arrives at each sample tick.
Next week, I’ll focus entirely upon creating the oscillators. I’ll show how we can often process dozens of NES clock ticks simultaneously, and the basics of creating NES oscillators. I hope you have enjoyed this tutorial, as always, feel free to leave any questions or suggestions in the comments.