📄 snesapu.pas
字号:
ENV_11,ENV_12,
ENV_DECAY // Decay mode
);
const
ENVM_IDLE = $80; // Envelope is marked as idle, or not changing
ENVM_MODE = $F; // Envelope mode is stored in lower four bits
type
Voice = record
//Voice -----------08
pVoice : ^DSPVoice; // -> voice registers in DSP
_r : u32;
//Waveform --------06
bCur : Pointer; // -> current block
bHdr : u8; // Block Header for current block
mFlg : u8; // Mixing options (see MixO)
//Envelope --------22
eMode : u8; // Current mode (see EnvM)
eRIdx : u8; // Index in RateTab (0-31)
eRate : u32; // Rate of envelope adjustment (16.16)
eCnt : u32; // Sample counter (16.16)
eVal : u32; // Current envelope value
eAdj : s32; // Amount to adjust envelope height
eDest : u32; // Envelope Destination
//Visualization ---08
vMaxL : s32; // Maximum absolute sample output
vMaxR : s32;
//Samples ---------52
sP1 : s32; // Last sample decompressed (prev1)
sP2 : s32; // Second to last sample (prev2)
sIdx : ^s16; // -> current sample in sBuf
sBufP : array[0..3] of s16; // Last 4 samples from previous block (needed for inter.)
sBuf : array[0..15] of s16; // 32 bytes for decompressed sample blocks
//Mixing ----------32
mTgtL : f32; // Target volume (floating-point routine only)
mTgtR : f32; // " "
mChnL : s32; // Channel Volume (-24.7)
mChnR : s32; // " "
mRate : u32; // Pitch Rate after modulation (16.16)
mDec : u32; // Pitch Decimal (.16) (used as delta for interpolation)
mOrgP : u32; // Original pitch rate converted from the DSP (16.16)
mOut : s32; // Last sample output before chn vol (used for pitch mod)
end;
//Saved state ----------------------------------
DSPState = record
pDSP : ^DSPReg; // [0.0] -> DSP registers (128 bytes)
pVoice : ^Voice; // [0.4] -> Internal mixing settings (1k)
pEcho : Pointer; // [0.8] -> echo buffer (bytes = sample rate * 1.92)
_r1 : u32; // [0.C] reserved
vMMaxL, vMMaxR : u32; // [1.0] Maximum output so far
mAmp : u32; // [1.8] Amplification
vActive : u8; // [1.C] Flags for each active voice
_r2 : array[0..2] of u8;// [1.D] reserved
end;
//**************************************************************************************************
// SNESAPU.h
SAPUFunc = record
ram : ^u8; // Base pointer to APU RAM
xram : ^u8; // Pointer to writeable IPL region
outPort : ^u8; // SPC700 output ports
t64Cnt : ^u32; // 64kHz timer counter
dsp : ^DSPReg; // DSP registers
voices : ^Voice; // Internal DSP mixing data
vMMaxL, vMMaxR : ^u32; // Max main sample output
SNESAPUInfo : procedure (var ver, min, opt: u32); stdcall;
GetAPUData : procedure (ram,xram,spcout,t64Cnt,dsp,voice,vMMaxL,vMMaxR:Pointer); stdcall;
BitRateReduce : procedure (pBlk,pSmp:Pointer; var pLen,pLoop:u32; opt:s32);
ResetAPU : procedure (level:s32); stdcall;
FixAPU : procedure (pc:u16; a,y,x,psw,sp:u8); stdcall;
LoadSPCFile : procedure (Spc:Pointer); stdcall;
SaveAPU : procedure (var Spc:SPCState; var dsp:DSPState); stdcall;
RestoreAPU : procedure (var Spc:SPCState; var dsp:DSPState); stdcall;
SetAPUOpt : procedure (mix,chn,bits,rate,inter,opts:u32); stdcall;
SetAPUSmpClk : procedure (speed:u32); stdcall;
SetAPULength : function (song,fade:u32):u32; stdcall;
SetAPURAM : procedure (addr:u32; val:u8); stdcall;
EmuAPU : function (buf:Pointer; len:u32; t:b8):Pointer; stdcall;
SeekAPU : procedure (time:u32; fast:b8); stdcall;
// SetSPCDbg:procedure(trace:DebugSPC; opts:u32); stdcall;
GetSPCRegs : procedure (var pc:u16; var a,y,x,psw,sp:u8); stdcall;
InPort : procedure (port,val:u32); stdcall;
InPortW : procedure (port,val:u32); stdcall;
EmuSPC : function (cyc:u32):s32; stdcall;
GetProcInfo : function :u32; stdcall;
// SetDSPDbg:procedure(trace:DebugSPC); stdcall;
SetDSPReg : function (reg,val:u8):b8; stdcall;
SetDSPPitch : procedure (base:u32); stdcall;
SetDSPAmp : procedure (level:u32); stdcall;
SetDSPStereo : procedure (sep:u32); stdcall;
SetDSPEFBCT : procedure (leak:s32); stdcall;
EmuDSP : function (buf:Pointer; size:s32):Pointer; stdcall;
PlayWave : function (src:Pointer; loop,rate:u32):Pointer; stdcall;
UnpackWave : function (buf:Pointer; src:Pointer; num,opts:u32; var prev1,prev2:s32):u32; stdcall;
PackWave : procedure (buf:Pointer; smp:Pointer; num,opts:u32; var prev1,prev2:s32); stdcall;
VMax2dB : procedure (list:Pointer; fp:b8); stdcall;
end;
var
APU: SAPUFunc;
// ApuLoaded: Boolean;
implementation
const
SNESAPU_DLL = 'SNESAPU.DLL';
var
hSnesAPU : THandle;
Ver, Min, Opt : u32;
initialization
hSnesAPU := LoadLibrary(SNESAPU_DLL);
if hSnesAPU <> 0 then
begin
Apu.SNESAPUInfo := GetProcAddress(hSnesAPU, 'SNESAPUInfo');
Apu.SNESAPUInfo(Ver, Min, Opt);
if (Ver < $11000) or (Min > $11000) then // Make sure DLL is compatible with v1.1
begin
MessageBox(0, 'This version of SNESAPU.DLL is not compatible.', 'SPCPlayer', MB_OK or MB_ICONERROR);
FreeLibrary(hSnesAPU);
Exit;
end;
end else
begin
MessageBox(0, 'File "SNESAPU.DLL" not found !', 'ERROR', MB_OK or MB_ICONERROR);
// ApuLoaded := False;
Exit;
end;
// ApuLoaded := True;
Apu.BitRateReduce := GetProcAddress(hSnesAPU, 'BitRateReduce');
Apu.SetAPURAM := GetProcAddress(hSnesAPU, 'SetAPURAM');
Apu.InPort := GetProcAddress(hSnesAPU, 'InPort');
Apu.InPortW := GetProcAddress(hSnesAPU, 'InPortW');
Apu.SetDSPReg := GetProcAddress(hSnesAPU, 'SetDSPReg');
Apu.GetAPUData := GetProcAddress(hSnesAPU, 'GetAPUData');
Apu.ResetAPU := GetProcAddress(hSnesAPU, 'ResetAPU');
Apu.FixAPU := GetProcAddress(hSnesAPU, 'FixAPU');
Apu.LoadSPCFile := GetProcAddress(hSnesAPU, 'LoadSPCFile');
Apu.SaveAPU := GetProcAddress(hSnesAPU, 'SaveAPU');
Apu.RestoreAPU := GetProcAddress(hSnesAPU, 'RestoreAPU');
Apu.SetAPUOpt := GetProcAddress(hSnesAPU, 'SetAPUOpt');
Apu.SetAPUSmpClk := GetProcAddress(hSnesAPU, 'SetAPUSmpClk');
Apu.SetAPULength := GetProcAddress(hSnesAPU, 'SetAPULength');
Apu.EmuAPU := GetProcAddress(hSnesAPU, 'EmuAPU');
Apu.SeekAPU := GetProcAddress(hSnesAPU, 'SeekAPU');
Apu.GetSPCRegs := GetProcAddress(hSnesAPU, 'GetSPCRegs');
Apu.EmuSPC := GetProcAddress(hSnesAPU, 'EmuSPC');
Apu.GetProcInfo := GetProcAddress(hSnesAPU, 'GetProcInfo');
Apu.SetDSPPitch := GetProcAddress(hSnesAPU, 'SetDSPPitch');
Apu.SetDSPAmp := GetProcAddress(hSnesAPU, 'SetDSPAmp');
Apu.SetDSPStereo := GetProcAddress(hSnesAPU, 'SetDSPStereo');
Apu.SetDSPEFBCT := GetProcAddress(hSnesAPU, 'SetDSPEFBCT');
Apu.EmuDSP := GetProcAddress(hSnesAPU, 'EmuDSP');
Apu.PlayWave := GetProcAddress(hSnesAPU, 'PlayWave');
Apu.UnpackWave := GetProcAddress(hSnesAPU, 'UnpackWave');
Apu.PackWave := GetProcAddress(hSnesAPU, 'PackWave');
Apu.VMax2dB := GetProcAddress(hSnesAPU, 'VMax2dB');
// Get pointers to necessary data
Apu.GetAPUData(@Apu.ram, @Apu.xram, @Apu.outPort, @Apu.t64Cnt, @Apu.dsp, @Apu.voices, @Apu.vMMaxL, @Apu.vMMaxR);
// SetSPCDbg:procedure(trace:DebugSPC; opts:u32); stdcall;
// SetDSPDbg:procedure(trace:DebugSPC); stdcall;
// Apu.APUIn := GetProcAddress(hSnesAPU, 'APUIn');
// Apu.SetSPCDbg := GetProcAddress(hSnesAPU, 'SetSPCDbg');
// Apu.SPCIn := GetProcAddress(hSnesAPU, 'SPCIn');
// Apu.SPCInW := GetProcAddress(hSnesAPU, 'SPCInW');
// Apu.DSPIn := GetProcAddress(hSnesAPU, 'DSPIn');
{*****************************************************************************}
finalization
if hSnesAPU <> 0 then
FreeLibrary(hSnesAPU);
{*****************************************************************************}
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -