vspcplay is a .spc player based on the snes9x snes apu emulation code, featuring a colored
visual (hence the name) memory representation, ability to view memory content simply
by moving the mouse around, volume/gain bars, pitch dots and simple port
vspcplay uses libSDL for it's display output. Most of the screen space is occupied by the
memory surface (512x512). There is a small menubar near the lower edge of the screen. See
below for details about each component.
The main component is the memory surface. The upper left corner is address $0000 and the lower
right corner is address $ffff. Reads are colored as blue, writes as green (read+write gives cyan).
PC (program counter) execution address are colored as red. Pixels slowly fades, but never completely thus leaving a footprint.
By moving the mouse over the memory surface, you can see a 128 bytes hexdump starting at the address
under the mouse pointer. You can toggle the hexdump address lock by clicking in the memory surface.
Colors used are the same as in the memory surface, but they are brighter for visibility.
The pitch dots represent the pitch of the sample for each track. Pitch increase as the dots moves
towards the left.
Each channel can have it's own left and right volume, which permits panning effects. There
is also a gain, which is sometimes used for enveloppe effects. Volume increase as the bars lengths increases.
New in version 1.4: Channels can be muted using the 1-8 keys. 0 toggles mute all / mute none.
The port tool allows you to change the values as if you were the Snes. With some games, you can
use this to play sound effects. In some other games, you can even change the tune.
You can use the mouse to click on the + and - to increase or decrease the port value, or you can
roll the mousewheel. The changes you make will be visible at addresses $f4 to $f7 (left to right) in the APU memory
Game port usage
Below is a table about how to use extra spc features with some games. (Play sound effects, change the tune, etc). This is work in progress. Contributions would be welcomed.
Legend of Zelda 3
Tune selection: Value in port $f4 selects the tune. Sound effects: Values in ports $f6 and $f7 plays sound effects.
The value in port $f5 controls how the rain sounds. When set to $ff the
Tune selection: Value in port $f4 selects the tune. Do it
with a menu or information screen tune, otherwise a motor sound kicks
in. Sound effects: Port $f5 and $f7 plays sound effects and beeps.
Port $f6 controls the pitch of the plane motor.
Super Mario World
Tune selection: Values ranging from $0 to $1D in port $f6 selects
the tune being played. A value of $ff fades out the current tune. Sound effects: Values in port $f4 and $f6 plays sound effects.
A Value of 1 in port $f5 plays the jump sound. Hurry up: If you put a value of $ff in port $f4, the hurry up
sound will be played and the music will go faster.
Tune selection: Values from $01 to $13 in port $f4 select the tune. Sound effects: Values in port $f6 select sound effects due to user actions (place road segment, place zone, etc)
Values in port $f7 is used to control additional sound effects
such as airplane noise, disaster noise, etc. Other:If you change the value in port $f5, the music stops but
sound effects will stay active.
Donkey Kong Country 1
Id of sound effect selected by port $f5. Each time $f4 changes (eg incremented), the
sound effect is played.
For sound effects, the most significant bit of $f5 is apparently not used. (eg sound $81 is the same as $01).
Values between $77 and $7F in port $f5 seem to be used for other purposes (changing tune, etc.). When $fd or $fc is in $f5, each time $f4 changes, then playback speed is momentarily increased.
Here is a list of the sound effects IDs.
Those which I am not sure are between parentheses. dkc1.html
Donkey Kong Country 2 (Diddy's Kong Quest)
Sound effects: Values ranging from $00 to $76 in port $f5 select the sound effect
to be played when $f4 changes.
Donkey Kong Country 3 (Dixie Kong's Double Trouble
Sound effects: Values ranging from $00 to around $60 in port $f5 selects the sound effect
to be played when $f4 changes.
Super mario kart
Sound effects: Some values in port $f5 plays some in-game sound effects.
Value ranging from $0 to $7f in port $f6 controls the player's kart motor pitch (value of 0 == off).
The value in port $f7 controls the motor sound volume and panning of karts passing by. Other: Changing value in port $f4 from $00 to $ff plays a pause sound and reduce the
music volume. When changed back from $ff to $00, the music resumes at it's initial volume.
Why I wrote vspcplay
In december 2004, I followed caitsith2's schematics
(see his webpage for details)
to connect an snes APU (Audio Processing Unit) to a PC using the parallel port. The goal
was to play .spc files (Snes music files) on a sound module taken from an SNES console.
SPC files are a full snapshot (save state) of the APU's CPU, the spc700. This works fine, but before
music starts the full 64kB of memory must be uploaded to the APU, and this takes about 5 seconds...
It occured to me that perhaps only a fraction of memory is used to play a given tune. For instance,
there are likely sound effects or maybe also unused instruments. For instance, a tune that only uses
50% of the APU memory could be loaded 50% less time!
So the question was, how to know which memory areas are not used... The .spc file format
does not help us, since .Spc's are nothing more than dumps of cpu registers and memory.
(see spc_file_format.txt for specification). The
only way I thought of is to play the tune in a modified emulator which would log all memory access.
I took the source code of an xmms spc plugin based on Snes9X and converted it in a simple tool
to log memory accesses. I knew that snes9x may not be the best APU emulator, but it was the only one
not written in assembly and I needed this tool to run on the Sparc workstation I used at the time. I decided
to represent the memory as 256 blocks of 256 Bytes. Whenever a reads occurs in particular block,
it gets marked as used.
While writing my memory access logging tool, I decided to try to representing the 64KB memory
as a 256x256 pixels surface, with a color code for read, write and execution. This looked
very cool, I could see the music tracks being read, the samples being used, etc. So I got
carried away and added visual volume bars for each channel, moving dots for each
channel pitch, a tool to play with port values (The APU and the Snes communicates together using
Version 1.4 July 22, 2022 (Friday)
Add an option to output a Wave file (--waveout)
Add options to mute/unmute specific channels (--mute and --unmute command-line options)
Add keyboard controls (1-8 to toggle mute, 0 to toggle mute all/none, N/P to play next/previous song, R to restart song, ESC to quit)
Fix a bunch of buffer overflows, fix warnings, some code cleanup...