Original Post

Hey, guess what. I’m not dead yet! Between months of Splatoon and some employment/relocation headaches, I took a longer-than-expected break from Virtual Boy. Rest assured, however, that I’m back in earnest.

It should be no surprise that I followed a tangent for working out the mysteries of the VSU while working on my music project. I’ve hunted down every single unknown detail and documented the crap out of it. Version 1.0 of the Tech Scroll is also in the works, and it contains all of the new information.

Among other things:
• Modulation memory can be written during sound generation, but not while channel 5 is active.
• Specifying a PCM wave above the usual 5 will prevent the channel from activating.
• Frequency is stored both in register memory as well as a current working value. Sweep and modulation only modify the working value.
• Modulation does not change the working frequency value, but rather each sample is added to the most recent value written to the frequency registers.
• If modulation causes the working frequency value to go out of range, it wraps to the lowest 11 bits.
• I incorrectly documented how sweep works. It shifts the working frequency value right by the given number of bits, then either adds or subtracts that to the working value.
• PCM sampling resets when Play Control or Wave Index are written.
• The noise generator’s shift register is reset when Play Control or Envelope/Noise Control are written.
• I also had the digital output documented wrong. I fixed that and added analog output documentation.

Attached to this post is the mother of all VSU test programs. I call it VSU Workshop, and it gives you an on-screen display of everything the VSU can do, and you can modify every memory value and every parameter of every register. Thanks to this software, I was able to utterly master the VSU’s operations and now I feel I’m more than certified for continuing on my musical journey. (-:

• Left D-Pad navigates.
• Up and down on the right D-Pad changes integer values, such as memory data and register parameters.
• A button will edit the currently selected register.
• A button toggles checkmark flags.
• B button will exit the edit mode and return to register selection.
• A button will activate the master Write and Stop commands.

All registers flagged to write will be written when the master Write command is invoked. All registers are de-flagged afterward.

Remember, to generate useful sound you need to do three things: 1) configure a PCM wave with some sample data, 2) configure the Stereo Levels register so the left/right channels are audible, and 3) set Reload in Envelope Data so the entire channel is audible.

Questions and comments are welcome. I’m cold and tired, so it’s to the shower for me. <3

11 Replies

That’s a nice bit of reverse-engineering, Guy!

I wish I had more time to play around with your VSU tool; it looks pretty handy for experimentation.

This looks fun to play with! Gonna give it a go here if I can figure it out =P Total newbie to this sort of thing.

I was a doofus and forgot to initialize PCM wave memory on startup. In the build attached to the OP, you’d have to change all the zeroes to something else and back to zero for it to take effect.

Attached to this post is a fixed version.


Neat, I stumbled on a most interesting find…

I missed an unanswered question before. The question was: “Is the sweep shift amount taken as-is or is 1 added to it like most of the other register fields?” The answer is it’s taken as-is, so a shift amount of zero will either double or zero out the current frequency value on channel 5. So there’s that.

While trying to determine that, however, I noticed an odd behavior. A little experimentation shows that there’s not one, but two actual bugs in the hardware implementation of the sweep function!

By design, the sweep function will stop channel 5 if the result of the sweep operation would cause its frequency value to exceed 2047. No harm there, but the failsafe still shuts off the channel even if the sweep function is not active (either disabled in the control register or if the sweep interval is zero). Logically, one would think that the channel should only activate if the sweep function is actually turned on.

Additionally, channel shutoff happens one sweep frame early. The algorithm looks something like this:

• Calculate the new frequency value = current ± (current >> shift)
• If new value > 2047, stop channel
• Wait for the modification interval to elapse
• Update the current frequency value with the new one
• Return to top

It might be hard to see why that’s a problem, so let’s try a for-instance. Let’s say we use frequency value 510, which comes out to about 101.6 hz for a full wave, and a sweep shift amount of zero, which will double the frequency value every sweep frame.

• During the first frame, it notices that 510 * 2 = 1020 is less than 2048, so it plays the frame at 510 then sets it to 1020 afterward.
• During the second frame, it notices that 2040 is less than 2048, so it plays the frame at 1020 then sets it to 2040 afterward.
• During the third frame, it notices that 4080 is greater than 2047 and stops the channel.

So even though 2040 is a valid frequency value, the channel was stopped without playing at that frequency.

I took a look at the sound board and saw that it was using 220μF capacitors and 100Ω resistors to cancel the DC bias of the analog output. If you work that into the formula, you get a cutoff frequency of about 7.23hz. My earlier estimation of 10.0hz was based on analysis of recorded sound output, but I’m pleased to say that I know the exact value now.

I’m testing a VSU emulator that I wrote for the music project, and implemented the new RC value based on the components I saw wired into the actual device. There’s still some noise in the hardware line and the usual analog oddities, but holy smokes, my output matches almost exactly both for amplitude as well as timing.


Welcome to “Guy Perfect Talks to Himself 2016”!

I’ve completed my Java VSU emulator and ported over the VB sounds engine I wrote for this project. I set up a cobbled mess of tones and interrupting sounds then ran it through both my emulator and the hardware… and Mednafen.

The results are attached to this post, as is a ROM that produces this audio sequence. While we’re never going to get a 100% match with the hardware sample-for-sample, at least we can get awfully darn close.

This Debugging program is the best on Virtual Boy! 😀

very awesome man.. I’m actually researching vsu as well.. except that I’m just starting. sent you a PM

Morintari notified me of this a few days ago. And holy moly. This looks, in one word, amazing.

Can’t wait to get my hands dirty on it once I get the opportunity. 🙂

I can’t get it to work on VBJin

I used your tool on various emulators with the most compatibility, but followed your instructions and got no sound out of it.

Here’s what I tried to do:
First, I initialized the first PCM wave with a basic 50% square wave.
Then, I enabled the write flag before setting my values on Channel 1.
Next, I turned up the stereo panning values and the initial value.

Get no sound. What am I doing wrong here?

Just can’t wait to use it more often and figure out what it would sound like with the sweep hardware and the noise generator!


Write a reply

You must be logged in to reply to this topic.