-
Notifications
You must be signed in to change notification settings - Fork 7
About improved SNESAPU.DLL
The SNESAPU published here is based on v2.0 by Alpha-II Productions with various improvements and customizations, some features are ported from v3.0.
Some emulators can perfectly reproduce the actual device, but the SNESAPU is not perfect because slightly old design.
Instead, it provides high-quality sound output and a number of features that will especially please those who enjoy the SPC as a soundtrack.
Inherits parts:
- 32-bit floating point DSP processing.
- SNESAPU's DSP delivers sound quality that exceeds that of the actual device.
- Prevents noise caused by continuous volume changes.
- "Spirit of the Night" of "Secret of Mana" songs will come out beautiful especially.
- Extensive DSP customization options.
- Change speed/pitch, channel mute, disable echo/surround/FIR/pitch modulation, etc.
Customized/updated parts:
- 8-point sinc interporation.
- Backported from v3.0, sound is as clear as a CD without the muffled sound of the actual device.
- Low-pass filter with the same cut-off frequency, and noise generator as in the actual device.
- It improves compatibility with the actual machine, and creates an analog feel output.
-
Script700 compatible function.
- For example, can play SPC files of "PuyoPuyo" series without applying the patch.
- Other, many new features and improvements.
To emulate the SPC700 and DSP, call APIs of the SNESAPU in the following order:
void SetAPUOpt(u32 mixType, u32 numChn, u32 bits, u32 rate, u32 inter, u32 opts);
-
void LoadSPCFile(void *pFile);
- pFile specifies the contents of the SPC file, not file name.
-
void* EmuAPU(void *pBuf, u32 len, u8 type);
- To get more waveform data, call EmuAPU repeatedly.
Depending on your preferences, make additional calls to the following APIs:
void SetAPUSmpClk(u32 speed);
void SetDSPAmp(u32 amp);
void SetDSPEFBCT(s32 leak);
void SetDSPPitch(u32 base);
void SetDSPStereo(u32 sep);
See APU.h, DSP.h, and SPC700.h for a description of each API.
The Script700 is an assistance script of SPC700 used in Japan.
Some songs (ex. "PuyoPuyo" series, "RPG tsukuru 2", "Furai no shiren", etc.) are not played simply by saving an SPC.
Because SNES main CPU transfers additional data in real time.
If used the Script700, these special SPCs can be played correctly by mimicking main CPU instructions.
For using the Script700 in the SNES SPC700 Player, save a code of the Script700 to a file with same name as the SPC file, and change extension to "700".
For example, if you want to apply the Script700 to "sample.spc", write a code in "sample.700".
If you want to apply the Script700 for all SPC files in a folder at once, write script in the "65816.700" file instead.
Now, here is the script to correctly play an SPC of "PuyoPuyo" series.
If you write this in the "65816.700" file, you will be able to play it without patching all SPC files.
m 0 w0 ;Read value from port[0], copy to work[0]
:001 w 16661 ;Wait 16661 clocks
a #1 w0 ;Increment work[0]
m w0 0 ;Write value from work[0] to port[0]
bra 001 ;Jump to :001
e ;End of script
There are many scripts that can be adapted to each game.
KUROHANE Works has made a summary page for the list of known the Script700.
See also: About special SPC (in Japanese)
For coding the Script700, provided an extension plugin for VSCode.
This extension provides functions such as instruction highlighting.
Summary of Script700 syntax is provided below, but please see the extension's help for more details.
See also: Script700 Helper
To use the Script700 with SNESAPU alone, use the following API:
-
s32 SetScript700(void *pSource);
- pSource specifies the contents of the Script700 file, not file name.
Script700 has 3 zones with different roles, which are divided with the e
command.
; --- Script commands zone ---
m #0 0
e
; --- Extended commands zone ---
m 20
e
; --- Data area ---
0007CBA380AD4E52
79A3C4E7BB524042
Script commands zone:
Each command in the "script commands zone" executes the instruction in a different thread than SPC700.
Commands:
:[LABEL] ; Label (use with 'bxx' command)
w [TIME] ; Wait (1/2048 kHz)
m [SRC] [DEST] ; DEST = SRC
c [CMP1] [CMP2] ; [CMP1] = CMP1, [CMP2] = CMP2
a [VAL] [SRC/DEST] ; DEST = SRC + VAL
s [VAL] [SRC/DEST] ; DEST = SRC - VAL
u [VAL] [SRC/DEST] ; DEST = SRC * VAL
d [VAL] [SRC/DEST] ; DEST = SRC / VAL (signed)
n [VAL] + [SRC/DEST] ; DEST = SRC + VAL
n [VAL] - [SRC/DEST] ; DEST = SRC - VAL
n [VAL] * [SRC/DEST] ; DEST = SRC * VAL
n [VAL] / [SRC/DEST] ; DEST = SRC / VAL (signed)
n [VAL] \ [SRC/DEST] ; DEST = SRC / VAL (unsigned)
n [VAL] % [SRC/DEST] ; DEST = SRC MOD VAL (signed)
n [VAL] $ [SRC/DEST] ; DEST = SRC MOD VAL (unsigned)
n [VAL] & [SRC/DEST] ; DEST = SRC AND VAL
n [VAL] | [SRC/DEST] ; DEST = SRC OR VAL
n [VAL] ^ [SRC/DEST] ; DEST = SRC XOR VAL
n [VAL] < [SRC/DEST] ; DEST = SRC << VAL
n [VAL] _ [SRC/DEST] ; DEST = SRC >> VAL (signed)
n [VAL] > [SRC/DEST] ; DEST = SRC >> VAL (unsigned)
n [SRC] ! [DEST] ; DEST = NOT SRC
bra (#)[LABEL],w[WORK] ; Unconditional jump
beq (#)[LABEL],w[WORK] ; Jump to label if [CMP1] == [CMP2]
bne (#)[LABEL],w[WORK] ; Jump to label if [CMP1] != [CMP2]
bge (#)[LABEL],w[WORK] ; Jump to label if [CMP1] <= [CMP2] (signed)
ble (#)[LABEL],w[WORK] ; Jump to label if [CMP1] >= [CMP2] (signed)
bgt (#)[LABEL],w[WORK] ; Jump to label if [CMP1] < [CMP2] (signed)
blt (#)[LABEL],w[WORK] ; Jump to label if [CMP1] > [CMP2] (signed)
bcc (#)[LABEL],w[WORK] ; Jump to label if [CMP1] <= [CMP2] (unsigned)
blo (#)[LABEL],w[WORK] ; Jump to label if [CMP1] >= [CMP2] (unsigned)
bhi (#)[LABEL],w[WORK] ; Jump to label if [CMP1] < [CMP2] (unsigned)
bcs (#)[LABEL],w[WORK] ; Jump to label if [CMP1] > [CMP2] (unsigned)
r ; Jump to next to last called 'bxx'
r0 ; Do not record the return destination of 'r' command
r1 ; Record the return destination of 'r' command
f ; Flush SPC700 port writes
f0 ; Temporarily disable writing to the SPC700 port
f1 ; Resume writing to SPC700 port
wi [PORT] ; Wait until SPC700 reads a port
wo [PORT] ; Wait until SPC700 writes a port
bp [RAM] ; Breakpoint in SPC700 processing
q ; Quit script
nop ; Do nothing (not even waiting)
Parameters ([TIME],[SRC],[DEST],[CMP1],[CMP2],[VAL]
):
#[NUM] ; Literal number (32-bit)
i[PORT] ; SPC700 input port
o[PORT] ; SPC700 output port
w[WORK] ; User work memory (32-bit)
r[RAM] ; Address of Main RAM (8-bit)
rb[RAM] ; Address of Main RAM (8-bit)
rw[RAM] ; Address of Main RAM (16-bit)
rd[RAM] ; Address of Main RAM (32-bit)
x[XRAM] ; Address of memory for swapping between main and IPL (8-bit)
d[DATA] ; Address of data area (8-bit)
db[DATA] ; Address of data area (8-bit)
dw[DATA] ; Address of data area (16-bit)
dd[DATA] ; Address of data area (32-bit)
l[LABEL] ; Address of label
#?, i?, o?, w?, r?, ... ; Process '?' part with value of [CMP1] or [CMP2]
Extended commands zone:
Each command in the "extended commands zone" switches the processing for the DSP.
Commands:
m [SOUND],! ; Mute a specific tone
c [SOUND],! [CHANGE] ; Replace a specific sound (SOUND <- CHANGE)
d [SOUND],! [RATE] ; Detune a specific tone
v [SOUND],! [VOLUME] ; Change volume of a specific tone (x1 = 65536)
Parameters ([SOUND],[CHANGE]
):
0~255 ; Tone number
vl ; Main left volume (v command only)
vr ; Main right volume (v command only)
el ; Echo left volume (v command only)
er ; Echo right volume (v command only)
l ; vl + el (v command only)
r ; vr + er (v command only)
lr ; l + r (v command only)
** Now obsolete method, parallel port is not equipped on most modern computers, but you can try it if you have the materials. **
This improved SNESAPU.DLL supports data transfer to SHVC-SOUND using parallel port.
Refer to the following pages for electronic circuits for transfer.
See also: Snes APU on a PC
To transfer data, install "GiveIO" or "InpOut32" first, and call APIs of the SNESAPU in the following order:
-
void LoadSPCFile(void *pFile);
- pFile specifies the contents of the SPC file, not file name.
-
s32 TransmitSPC(u32 addr);
- addr specifies the data address of parallel port. (ex. 0x378)
-
Result:
- 0 = Successful transfer
- not 0 = Failed, see below for the meaning of the numbers.
Result | Cause |
---|---|
-1 | Not installed GiveIO or InpOut32. |
-2 | Not supported EPP/ECP mode. |
-3 | No space available for boot loader. |
1 ~ 9 | Failed reset SHVC-SOUND. |
10 ~ 19, -10 ~ -19 | Failed transfer memory loader. |
20 ~ 29, -20 ~ -29 | Failed transfer SPC buffer. |
** Sadly, G.I.M.I.C production has ended in 2024 summer. **
In Japan, there is Dojin hardware called G.I.M.I.C which operates a retro music chip and outputs high quality sound.
This device with GMC-SPC2 module can output real SNES music.
In addition, it supports optical output and can extract sound from SNES without degradation.
This improved SNESAPU.DLL supports SPC playing using G.I.M.I.C and fast transfer.
Transfer time of is about 1.7 seconds, because unique boot code increases transfer capacity 3 times.
Since the memory used for echo is cleared to 0 in advance, loud noise is not generated at the start of playing.