N-SPC Engine: Difference between revisions
KungFuFurby (talk | contribs) (Starting documentation, including recording general identifications of VCMDs from the music-only source that many variants templated off of) |
KungFuFurby (talk | contribs) (Adding extra phrase and some VCMD definitions) |
||
Line 42: | Line 42: | ||
==Phrase Format== | ==Phrase Format== | ||
Song entries point to a list of phrases for the song to play. | Song entries point to a list of phrases for the song to play. | ||
If the high byte is zero, then the low byte is a loop counter, and a second pointer is defined as a jump pointer. If the loop counter is <tt>$FF</tt>, then the jump always executes, rather than executing 255 times. | |||
If the loop counter is also zero, the song terminates, and no second pointer is required. | |||
Each phrase is a pointer to a collection of eight pointers to track data. If the pointer is zero, there is no track data. | Each phrase is a pointer to a collection of eight pointers to track data. If the pointer is zero, there is no track data. | ||
Line 129: | Line 131: | ||
|} | |} | ||
''TODO: Voice Command Descriptions'' | ===Invalid (VCMD <tt>$FF</tt>)=== | ||
Crashes the sound driver due to being outside of the array of pointers, and thus jumping to an invalid pointer. | |||
===NOP (VCMD <tt>$FB</tt>)=== | |||
<pre>$FB xx</pre> | |||
Reads a single byte, then does absolutely nothing with the command. | |||
===Phrase Termination/End of Subroutine (VCMD <tt>$00</tt>)=== | |||
This VCMD's operation depends on whether or not it is inside a subroutine or not. | |||
If it is inside a subroutine, it exits the subroutine and song execution continues. | |||
Otherwise, the phrase is terminated. This affects ''all'' channels in the music: any other channels still playing are interrupted. | |||
===Note Duration (VCMD <tt>$01-$7F</tt>)=== | |||
<pre>%0xxxxxxx (yz)</pre> | |||
* <tt>xxxxxxx</tt> represents your note length (as seven bits) in tempo ticks. | |||
* <tt>y</tt>, if less than <tt>$8</tt>, defines the quantization. It is an index value to a table of values that indicate, in 256ths, how far along the note to play before keying it off. This table can vary on a per-game basis. | |||
* <tt>z</tt>, which is only defined if y is less than <tt>$8</tt>, defines the velocity. It is an index to a table of values that indicate the volume in a decibel-like number (due to the final volume calculation being multiplied by itself at the end). This table can vary on a per-game basis. | |||
Notes and/or special VCMDs, by default, are forced after the parameter byte is read. Attempting to use <tt>$00-$7F</tt> again results in an invalid note. | |||
===Note (VCMD <tt>$80-$C7</tt>)=== | |||
Plays a note and delays the channel for one note length before reading another VCMD. | |||
===Tie (VCMD <tt>$C8</tt>)=== | |||
Continues playing the previous note and delays the channel for one note length before reading another VCMD. | |||
===Rest (VCMD <tt>$C9</tt>)=== | |||
Keys off the previous note and delays the channel for one note length before reading another VCMD. | |||
===Percussion (VCMD <tt>$CA-$DF</tt>)=== | |||
Plays a percussion note. | |||
By default, percussion uses the same instrument set as the song, and all percussion is keyed on with a note of <tt>$A4</tt>. | |||
''TODO: Voice Command Descriptions for <tt>$E0-$FE</tt>'' | |||
==Variants== | ==Variants== |
Revision as of 17:58, 9 October 2020
WIP: currently a stub
Nintendo SPC Sound Engine, abbreviated N-SPC and officially known as Kankichi-kun [1], is the most common sound engine used in all of the SNES/SFC games. Only the music portion was initially provided in the source code included in the IS-Sound unit along with some templating for a protocol for music and sound effects [2]: usually it was modified by developers on an individual basis, resulting in many different variants, some of them more heavily modifying the sound driver than others. Usually what was added on was sound effect support, but sometimes the music VCMDs were modified as well.
The following games are purely based off of the source code provided with the IS-Sound unit, and are either unmodified or barely modified, if at all:
Game Name | VCMD Table Location (usually $E0 and up) | ROM Offset |
---|---|---|
Hong Kong '97 | 0x0DEC, relative to 0x0D2C | 0x0F800A (both versions) |
SM Choukyoushi Hitomi - Bangai Hen | 0x0DEC, relative to 0x0D2C | 0x01801C |
SM Choukyoushi Hitomi Vol. 2 Trial Version | 0x0DEC, relative to 0x0D2C | 0x01801C |
SM Choukyoushi Hitomi Vol. 2 | 0x0DEC, relative to 0x0D2C | 0x03801C |
SM Choukyoushi Hitomi Vol. 2 Remix | 0x0DEC, relative to 0x0D2C | 0x01801C |
SM Choukyoushi Hitomi Vol. 3 Trial Version | 0x0DEC, relative to 0x0D2C | 0x018058 |
SM Choukyoushi Hitomi Vol. 3 (Alt 1) | 0x0DF0, relative to 0x0D30 | 0x018076 |
Wheel of Fortune - Deluxe Edition | 0x0DEC, relative to 0x0D2C | 0x01D842 |
Of the games listed here, two of them are very minor edits...
- Wheel of Fortune - Deluxe Edition's build is unused and is missing an opcode near the *Ver S1.20* string.
- SM Choukyoushi Hitomi Vol. 3 (Alt 1)'s program starts with a JMP opcode, and contains a NOP between the first and second opcodes of the actual program.
Instrument Format
The instrument format is most commonly defined as direct writes to DSP registers for the first four bytes, followed by two pitch-related bytes. They are defined in this order, from top to bottom...
- SRCN
- If this value is above $7F, noise is used, and the lowest five bits contains the noise clock rate.
- ADSR1
- ADSR2
- GAIN
- Pitch Base Multiplier
- Pitch Base Fractional Multiplier (in 256ths)
Phrase Format
Song entries point to a list of phrases for the song to play. If the high byte is zero, then the low byte is a loop counter, and a second pointer is defined as a jump pointer. If the loop counter is $FF, then the jump always executes, rather than executing 255 times. If the loop counter is also zero, the song terminates, and no second pointer is required.
Each phrase is a pointer to a collection of eight pointers to track data. If the pointer is zero, there is no track data.
Voice Command Format
NOTE: This is not representative of every single variant. Instead, it represents the collection of VCMDs from the source code included in the IS-Sound unit, which in turn is carried over to most variants.
VCMD ID | Description | Arguments |
---|---|---|
$00 | Phrase Termination/End of Subroutine | |
$01-$7F | Note Duration | xy |
$80-$C7 | Note | |
$C8 | Tie | |
$C9 | Rest | |
$CA-$DF | Percussion | |
$E0 | Instrument | xx |
$E1 | Panning | %xyzzzzz |
$E2 | Panning Fade | xx yy |
$E3 | Vibrato On | xx yy zz |
$E4 | Vibrato Off | |
$E5 | Master Volume | xx |
$E6 | Master Volme Fade | xx yy zz |
$E7 | Tempo | xx |
$E8 | Tempo Fade | xx yy |
$E9 | Global Transposition | xx |
$EA | Single Channel Transposition | xx |
$EB | Tremolo On | xx yy zz |
$EC | Tremolo Off | |
$ED | Volume | xx |
$EE | Volume Fade | xx yy |
$EF | Subroutine | xx xx yy |
$F0 | Vibrato Fade In | xx |
$F1 | Note Pitch Envelope To | xx yy zz |
$F2 | Note Pitch Envelope From | xx yy zz |
$F3 | Note Pitch Envelope Off | |
$F4 | Fine Tune | xx |
$F5 | Echo On | xx yy zz |
$F6 | Echo Off | |
$F7 | Echo Parameter Setup | xx yy zz |
$F8 | Echo Volume Fade | xx yy zz |
$F9 | Pitch Slide to Note | xx yy zz |
$FA | Percussion Patch Base Redefine | xx |
$FB | NOP | ?? |
$FC | Channel Mute | |
$FD | Fast Forward On | |
$FE | Fast Forward Off | |
$FF | Invalid |
Invalid (VCMD $FF)
Crashes the sound driver due to being outside of the array of pointers, and thus jumping to an invalid pointer.
NOP (VCMD $FB)
$FB xx
Reads a single byte, then does absolutely nothing with the command.
Phrase Termination/End of Subroutine (VCMD $00)
This VCMD's operation depends on whether or not it is inside a subroutine or not. If it is inside a subroutine, it exits the subroutine and song execution continues. Otherwise, the phrase is terminated. This affects all channels in the music: any other channels still playing are interrupted.
Note Duration (VCMD $01-$7F)
%0xxxxxxx (yz)
- xxxxxxx represents your note length (as seven bits) in tempo ticks.
- y, if less than $8, defines the quantization. It is an index value to a table of values that indicate, in 256ths, how far along the note to play before keying it off. This table can vary on a per-game basis.
- z, which is only defined if y is less than $8, defines the velocity. It is an index to a table of values that indicate the volume in a decibel-like number (due to the final volume calculation being multiplied by itself at the end). This table can vary on a per-game basis.
Notes and/or special VCMDs, by default, are forced after the parameter byte is read. Attempting to use $00-$7F again results in an invalid note.
Note (VCMD $80-$C7)
Plays a note and delays the channel for one note length before reading another VCMD.
Tie (VCMD $C8)
Continues playing the previous note and delays the channel for one note length before reading another VCMD.
Rest (VCMD $C9)
Keys off the previous note and delays the channel for one note length before reading another VCMD.
Percussion (VCMD $CA-$DF)
Plays a percussion note.
By default, percussion uses the same instrument set as the song, and all percussion is keyed on with a note of $A4.
TODO: Voice Command Descriptions for $E0-$FE
Variants
References
- Video Game Music Preservation Foundation - Kankichi-kun
- Retro Reversing - SNES (Super Famicom) Development Kit Hardware - Intelligent Systems SHVC Development System
- Super Famicom Wiki - N-SPC
- GDRI - Super Famicom/Super NES Sound Driver List
- Github - N-SPC VCMD $FB-$FE identifications
TODO: There are a lot of variants... these will be split into sub-pages depending on the modifications made