From d4e4912b5bd1f70022567abc3df880f32e174567 Mon Sep 17 00:00:00 2001 From: "SND\\weimingzhi_cp" Date: Sat, 31 Oct 2009 15:48:52 +0000 Subject: git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@34345 e17a0e51-4ae3-4d35-97c3-1a29b211df97 --- .../plugins/PeopsSpu109/English.lproj/Credits.rtf | 14 + .../PeopsSpu109/English.lproj/InfoPlist.strings | Bin 0 -> 630 bytes .../NetSfPeopsSpuPluginMain.nib/classes.nib | 26 + .../NetSfPeopsSpuPluginMain.nib/info.nib | 16 + .../NetSfPeopsSpuPluginMain.nib/keyedobjects.nib | Bin 0 -> 9698 bytes macosx/plugins/PeopsSpu109/Info.plist | 22 + .../PeopsSpu109/PeopsSPU.xcodeproj/project.pbxproj | 381 ++++++ macosx/plugins/PeopsSpu109/macsrc/NamedSlider.h | 13 + macosx/plugins/PeopsSpu109/macsrc/NamedSlider.m | 33 + .../plugins/PeopsSpu109/macsrc/PluginController.h | 29 + .../plugins/PeopsSpu109/macsrc/PluginController.m | 166 +++ macosx/plugins/PeopsSpu109/src/adsr.c | 636 +++++++++ macosx/plugins/PeopsSpu109/src/adsr.h | 28 + macosx/plugins/PeopsSpu109/src/dma.c | 117 ++ macosx/plugins/PeopsSpu109/src/dma.h | 31 + macosx/plugins/PeopsSpu109/src/externals.h | 344 +++++ macosx/plugins/PeopsSpu109/src/freeze.c | 234 ++++ macosx/plugins/PeopsSpu109/src/gauss_i.h | 162 +++ macosx/plugins/PeopsSpu109/src/macosx.c | 203 +++ macosx/plugins/PeopsSpu109/src/psemu.c | 109 ++ macosx/plugins/PeopsSpu109/src/psemuxa.h | 28 + macosx/plugins/PeopsSpu109/src/registers.c | 615 +++++++++ macosx/plugins/PeopsSpu109/src/registers.h | 153 +++ macosx/plugins/PeopsSpu109/src/regs.h | 36 + macosx/plugins/PeopsSpu109/src/resource.h | 148 +++ macosx/plugins/PeopsSpu109/src/reverb.c | 480 +++++++ macosx/plugins/PeopsSpu109/src/reverb.h | 30 + macosx/plugins/PeopsSpu109/src/spu.c | 1359 ++++++++++++++++++++ macosx/plugins/PeopsSpu109/src/spu.h | 30 + macosx/plugins/PeopsSpu109/src/stdafx.h | 53 + macosx/plugins/PeopsSpu109/src/swap.h | 21 + macosx/plugins/PeopsSpu109/src/xa.c | 367 ++++++ macosx/plugins/PeopsSpu109/src/xa.h | 29 + macosx/plugins/PeopsSpu109/src/zn.c | 183 +++ 34 files changed, 6096 insertions(+) create mode 100644 macosx/plugins/PeopsSpu109/English.lproj/Credits.rtf create mode 100755 macosx/plugins/PeopsSpu109/English.lproj/InfoPlist.strings create mode 100644 macosx/plugins/PeopsSpu109/English.lproj/NetSfPeopsSpuPluginMain.nib/classes.nib create mode 100644 macosx/plugins/PeopsSpu109/English.lproj/NetSfPeopsSpuPluginMain.nib/info.nib create mode 100755 macosx/plugins/PeopsSpu109/English.lproj/NetSfPeopsSpuPluginMain.nib/keyedobjects.nib create mode 100644 macosx/plugins/PeopsSpu109/Info.plist create mode 100644 macosx/plugins/PeopsSpu109/PeopsSPU.xcodeproj/project.pbxproj create mode 100644 macosx/plugins/PeopsSpu109/macsrc/NamedSlider.h create mode 100644 macosx/plugins/PeopsSpu109/macsrc/NamedSlider.m create mode 100644 macosx/plugins/PeopsSpu109/macsrc/PluginController.h create mode 100644 macosx/plugins/PeopsSpu109/macsrc/PluginController.m create mode 100755 macosx/plugins/PeopsSpu109/src/adsr.c create mode 100755 macosx/plugins/PeopsSpu109/src/adsr.h create mode 100755 macosx/plugins/PeopsSpu109/src/dma.c create mode 100755 macosx/plugins/PeopsSpu109/src/dma.h create mode 100755 macosx/plugins/PeopsSpu109/src/externals.h create mode 100755 macosx/plugins/PeopsSpu109/src/freeze.c create mode 100755 macosx/plugins/PeopsSpu109/src/gauss_i.h create mode 100755 macosx/plugins/PeopsSpu109/src/macosx.c create mode 100755 macosx/plugins/PeopsSpu109/src/psemu.c create mode 100755 macosx/plugins/PeopsSpu109/src/psemuxa.h create mode 100755 macosx/plugins/PeopsSpu109/src/registers.c create mode 100755 macosx/plugins/PeopsSpu109/src/registers.h create mode 100755 macosx/plugins/PeopsSpu109/src/regs.h create mode 100755 macosx/plugins/PeopsSpu109/src/resource.h create mode 100755 macosx/plugins/PeopsSpu109/src/reverb.c create mode 100755 macosx/plugins/PeopsSpu109/src/reverb.h create mode 100755 macosx/plugins/PeopsSpu109/src/spu.c create mode 100755 macosx/plugins/PeopsSpu109/src/spu.h create mode 100755 macosx/plugins/PeopsSpu109/src/stdafx.h create mode 100755 macosx/plugins/PeopsSpu109/src/swap.h create mode 100755 macosx/plugins/PeopsSpu109/src/xa.c create mode 100755 macosx/plugins/PeopsSpu109/src/xa.h create mode 100755 macosx/plugins/PeopsSpu109/src/zn.c (limited to 'macosx/plugins') diff --git a/macosx/plugins/PeopsSpu109/English.lproj/Credits.rtf b/macosx/plugins/PeopsSpu109/English.lproj/Credits.rtf new file mode 100644 index 00000000..209850ac --- /dev/null +++ b/macosx/plugins/PeopsSpu109/English.lproj/Credits.rtf @@ -0,0 +1,14 @@ +{\rtf1\mac\ansicpg10000\cocoartf102 +{\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\vieww9000\viewh9000\viewkind0 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\f0\b\fs24 \cf0 Macintosh Port: +\f1\b0 \ + Gil Pedersen\ +\ + +\f0\b Original coders: +\f1\b0 \ + Pete Bernert and the P.E.Op.S. team} \ No newline at end of file diff --git a/macosx/plugins/PeopsSpu109/English.lproj/InfoPlist.strings b/macosx/plugins/PeopsSpu109/English.lproj/InfoPlist.strings new file mode 100755 index 00000000..e2602707 Binary files /dev/null and b/macosx/plugins/PeopsSpu109/English.lproj/InfoPlist.strings differ diff --git a/macosx/plugins/PeopsSpu109/English.lproj/NetSfPeopsSpuPluginMain.nib/classes.nib b/macosx/plugins/PeopsSpu109/English.lproj/NetSfPeopsSpuPluginMain.nib/classes.nib new file mode 100644 index 00000000..3a8b25b3 --- /dev/null +++ b/macosx/plugins/PeopsSpu109/English.lproj/NetSfPeopsSpuPluginMain.nib/classes.nib @@ -0,0 +1,26 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + ACTIONS = {cancel = id; ok = id; reset = id; }; + CLASS = NetSfPeopsSPUPluginController; + LANGUAGE = ObjC; + OUTLETS = { + hiCompBox = NSControl; + interpolValue = NetSfPeopsSPUPluginNamedSlider; + irqWaitBox = NetSfPeopsSPUPluginNamedSlider; + monoSoundBox = NSControl; + reverbValue = NSControl; + xaEnableBox = NSControl; + xaSpeedBox = NSControl; + }; + SUPERCLASS = NSWindowController; + }, + { + CLASS = NetSfPeopsSPUPluginNamedSlider; + LANGUAGE = ObjC; + SUPERCLASS = NSSlider; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/macosx/plugins/PeopsSpu109/English.lproj/NetSfPeopsSpuPluginMain.nib/info.nib b/macosx/plugins/PeopsSpu109/English.lproj/NetSfPeopsSpuPluginMain.nib/info.nib new file mode 100644 index 00000000..e32820d1 --- /dev/null +++ b/macosx/plugins/PeopsSpu109/English.lproj/NetSfPeopsSpuPluginMain.nib/info.nib @@ -0,0 +1,16 @@ + + + + + IBDocumentLocation + 42 12 546 240 0 0 1024 746 + IBFramework Version + 364.0 + IBOpenObjects + + 6 + + IBSystem Version + 7S215 + + diff --git a/macosx/plugins/PeopsSpu109/English.lproj/NetSfPeopsSpuPluginMain.nib/keyedobjects.nib b/macosx/plugins/PeopsSpu109/English.lproj/NetSfPeopsSpuPluginMain.nib/keyedobjects.nib new file mode 100755 index 00000000..80615cb1 Binary files /dev/null and b/macosx/plugins/PeopsSpu109/English.lproj/NetSfPeopsSpuPluginMain.nib/keyedobjects.nib differ diff --git a/macosx/plugins/PeopsSpu109/Info.plist b/macosx/plugins/PeopsSpu109/Info.plist new file mode 100644 index 00000000..88cf687f --- /dev/null +++ b/macosx/plugins/PeopsSpu109/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + PeopsSPU + CFBundleIconFile + + CFBundleIdentifier + net.sf.peops.SPUPlugin + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + PsxP + CFBundleSignature + PSPU + CFBundleVersion + 1.19 + + diff --git a/macosx/plugins/PeopsSpu109/PeopsSPU.xcodeproj/project.pbxproj b/macosx/plugins/PeopsSpu109/PeopsSPU.xcodeproj/project.pbxproj new file mode 100644 index 00000000..e825ad34 --- /dev/null +++ b/macosx/plugins/PeopsSpu109/PeopsSPU.xcodeproj/project.pbxproj @@ -0,0 +1,381 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + 2B4F9962077B042E004E36BA /* NetSfPeopsSpuPluginMain.nib in Resources */ = {isa = PBXBuildFile; fileRef = 2B4F9961077B042E004E36BA /* NetSfPeopsSpuPluginMain.nib */; }; + 2B4F99F9077B0CE4004E36BA /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 2B4F99F7077B0CE4004E36BA /* Credits.rtf */; }; + 2B7B2B94072D9BE6007F0C35 /* PluginController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B7B2B92072D9BE6007F0C35 /* PluginController.m */; }; + 2B7B2BD1072DAE5D007F0C35 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2B7B2BD0072DAE5D007F0C35 /* AppKit.framework */; }; + 2B7B2BE9072DB1B6007F0C35 /* NamedSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B7B2BE7072DB1B6007F0C35 /* NamedSlider.m */; }; + 2B84C132071D95EC00FA11D7 /* zn.c in Sources */ = {isa = PBXBuildFile; fileRef = 2B84C131071D95EC00FA11D7 /* zn.c */; }; + 2BE18A00077EED7F008688C9 /* macosx.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BFF7EFC0715D16A0061278A /* macosx.c */; }; + 2BFF7F190715D16B0061278A /* dma.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BFF7EF40715D16A0061278A /* dma.c */; }; + 2BFF7F1E0715D16B0061278A /* freeze.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BFF7EF90715D16A0061278A /* freeze.c */; }; + 2BFF7F250715D16B0061278A /* psemu.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BFF7F000715D16A0061278A /* psemu.c */; }; + 2BFF7F290715D16B0061278A /* registers.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BFF7F040715D16A0061278A /* registers.c */; }; + 2BFF7F2F0715D16B0061278A /* spu.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BFF7F0A0715D16A0061278A /* spu.c */; }; + 2BFF7F3E0715D2E00061278A /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BFF7F3D0715D2E00061278A /* Carbon.framework */; }; + 8D576314048677EA00EA77CD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */; }; + 8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8D5B49A704867FD3000E48DA /* InfoPlist.strings */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; + 0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; + 2B4F99F8077B0CE4004E36BA /* English */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = English; path = English.lproj/Credits.rtf; sourceTree = ""; }; + 2B6DA89307200A9A009F6FED /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/NetSfPeopsSpuPluginMain.nib; sourceTree = ""; }; + 2B7B2B91072D9BE6007F0C35 /* PluginController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PluginController.h; path = macsrc/PluginController.h; sourceTree = ""; }; + 2B7B2B92072D9BE6007F0C35 /* PluginController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = PluginController.m; path = macsrc/PluginController.m; sourceTree = ""; }; + 2B7B2BD0072DAE5D007F0C35 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + 2B7B2BE6072DB1B6007F0C35 /* NamedSlider.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = NamedSlider.h; path = macsrc/NamedSlider.h; sourceTree = ""; }; + 2B7B2BE7072DB1B6007F0C35 /* NamedSlider.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = NamedSlider.m; path = macsrc/NamedSlider.m; sourceTree = ""; }; + 2B84C131071D95EC00FA11D7 /* zn.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = zn.c; path = src/zn.c; sourceTree = ""; }; + 2BFF7EF40715D16A0061278A /* dma.c */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.c; name = dma.c; path = src/dma.c; sourceTree = ""; }; + 2BFF7EF50715D16A0061278A /* dma.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; name = dma.h; path = src/dma.h; sourceTree = ""; }; + 2BFF7EF80715D16A0061278A /* externals.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; name = externals.h; path = src/externals.h; sourceTree = ""; }; + 2BFF7EF90715D16A0061278A /* freeze.c */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.c; name = freeze.c; path = src/freeze.c; sourceTree = ""; }; + 2BFF7EFB0715D16A0061278A /* gauss_i.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; name = gauss_i.h; path = src/gauss_i.h; sourceTree = ""; }; + 2BFF7EFC0715D16A0061278A /* macosx.c */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.c; name = macosx.c; path = src/macosx.c; sourceTree = ""; }; + 2BFF7F000715D16A0061278A /* psemu.c */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.c; name = psemu.c; path = src/psemu.c; sourceTree = ""; }; + 2BFF7F010715D16A0061278A /* psemuxa.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; name = psemuxa.h; path = src/psemuxa.h; sourceTree = ""; }; + 2BFF7F040715D16A0061278A /* registers.c */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.c; name = registers.c; path = src/registers.c; sourceTree = ""; }; + 2BFF7F050715D16A0061278A /* registers.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; name = registers.h; path = src/registers.h; sourceTree = ""; }; + 2BFF7F060715D16A0061278A /* regs.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; name = regs.h; path = src/regs.h; sourceTree = ""; }; + 2BFF7F070715D16A0061278A /* resource.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; name = resource.h; path = src/resource.h; sourceTree = ""; }; + 2BFF7F0A0715D16A0061278A /* spu.c */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.c; name = spu.c; path = src/spu.c; sourceTree = ""; }; + 2BFF7F0B0715D16A0061278A /* spu.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; name = spu.h; path = src/spu.h; sourceTree = ""; }; + 2BFF7F0D0715D16B0061278A /* stdafx.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; name = stdafx.h; path = src/stdafx.h; sourceTree = ""; }; + 2BFF7F0E0715D16B0061278A /* swap.h */ = {isa = PBXFileReference; fileEncoding = 12; lastKnownFileType = sourcecode.c.h; name = swap.h; path = src/swap.h; sourceTree = ""; }; + 2BFF7F3D0715D2E00061278A /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; + 7146B70B0FDFBD5600D5203B /* adsr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = adsr.c; path = src/adsr.c; sourceTree = ""; }; + 7146B70C0FDFBD5600D5203B /* adsr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = adsr.h; path = src/adsr.h; sourceTree = ""; }; + 7146B70D0FDFBD5600D5203B /* reverb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = reverb.c; path = src/reverb.c; sourceTree = ""; }; + 7146B70E0FDFBD5600D5203B /* reverb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = reverb.h; path = src/reverb.h; sourceTree = ""; }; + 7146B70F0FDFBD5600D5203B /* xa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xa.c; path = src/xa.c; sourceTree = ""; }; + 7146B7100FDFBD5600D5203B /* xa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xa.h; path = src/xa.h; sourceTree = ""; }; + 8D576316048677EA00EA77CD /* PeopsSPU.psxplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PeopsSPU.psxplugin; sourceTree = BUILT_PRODUCTS_DIR; }; + 8D576317048677EA00EA77CD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8D576313048677EA00EA77CD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D576314048677EA00EA77CD /* CoreFoundation.framework in Frameworks */, + 2BFF7F3E0715D2E00061278A /* Carbon.framework in Frameworks */, + 2B7B2BD1072DAE5D007F0C35 /* AppKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 089C166AFE841209C02AAC07 /* PSX Plugin */ = { + isa = PBXGroup; + children = ( + 08FB77AFFE84173DC02AAC07 /* Source */, + 2B7B2B8E072D9BD6007F0C35 /* Classes */, + 089C167CFE841241C02AAC07 /* Resources */, + 089C1671FE841209C02AAC07 /* External Frameworks and Libraries */, + 19C28FB6FE9D52B211CA2CBB /* Products */, + ); + name = "PSX Plugin"; + sourceTree = ""; + }; + 089C1671FE841209C02AAC07 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + 2B7B2BD0072DAE5D007F0C35 /* AppKit.framework */, + 2BFF7F3D0715D2E00061278A /* Carbon.framework */, + 0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; + 089C167CFE841241C02AAC07 /* Resources */ = { + isa = PBXGroup; + children = ( + 8D576317048677EA00EA77CD /* Info.plist */, + 2B4F99F7077B0CE4004E36BA /* Credits.rtf */, + 8D5B49A704867FD3000E48DA /* InfoPlist.strings */, + 2B4F9961077B042E004E36BA /* NetSfPeopsSpuPluginMain.nib */, + ); + name = Resources; + sourceTree = ""; + }; + 08FB77AFFE84173DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + 7146B70B0FDFBD5600D5203B /* adsr.c */, + 7146B70C0FDFBD5600D5203B /* adsr.h */, + 7146B70D0FDFBD5600D5203B /* reverb.c */, + 7146B70E0FDFBD5600D5203B /* reverb.h */, + 7146B70F0FDFBD5600D5203B /* xa.c */, + 7146B7100FDFBD5600D5203B /* xa.h */, + 2BFF7EF40715D16A0061278A /* dma.c */, + 2BFF7EF50715D16A0061278A /* dma.h */, + 2BFF7EF80715D16A0061278A /* externals.h */, + 2BFF7EF90715D16A0061278A /* freeze.c */, + 2BFF7EFB0715D16A0061278A /* gauss_i.h */, + 2BFF7EFC0715D16A0061278A /* macosx.c */, + 2BFF7F000715D16A0061278A /* psemu.c */, + 2BFF7F010715D16A0061278A /* psemuxa.h */, + 2BFF7F040715D16A0061278A /* registers.c */, + 2BFF7F050715D16A0061278A /* registers.h */, + 2BFF7F060715D16A0061278A /* regs.h */, + 2BFF7F070715D16A0061278A /* resource.h */, + 2BFF7F0A0715D16A0061278A /* spu.c */, + 2BFF7F0B0715D16A0061278A /* spu.h */, + 2BFF7F0D0715D16B0061278A /* stdafx.h */, + 2BFF7F0E0715D16B0061278A /* swap.h */, + 2B84C131071D95EC00FA11D7 /* zn.c */, + ); + name = Source; + sourceTree = ""; + }; + 19C28FB6FE9D52B211CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8D576316048677EA00EA77CD /* PeopsSPU.psxplugin */, + ); + name = Products; + sourceTree = ""; + }; + 2B7B2B8E072D9BD6007F0C35 /* Classes */ = { + isa = PBXGroup; + children = ( + 2B7B2B91072D9BE6007F0C35 /* PluginController.h */, + 2B7B2B92072D9BE6007F0C35 /* PluginController.m */, + 2B7B2BE6072DB1B6007F0C35 /* NamedSlider.h */, + 2B7B2BE7072DB1B6007F0C35 /* NamedSlider.m */, + ); + name = Classes; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8D57630D048677EA00EA77CD /* PeopsSPU */ = { + isa = PBXNativeTarget; + buildConfigurationList = 71155B260FDFA2EB00EC0BC5 /* Build configuration list for PBXNativeTarget "PeopsSPU" */; + buildPhases = ( + 8D57630F048677EA00EA77CD /* Resources */, + 8D576311048677EA00EA77CD /* Sources */, + 8D576313048677EA00EA77CD /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PeopsSPU; + productInstallPath = "$(HOME)/Library/Bundles"; + productName = "PSX Plugin"; + productReference = 8D576316048677EA00EA77CD /* PeopsSPU.psxplugin */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 089C1669FE841209C02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 71155B2B0FDFA2EB00EC0BC5 /* Build configuration list for PBXProject "PeopsSPU" */; + hasScannedForEncodings = 1; + mainGroup = 089C166AFE841209C02AAC07 /* PSX Plugin */; + projectDirPath = ""; + targets = ( + 8D57630D048677EA00EA77CD /* PeopsSPU */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8D57630F048677EA00EA77CD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */, + 2B4F9962077B042E004E36BA /* NetSfPeopsSpuPluginMain.nib in Resources */, + 2B4F99F9077B0CE4004E36BA /* Credits.rtf in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8D576311048677EA00EA77CD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2BFF7F190715D16B0061278A /* dma.c in Sources */, + 2BFF7F1E0715D16B0061278A /* freeze.c in Sources */, + 2BFF7F250715D16B0061278A /* psemu.c in Sources */, + 2BFF7F290715D16B0061278A /* registers.c in Sources */, + 2BFF7F2F0715D16B0061278A /* spu.c in Sources */, + 2B84C132071D95EC00FA11D7 /* zn.c in Sources */, + 2B7B2B94072D9BE6007F0C35 /* PluginController.m in Sources */, + 2B7B2BE9072DB1B6007F0C35 /* NamedSlider.m in Sources */, + 2BE18A00077EED7F008688C9 /* macosx.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 2B4F9961077B042E004E36BA /* NetSfPeopsSpuPluginMain.nib */ = { + isa = PBXVariantGroup; + children = ( + 2B6DA89307200A9A009F6FED /* English */, + ); + name = NetSfPeopsSpuPluginMain.nib; + sourceTree = ""; + }; + 2B4F99F7077B0CE4004E36BA /* Credits.rtf */ = { + isa = PBXVariantGroup; + children = ( + 2B4F99F8077B0CE4004E36BA /* English */, + ); + name = Credits.rtf; + sourceTree = ""; + }; + 8D5B49A704867FD3000E48DA /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 089C167EFE841241C02AAC07 /* English */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 71155B270FDFA2EB00EC0BC5 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = ""; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = _MACOSX; + HEADER_SEARCH_PATHS = src/; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(USER_LIBRARY_DIR)/Playstation Emulator Plugins"; + LIBRARY_STYLE = BUNDLE; + PRODUCT_NAME = PeopsSPU; + WRAPPER_EXTENSION = psxplugin; + ZERO_LINK = NO; + }; + name = Development; + }; + 71155B280FDFA2EB00EC0BC5 /* Beta */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = ""; + GCC_OPTIMIZATION_LEVEL = s; + GCC_PREPROCESSOR_DEFINITIONS = _MACOSX; + HEADER_SEARCH_PATHS = src/; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(USER_LIBRARY_DIR)/Playstation Emulator Plugins"; + LIBRARY_STYLE = BUNDLE; + PRODUCT_NAME = PeopsSPU; + WRAPPER_EXTENSION = psxplugin; + ZERO_LINK = NO; + }; + name = Beta; + }; + 71155B290FDFA2EB00EC0BC5 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + DEBUGGING_SYMBOLS = NO; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = ""; + GCC_PREPROCESSOR_DEFINITIONS = _MACOSX; + HEADER_SEARCH_PATHS = src/; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(USER_LIBRARY_DIR)/Playstation Emulator Plugins"; + LIBRARY_STYLE = BUNDLE; + PRODUCT_NAME = PeopsSPU; + WRAPPER_EXTENSION = psxplugin; + ZERO_LINK = NO; + }; + name = Deployment; + }; + 71155B2A0FDFA2EB00EC0BC5 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = ""; + GCC_PREPROCESSOR_DEFINITIONS = _MACOSX; + HEADER_SEARCH_PATHS = src/; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(USER_LIBRARY_DIR)/Playstation Emulator Plugins"; + LIBRARY_STYLE = BUNDLE; + PRODUCT_NAME = PeopsSPU; + WRAPPER_EXTENSION = psxplugin; + }; + name = Default; + }; + 71155B2C0FDFA2EB00EC0BC5 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Development; + }; + 71155B2D0FDFA2EB00EC0BC5 /* Beta */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Beta; + }; + 71155B2E0FDFA2EB00EC0BC5 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Deployment; + }; + 71155B2F0FDFA2EB00EC0BC5 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Default; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 71155B260FDFA2EB00EC0BC5 /* Build configuration list for PBXNativeTarget "PeopsSPU" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 71155B270FDFA2EB00EC0BC5 /* Development */, + 71155B280FDFA2EB00EC0BC5 /* Beta */, + 71155B290FDFA2EB00EC0BC5 /* Deployment */, + 71155B2A0FDFA2EB00EC0BC5 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + 71155B2B0FDFA2EB00EC0BC5 /* Build configuration list for PBXProject "PeopsSPU" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 71155B2C0FDFA2EB00EC0BC5 /* Development */, + 71155B2D0FDFA2EB00EC0BC5 /* Beta */, + 71155B2E0FDFA2EB00EC0BC5 /* Deployment */, + 71155B2F0FDFA2EB00EC0BC5 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; +/* End XCConfigurationList section */ + }; + rootObject = 089C1669FE841209C02AAC07 /* Project object */; +} diff --git a/macosx/plugins/PeopsSpu109/macsrc/NamedSlider.h b/macosx/plugins/PeopsSpu109/macsrc/NamedSlider.h new file mode 100644 index 00000000..c5a40aa0 --- /dev/null +++ b/macosx/plugins/PeopsSpu109/macsrc/NamedSlider.h @@ -0,0 +1,13 @@ +/* NetSfPeopsSPUPluginNamedSlider */ + +#import + +#define NamedSlider NetSfPeopsSPUPluginNamedSlider + +@interface NamedSlider : NSSlider +{ + NSArray *strings; +} + +- (void)setStrings:(NSArray *)theStrings; +@end diff --git a/macosx/plugins/PeopsSpu109/macsrc/NamedSlider.m b/macosx/plugins/PeopsSpu109/macsrc/NamedSlider.m new file mode 100644 index 00000000..fd07780a --- /dev/null +++ b/macosx/plugins/PeopsSpu109/macsrc/NamedSlider.m @@ -0,0 +1,33 @@ +#import "NamedSlider.h" + +@implementation NamedSlider + +- (void)dealloc +{ + [strings release]; + [super dealloc]; +} + +- (void)setStrings:(NSArray *)theStrings +{ + [strings release]; + strings = [theStrings retain]; +} + +- (NSString *)stringValue +{ + int index = [self intValue]; + + if (index >= 0 && index < [strings count]) + return [strings objectAtIndex:index]; + + return @"(Unknown)"; +} + +- (void)setIntValue:(int)value +{ + [super setIntValue:value]; + [self sendAction:[self action] to:[self target]]; +} + +@end diff --git a/macosx/plugins/PeopsSpu109/macsrc/PluginController.h b/macosx/plugins/PeopsSpu109/macsrc/PluginController.h new file mode 100644 index 00000000..36373b1d --- /dev/null +++ b/macosx/plugins/PeopsSpu109/macsrc/PluginController.h @@ -0,0 +1,29 @@ +/* NetSfPeopsSPUPluginController */ + +#import +#import "NamedSlider.h" + +void DoAbout(); +long DoConfiguration(); +void LoadConfiguration(); + +#define PluginController NetSfPeopsSPUPluginController + +@interface PluginController : NSWindowController +{ + IBOutlet NSControl *hiCompBox; + IBOutlet NetSfPeopsSPUPluginNamedSlider *interpolValue; + IBOutlet NSControl *irqWaitBox; + IBOutlet NSControl *monoSoundBox; + IBOutlet NetSfPeopsSPUPluginNamedSlider *reverbValue; + IBOutlet NSControl *xaEnableBox; + IBOutlet NSControl *xaSpeedBox; + + NSMutableDictionary *keyValues; +} +- (IBAction)cancel:(id)sender; +- (IBAction)ok:(id)sender; +- (IBAction)reset:(id)sender; + +- (void)loadValues; +@end diff --git a/macosx/plugins/PeopsSpu109/macsrc/PluginController.m b/macosx/plugins/PeopsSpu109/macsrc/PluginController.m new file mode 100644 index 00000000..84d898dc --- /dev/null +++ b/macosx/plugins/PeopsSpu109/macsrc/PluginController.m @@ -0,0 +1,166 @@ +#import "PluginController.h" +#include "stdafx.h" +#include "externals.h" + +#define APP_ID @"net.sf.peops.SPUPlugin" +#define PrefsKey APP_ID @" Settings" + +static PluginController *pluginController; +char * pConfigFile=NULL; + +void DoAbout() +{ + // Get parent application instance + NSApplication *app = [NSApplication sharedApplication]; + NSBundle *bundle = [NSBundle bundleWithIdentifier:APP_ID]; + + // Get Credits.rtf + NSString *path = [bundle pathForResource:@"Credits" ofType:@"rtf"]; + NSAttributedString *credits; + if (path) { + credits = [[[NSAttributedString alloc] initWithPath: path + documentAttributes:NULL] autorelease]; + } else { + credits = [[[NSAttributedString alloc] initWithString:@""] autorelease]; + } + + // Get Application Icon + NSImage *icon = [[NSWorkspace sharedWorkspace] iconForFile:[bundle bundlePath]]; + NSSize size = NSMakeSize(64, 64); + [icon setSize:size]; + + [app orderFrontStandardAboutPanelWithOptions:[NSDictionary dictionaryWithObjectsAndKeys: + [bundle objectForInfoDictionaryKey:@"CFBundleName"], @"ApplicationName", + icon, @"ApplicationIcon", + [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"], @"ApplicationVersion", + [bundle objectForInfoDictionaryKey:@"CFBundleVersion"], @"Version", + [bundle objectForInfoDictionaryKey:@"NSHumanReadableCopyright"], @"Copyright", + credits, @"Credits", + nil]]; +} + + +long DoConfiguration() +{ + NSWindow *window; + + if (pluginController == nil) { + pluginController = [[PluginController alloc] initWithWindowNibName:@"NetSfPeopsSpuPluginMain"]; + } + window = [pluginController window]; + + /* load values */ + [pluginController loadValues]; + + [window center]; + [window makeKeyAndOrderFront:nil]; + + return 0; +} + +void ReadConfig(void) +{ + NSDictionary *keyValues; + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + [defaults registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys: + [[NSMutableDictionary alloc] initWithObjectsAndKeys: + [NSNumber numberWithBool:YES], @"High Compatibility Mode", + [NSNumber numberWithBool:YES], @"SPU IRQ Wait", + [NSNumber numberWithBool:YES], @"Enable XA", + [NSNumber numberWithBool:NO], @"XA Pitch", + //[NSNumber numberWithBool:YES], @"Decoded Buffer IRQ", + [NSNumber numberWithInt:0], @"Interpolation Quality", + [NSNumber numberWithInt:1], @"Reverb Quality", + nil], PrefsKey, + nil]]; + + keyValues = [defaults dictionaryForKey:PrefsKey]; + + iUseTimer = [[keyValues objectForKey:@"High Compatibility Mode"] boolValue] ? 2 : 0; + iSPUIRQWait = [[keyValues objectForKey:@"SPU IRQ Wait"] boolValue]; + iDisStereo = [[keyValues objectForKey:@"Mono Sound Output"] boolValue]; + iUseXA = [[keyValues objectForKey:@"Enable XA"] boolValue]; + iXAPitch = [[keyValues objectForKey:@"XA Pitch"] boolValue]; + iUseDBufIrq = 1;//[[keyValues objectForKey:@"Decoded Buffer IRQ"] boolValue]; + + iUseInterpolation = [[keyValues objectForKey:@"Interpolation Quality"] intValue]; + iUseReverb = [[keyValues objectForKey:@"Reverb Quality"] intValue]; + + iVolume=1; +} + +@implementation PluginController + +- (IBAction)cancel:(id)sender +{ + [self close]; +} + +- (IBAction)ok:(id)sender +{ + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + + NSMutableDictionary *writeDic = [NSMutableDictionary dictionaryWithDictionary:keyValues]; + [writeDic setObject:[NSNumber numberWithInt:[hiCompBox intValue]] forKey:@"High Compatibility Mode"]; + [writeDic setObject:[NSNumber numberWithInt:[irqWaitBox intValue]] forKey:@"SPU IRQ Wait"]; + [writeDic setObject:[NSNumber numberWithInt:[monoSoundBox intValue]] forKey:@"Mono Sound Output"]; + [writeDic setObject:[NSNumber numberWithInt:[xaEnableBox intValue]] forKey:@"Enable XA"]; + [writeDic setObject:[NSNumber numberWithInt:[xaSpeedBox intValue]] forKey:@"XA Pitch"]; + + [writeDic setObject:[NSNumber numberWithInt:[interpolValue intValue]] forKey:@"Interpolation Quality"]; + [writeDic setObject:[NSNumber numberWithInt:[reverbValue intValue]] forKey:@"Reverb Quality"]; + + // write to defaults + [defaults setObject:writeDic forKey:PrefsKey]; + [defaults synchronize]; + + // and set global values accordingly + ReadConfig(); + + [self close]; +} + +- (IBAction)reset:(id)sender +{ + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + [defaults removeObjectForKey:PrefsKey]; + [self loadValues]; +} + +- (void)loadValues +{ + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + + ReadConfig(); + + /* load from preferences */ + [keyValues release]; + keyValues = [[defaults dictionaryForKey:PrefsKey] retain]; + + [hiCompBox setIntValue:[[keyValues objectForKey:@"High Compatibility Mode"] intValue]]; + [irqWaitBox setIntValue:[[keyValues objectForKey:@"SPU IRQ Wait"] intValue]]; + [monoSoundBox setIntValue:[[keyValues objectForKey:@"Mono Sound Output"] intValue]]; + [xaEnableBox setIntValue:[[keyValues objectForKey:@"Enable XA"] intValue]]; + [xaSpeedBox setIntValue:[[keyValues objectForKey:@"XA Pitch"] intValue]]; + + [interpolValue setIntValue:[[keyValues objectForKey:@"Interpolation Quality"] intValue]]; + [reverbValue setIntValue:[[keyValues objectForKey:@"Reverb Quality"] intValue]]; +} + +- (void)awakeFromNib +{ + [interpolValue setStrings:[NSArray arrayWithObjects: + @"(No Interpolation)", + @"(Simple Interpolation)", + @"(Gaussian Interpolation)", + @"(Cubic Interpolation)", + nil]]; + + [reverbValue setStrings:[NSArray arrayWithObjects: + @"(No Reverb)", + @"(Simple Reverb)", + @"(PSX Reverb)", + nil]]; +} + +@end diff --git a/macosx/plugins/PeopsSpu109/src/adsr.c b/macosx/plugins/PeopsSpu109/src/adsr.c new file mode 100755 index 00000000..9a3ad0aa --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/adsr.c @@ -0,0 +1,636 @@ +/*************************************************************************** + adsr.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/09/18 - LDChen +// - Speed optimized ADSR mixing +// +// 2003/05/14 - xodnizel +// - removed stopping of reverb on sample end +// +// 2003/01/06 - Pete +// - added Neill's ADSR timings +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_ADSR + +// will be included from spu.c +#ifdef _IN_SPU + +//////////////////////////////////////////////////////////////////////// +// ADSR func +//////////////////////////////////////////////////////////////////////// + +static unsigned long int RateTable[160]; + +void InitADSR(void) // INIT ADSR +{ + unsigned long r,rs,rd;int i; + + memset(RateTable,0,sizeof(unsigned long)*160); // build the rate table according to Neill's rules (see at bottom of file) + + r=3;rs=1;rd=0; + + for(i=32;i<160;i++) // we start at pos 32 with the real values... everything before is 0 + { + if(r<0x3FFFFFFF) + { + r+=rs; + rd++;if(rd==5) {rd=1;rs*=2;} + } + if(r>0x3FFFFFFF) r=0x3FFFFFFF; + + RateTable[i]=r; + } +} + +//////////////////////////////////////////////////////////////////////// + +INLINE void StartADSR(SPUCHAN * pChannel) // MIX ADSR +{ + pChannel->ADSRX.lVolume=1; // and init some adsr vars + pChannel->ADSRX.State=0; + pChannel->ADSRX.EnvelopeVol=0; +} + +//////////////////////////////////////////////////////////////////////// + +static const unsigned long int TableDisp[] = { + -0x18+0+32,-0x18+4+32,-0x18+6+32,-0x18+8+32, // release/decay + -0x18+9+32,-0x18+10+32,-0x18+11+32,-0x18+12+32, + + -0x1B+0+32,-0x1B+4+32,-0x1B+6+32,-0x1B+8+32, // sustain + -0x1B+9+32,-0x1B+10+32,-0x1B+11+32,-0x1B+12+32, +}; + +INLINE int MixADSR(SPUCHAN *ch) +{ + unsigned long int disp; + signed long int EnvelopeVol = ch->ADSRX.EnvelopeVol; + + if(ch->bStop) // should be stopped: + { // do release + if(ch->ADSRX.ReleaseModeExp) + { + disp = TableDisp[(EnvelopeVol>>28)&0x7]; + } + else + { + disp=-0x0C+32; + } + EnvelopeVol-=RateTable[ch->ADSRX.ReleaseRate + disp]; + + if(EnvelopeVol<0) + { + EnvelopeVol=0; + ch->bOn=0; + } + + ch->ADSRX.EnvelopeVol=EnvelopeVol; + ch->ADSRX.lVolume=(EnvelopeVol>>=21); + return EnvelopeVol; + } + else // not stopped yet? + { + if(ch->ADSRX.State==0) // -> attack + { + disp = -0x10+32; + if(ch->ADSRX.AttackModeExp) + { + if(EnvelopeVol>=0x60000000) + disp = -0x18+32; + } + EnvelopeVol+=RateTable[ch->ADSRX.AttackRate+disp]; + + if(EnvelopeVol<0) + { + EnvelopeVol=0x7FFFFFFF; + ch->ADSRX.State=1; + } + + ch->ADSRX.EnvelopeVol=EnvelopeVol; + ch->ADSRX.lVolume=(EnvelopeVol>>=21); + return EnvelopeVol; + } + //--------------------------------------------------// + if(ch->ADSRX.State==1) // -> decay + { + disp = TableDisp[(EnvelopeVol>>28)&0x7]; + EnvelopeVol-=RateTable[ch->ADSRX.DecayRate+disp]; + + if(EnvelopeVol<0) EnvelopeVol=0; + if(EnvelopeVol <= ch->ADSRX.SustainLevel) + { + ch->ADSRX.State=2; + } + + ch->ADSRX.EnvelopeVol=EnvelopeVol; + ch->ADSRX.lVolume=(EnvelopeVol>>=21); + return EnvelopeVol; + } + //--------------------------------------------------// + if(ch->ADSRX.State==2) // -> sustain + { + if(ch->ADSRX.SustainIncrease) + { + disp = -0x10+32; + if(ch->ADSRX.SustainModeExp) + { + if(EnvelopeVol>=0x60000000) + disp = -0x18+32; + } + EnvelopeVol+=RateTable[ch->ADSRX.SustainRate+disp]; + + if(EnvelopeVol<0) + { + EnvelopeVol=0x7FFFFFFF; + } + } + else + { + if(ch->ADSRX.SustainModeExp) + { + disp = TableDisp[((EnvelopeVol>>28)&0x7)+8]; + } + else + { + disp=-0x0F+32; + } + EnvelopeVol-=RateTable[ch->ADSRX.SustainRate+disp]; + + if(EnvelopeVol<0) + { + EnvelopeVol=0; + } + } + ch->ADSRX.EnvelopeVol=EnvelopeVol; + ch->ADSRX.lVolume=(EnvelopeVol>>=21); + return EnvelopeVol; + } + } + return 0; +} + +#endif + +/* +James Higgs ADSR investigations: + +PSX SPU Envelope Timings +~~~~~~~~~~~~~~~~~~~~~~~~ + +First, here is an extract from doomed's SPU doc, which explains the basics +of the SPU "volume envelope": + +*** doomed doc extract start *** + +-------------------------------------------------------------------------- +Voices. +-------------------------------------------------------------------------- +The SPU has 24 hardware voices. These voices can be used to reproduce sample +data, noise or can be used as frequency modulator on the next voice. +Each voice has it's own programmable ADSR envelope filter. The main volume +can be programmed independently for left and right output. + +The ADSR envelope filter works as follows: +Ar = Attack rate, which specifies the speed at which the volume increases + from zero to it's maximum value, as soon as the note on is given. The + slope can be set to lineair or exponential. +Dr = Decay rate specifies the speed at which the volume decreases to the + sustain level. Decay is always decreasing exponentially. +Sl = Sustain level, base level from which sustain starts. +Sr = Sustain rate is the rate at which the volume of the sustained note + increases or decreases. This can be either lineair or exponential. +Rr = Release rate is the rate at which the volume of the note decreases + as soon as the note off is given. + + lvl | + ^ | /\Dr __ + Sl _| _ / _ \__--- \ + | / ---__ \ Rr + | /Ar Sr \ \ + | / \\ + |/___________________\________ + ->time + +The overal volume can also be set to sweep up or down lineairly or +exponentially from it's current value. This can be done seperately +for left and right. + +Relevant SPU registers: +------------------------------------------------------------- +$1f801xx8 Attack/Decay/Sustain level +bit |0f|0e 0d 0c 0b 0a 09 08|07 06 05 04|03 02 01 00| +desc.|Am| Ar |Dr |Sl | + +Am 0 Attack mode Linear + 1 Exponential + +Ar 0-7f attack rate +Dr 0-f decay rate +Sl 0-f sustain level +------------------------------------------------------------- +$1f801xxa Sustain rate, Release Rate. +bit |0f|0e|0d|0c 0b 0a 09 08 07 06|05|04 03 02 01 00| +desc.|Sm|Sd| 0| Sr |Rm|Rr | + +Sm 0 sustain rate mode linear + 1 exponential +Sd 0 sustain rate mode increase + 1 decrease +Sr 0-7f Sustain Rate +Rm 0 Linear decrease + 1 Exponential decrease +Rr 0-1f Release Rate + +Note: decay mode is always Expontial decrease, and thus cannot +be set. +------------------------------------------------------------- +$1f801xxc Current ADSR volume +bit |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00| +desc.|ADSRvol | + +ADSRvol Returns the current envelope volume when + read. +-- James' Note: return range: 0 -> 32767 + +*** doomed doc extract end *** + +By using a small PSX proggie to visualise the envelope as it was played, +the following results for envelope timing were obtained: + +1. Attack rate value (linear mode) + + Attack value range: 0 -> 127 + + Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | | 80 | + ----------------------------------------------------------------- + Frames | 11 | 21 | 42 | 84 | 169| 338| 676| |2890| + + Note: frames is no. of PAL frames to reach full volume (100% + amplitude) + + Hmm, noticing that the time taken to reach full volume doubles + every time we add 4 to our attack value, we know the equation is + of form: + frames = k * 2 ^ (value / 4) + + (You may ponder about envelope generator hardware at this point, + or maybe not... :) + + By substituting some stuff and running some checks, we get: + + k = 0.00257 (close enuf) + + therefore, + frames = 0.00257 * 2 ^ (value / 4) + If you just happen to be writing an emulator, then you can probably + use an equation like: + + %volume_increase_per_tick = 1 / frames + + + ------------------------------------ + Pete: + ms=((1<<(value>>2))*514)/10000 + ------------------------------------ + +2. Decay rate value (only has log mode) + + Decay value range: 0 -> 15 + + Value | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | + ------------------------------------------------ + frames | | | | | 6 | 12 | 24 | 47 | + + Note: frames here is no. of PAL frames to decay to 50% volume. + + formula: frames = k * 2 ^ (value) + + Substituting, we get: k = 0.00146 + + Further info on logarithmic nature: + frames to decay to sustain level 3 = 3 * frames to decay to + sustain level 9 + + Also no. of frames to 25% volume = roughly 1.85 * no. of frames to + 50% volume. + + Frag it - just use linear approx. + + ------------------------------------ + Pete: + ms=((1< 127 + + Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | + ------------------------------------------- + frames | 9 | 19 | 37 | 74 | 147| 293| 587| + + Here, frames = no. of PAL frames for volume amplitude to go from 100% + to 0% (or vice-versa). + + Same formula as for attack value, just a different value for k: + + k = 0.00225 + + ie: frames = 0.00225 * 2 ^ (value / 4) + + For emulation purposes: + + %volume_increase_or_decrease_per_tick = 1 / frames + + ------------------------------------ + Pete: + ms=((1<<(value>>2))*450)/10000 + ------------------------------------ + + +4. Release rate (linear mode) + + Release rate range: 0 -> 31 + + Value | 13 | 14 | 15 | 16 | 17 | + --------------------------------------------------------------- + frames | 18 | 36 | 73 | 146| 292| + + Here, frames = no. of PAL frames to decay from 100% vol to 0% vol + after "note-off" is triggered. + + Formula: frames = k * 2 ^ (value) + + And so: k = 0.00223 + + ------------------------------------ + Pete: + ms=((1< release phase + { + if(s_chan[ch].ADSR.ReleaseVal!=0) // -> release not 0: do release (if 0: stop right now) + { + if(!s_chan[ch].ADSR.ReleaseVol) // --> release just started? set up the release stuff + { + s_chan[ch].ADSR.ReleaseStartTime=s_chan[ch].ADSR.lTime; + s_chan[ch].ADSR.ReleaseVol=s_chan[ch].ADSR.lVolume; + s_chan[ch].ADSR.ReleaseTime = // --> calc how long does it take to reach the wanted sus level + (s_chan[ch].ADSR.ReleaseTime* + s_chan[ch].ADSR.ReleaseVol)/1024; + } + // -> NO release exp mode used (yet) + v=s_chan[ch].ADSR.ReleaseVol; // -> get last volume + lT=s_chan[ch].ADSR.lTime- // -> how much time is past? + s_chan[ch].ADSR.ReleaseStartTime; + l1=s_chan[ch].ADSR.ReleaseTime; + + if(lT we still have to release + { + v=v-((v*lT)/l1); // --> calc new volume + } + else // -> release is over: now really stop that sample + {v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;} + } + else // -> release IS 0: release at once + { + v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0; + } + } + else + {//--------------------------------------------------// not in release phase: + v=1024; + lT=s_chan[ch].ADSR.lTime; + l1=s_chan[ch].ADSR.AttackTime; + + if(lT0) + { + if(l3!=0) v2+=((v-v2)*lT)/l3; + else v2=v; + } + else + { + if(l3!=0) v2-=(v2*lT)/l3; + else v2=v; + } + + if(v2>v) v2=v; + if(v2<=0) {v2=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;} + + v=v2; + } + } + } + + //----------------------------------------------------// + // ok, done for this channel, so increase time + + s_chan[ch].ADSR.lTime+=1; // 1 = 1.020408f ms; + + if(v>1024) v=1024; // adjust volume + if(v<0) v=0; + s_chan[ch].ADSR.lVolume=v; // store act volume + + return v; // return the volume factor +*/ + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + + +/* +----------------------------------------------------------------------------- +Neill Corlett +Playstation SPU envelope timing notes +----------------------------------------------------------------------------- + +This is preliminary. This may be wrong. But the model described herein fits +all of my experimental data, and it's just simple enough to sound right. + +ADSR envelope level ranges from 0x00000000 to 0x7FFFFFFF internally. +The value returned by channel reg 0xC is (envelope_level>>16). + +Each sample, an increment or decrement value will be added to or +subtracted from this envelope level. + +Create the rate log table. The values double every 4 entries. + entry #0 = 4 + + 4, 5, 6, 7, + 8,10,12,14, + 16,20,24,28, ... + + entry #40 = 4096... + entry #44 = 8192... + entry #48 = 16384... + entry #52 = 32768... + entry #56 = 65536... + +increments and decrements are in terms of ratelogtable[n] +n may exceed the table bounds (plan on n being between -32 and 127). +table values are all clipped between 0x00000000 and 0x3FFFFFFF + +when you "voice on", the envelope is always fully reset. +(yes, it may click. the real thing does this too.) + +envelope level begins at zero. + +each state happens for at least 1 cycle +(transitions are not instantaneous) +this may result in some oddness: if the decay rate is uberfast, it will cut +the envelope from full down to half in one sample, potentially skipping over +the sustain level + +ATTACK +------ +- if the envelope level has overflowed past the max, clip to 0x7FFFFFFF and + proceed to DECAY. + +Linear attack mode: +- line extends upward to 0x7FFFFFFF +- increment per sample is ratelogtable[(Ar^0x7F)-0x10] + +Logarithmic attack mode: +if envelope_level < 0x60000000: + - line extends upward to 0x60000000 + - increment per sample is ratelogtable[(Ar^0x7F)-0x10] +else: + - line extends upward to 0x7FFFFFFF + - increment per sample is ratelogtable[(Ar^0x7F)-0x18] + +DECAY +----- +- if ((envelope_level>>27)&0xF) <= Sl, proceed to SUSTAIN. + Do not clip to the sustain level. +- current line ends at (envelope_level & 0x07FFFFFF) +- decrement per sample depends on (envelope_level>>28)&0x7 + 0: ratelogtable[(4*(Dr^0x1F))-0x18+0] + 1: ratelogtable[(4*(Dr^0x1F))-0x18+4] + 2: ratelogtable[(4*(Dr^0x1F))-0x18+6] + 3: ratelogtable[(4*(Dr^0x1F))-0x18+8] + 4: ratelogtable[(4*(Dr^0x1F))-0x18+9] + 5: ratelogtable[(4*(Dr^0x1F))-0x18+10] + 6: ratelogtable[(4*(Dr^0x1F))-0x18+11] + 7: ratelogtable[(4*(Dr^0x1F))-0x18+12] + (note that this is the same as the release rate formula, except that + decay rates 10-1F aren't possible... those would be slower in theory) + +SUSTAIN +------- +- no terminating condition except for voice off +- Sd=0 (increase) behavior is identical to ATTACK for both log and linear. +- Sd=1 (decrease) behavior: +Linear sustain decrease: +- line extends to 0x00000000 +- decrement per sample is ratelogtable[(Sr^0x7F)-0x0F] +Logarithmic sustain decrease: +- current line ends at (envelope_level & 0x07FFFFFF) +- decrement per sample depends on (envelope_level>>28)&0x7 + 0: ratelogtable[(Sr^0x7F)-0x1B+0] + 1: ratelogtable[(Sr^0x7F)-0x1B+4] + 2: ratelogtable[(Sr^0x7F)-0x1B+6] + 3: ratelogtable[(Sr^0x7F)-0x1B+8] + 4: ratelogtable[(Sr^0x7F)-0x1B+9] + 5: ratelogtable[(Sr^0x7F)-0x1B+10] + 6: ratelogtable[(Sr^0x7F)-0x1B+11] + 7: ratelogtable[(Sr^0x7F)-0x1B+12] + +RELEASE +------- +- if the envelope level has overflowed to negative, clip to 0 and QUIT. + +Linear release mode: +- line extends to 0x00000000 +- decrement per sample is ratelogtable[(4*(Rr^0x1F))-0x0C] + +Logarithmic release mode: +- line extends to (envelope_level & 0x0FFFFFFF) +- decrement per sample depends on (envelope_level>>28)&0x7 + 0: ratelogtable[(4*(Rr^0x1F))-0x18+0] + 1: ratelogtable[(4*(Rr^0x1F))-0x18+4] + 2: ratelogtable[(4*(Rr^0x1F))-0x18+6] + 3: ratelogtable[(4*(Rr^0x1F))-0x18+8] + 4: ratelogtable[(4*(Rr^0x1F))-0x18+9] + 5: ratelogtable[(4*(Rr^0x1F))-0x18+10] + 6: ratelogtable[(4*(Rr^0x1F))-0x18+11] + 7: ratelogtable[(4*(Rr^0x1F))-0x18+12] + +----------------------------------------------------------------------------- +*/ diff --git a/macosx/plugins/PeopsSpu109/src/adsr.h b/macosx/plugins/PeopsSpu109/src/adsr.h new file mode 100755 index 00000000..1e365c90 --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/adsr.h @@ -0,0 +1,28 @@ +/*************************************************************************** + adsr.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +INLINE void StartADSR(SPUCHAN * pChannel); +INLINE int MixADSR(SPUCHAN * pChannel); diff --git a/macosx/plugins/PeopsSpu109/src/dma.c b/macosx/plugins/PeopsSpu109/src/dma.c new file mode 100755 index 00000000..d25a4bf9 --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/dma.c @@ -0,0 +1,117 @@ +/*************************************************************************** + dma.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_DMA + +#include "externals.h" +#include "swap.h" + +//////////////////////////////////////////////////////////////////////// +// READ DMA (one value) +//////////////////////////////////////////////////////////////////////// + +unsigned short CALLBACK SPUreadDMA(void) +{ + unsigned short s; + + s=LE2HOST16(spuMem[spuAddr>>1]); + + + spuAddr+=2; + if(spuAddr>0x7ffff) spuAddr=0; + + iSpuAsyncWait=0; + + return s; +} + +//////////////////////////////////////////////////////////////////////// +// READ DMA (many values) +//////////////////////////////////////////////////////////////////////// + +void CALLBACK SPUreadDMAMem(unsigned short * pusPSXMem,int iSize) +{ + int i, mask = 0x7fffe; + + for(i=0;i>1]; // spu addr got by writeregister + //spuAddr+=2; // inc spu addr + //if(spuAddr>0x7ffff) spuAddr=0; // wrap + spuAddr = (spuAddr+2) & mask; // wrap + } + + iSpuAsyncWait=0; + +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +// to investigate: do sound data updates by writedma affect spu +// irqs? Will an irq be triggered, if new data is written to +// the memory irq address? + +//////////////////////////////////////////////////////////////////////// +// WRITE DMA (one value) +//////////////////////////////////////////////////////////////////////// + +void CALLBACK SPUwriteDMA(unsigned short val) +{ + spuMem[spuAddr>>1] = HOST2LE16(val); // spu addr got by writeregister + + spuAddr+=2; // inc spu addr + if(spuAddr>0x7ffff) spuAddr=0; // wrap + + iSpuAsyncWait=0; + +} + +//////////////////////////////////////////////////////////////////////// +// WRITE DMA (many values) +//////////////////////////////////////////////////////////////////////// + +void CALLBACK SPUwriteDMAMem(unsigned short * pusPSXMem,int iSize) +{ + int i, mask = 0x7fffe; + + for(i=0;i>1] = *pusPSXMem++; // spu addr got by writeregister + //spuAddr+=2; // inc spu addr + //if(spuAddr>0x7ffff) spuAddr=0; // wrap + spuAddr = (spuAddr+2) & mask; // wrap + } + + iSpuAsyncWait=0; + +} + +//////////////////////////////////////////////////////////////////////// + diff --git a/macosx/plugins/PeopsSpu109/src/dma.h b/macosx/plugins/PeopsSpu109/src/dma.h new file mode 100755 index 00000000..440536fe --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/dma.h @@ -0,0 +1,31 @@ +/*************************************************************************** + dma.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +unsigned short CALLBACK SPUreadDMA(void); +void CALLBACK SPUreadDMAMem(unsigned short * pusPSXMem,int iSize); +void CALLBACK SPUwriteDMA(unsigned short val); +void CALLBACK SPUwriteDMAMem(unsigned short * pusPSXMem,int iSize); diff --git a/macosx/plugins/PeopsSpu109/src/externals.h b/macosx/plugins/PeopsSpu109/src/externals.h new file mode 100755 index 00000000..1b19c774 --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/externals.h @@ -0,0 +1,344 @@ +/*************************************************************************** + externals.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/04/04 - Pete +// - increased channel struct for interpolation +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +///////////////////////////////////////////////////////// +// generic defines +///////////////////////////////////////////////////////// + +#define PSE_LT_SPU 4 +#define PSE_SPU_ERR_SUCCESS 0 +#define PSE_SPU_ERR -60 +#define PSE_SPU_ERR_NOTCONFIGURED PSE_SPU_ERR - 1 +#define PSE_SPU_ERR_INIT PSE_SPU_ERR - 2 +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +//////////////////////////////////////////////////////////////////////// +// spu defines +//////////////////////////////////////////////////////////////////////// + +// sound buffer sizes +// 400 ms complete sound buffer +#define SOUNDSIZE 70560 +// 137 ms test buffer... if less than that is buffered, a new upload will happen +#define TESTSIZE 24192 + +// num of channels +#define MAXCHAN 24 + +// ~ 1 ms of data +#define NSSIZE 45 + +/////////////////////////////////////////////////////////// +// struct defines +/////////////////////////////////////////////////////////// + +// ADSR INFOS PER CHANNEL +typedef struct +{ + int AttackModeExp; + long AttackTime; + long DecayTime; + long SustainLevel; + int SustainModeExp; + long SustainModeDec; + long SustainTime; + int ReleaseModeExp; + unsigned long ReleaseVal; + long ReleaseTime; + long ReleaseStartTime; + long ReleaseVol; + long lTime; + long lVolume; +} ADSRInfo; + +typedef struct +{ + int State; + int AttackModeExp; + int AttackRate; + int DecayRate; + int SustainLevel; + int SustainModeExp; + int SustainIncrease; + int SustainRate; + int ReleaseModeExp; + int ReleaseRate; + int EnvelopeVol; + long lVolume; + long lDummy1; + long lDummy2; +} ADSRInfoEx; + +/////////////////////////////////////////////////////////// + +// Tmp Flags + +// used for debug channel muting +#define FLAG_MUTE 1 + +// used for simple interpolation +#define FLAG_IPOL0 2 +#define FLAG_IPOL1 4 + +/////////////////////////////////////////////////////////// + +// MAIN CHANNEL STRUCT +typedef struct +{ + // no mutexes used anymore... don't need them to sync access + //HANDLE hMutex; + + int bNew; // start flag + + int iSBPos; // mixing stuff + int spos; + int sinc; + int SB[32+32]; // Pete added another 32 dwords in 1.6 ... prevents overflow issues with gaussian/cubic interpolation (thanx xodnizel!), and can be used for even better interpolations, eh? :) + int sval; + + unsigned char * pStart; // start ptr into sound mem + unsigned char * pCurr; // current pos in sound mem + unsigned char * pLoop; // loop ptr in sound mem + + int bOn; // is channel active (sample playing?) + int bStop; // is channel stopped (sample _can_ still be playing, ADSR Release phase) + int bReverb; // can we do reverb on this channel? must have ctrl register bit, to get active + int iActFreq; // current psx pitch + int iUsedFreq; // current pc pitch + int iLeftVolume; // left volume + int iLeftVolRaw; // left psx volume value + int bIgnoreLoop; // ignore loop bit, if an external loop address is used + int iMute; // mute mode + int iRightVolume; // right volume + int iRightVolRaw; // right psx volume value + int iRawPitch; // raw pitch (0...3fff) + int iIrqDone; // debug irq done flag + int s_1; // last decoding infos + int s_2; + int bRVBActive; // reverb active flag + int iRVBOffset; // reverb offset + int iRVBRepeat; // reverb repeat + int bNoise; // noise active flag + int bFMod; // freq mod (0=off, 1=sound channel, 2=freq channel) + int iRVBNum; // another reverb helper + int iOldNoise; // old noise val for this channel + ADSRInfo ADSR; // active ADSR settings + ADSRInfoEx ADSRX; // next ADSR settings (will be moved to active on sample start) + +} SPUCHAN; + +/////////////////////////////////////////////////////////// + +typedef struct +{ + int StartAddr; // reverb area start addr in samples + int CurrAddr; // reverb area curr addr in samples + + int VolLeft; + int VolRight; + int iLastRVBLeft; + int iLastRVBRight; + int iRVBLeft; + int iRVBRight; + + + int FB_SRC_A; // (offset) + int FB_SRC_B; // (offset) + int IIR_ALPHA; // (coef.) + int ACC_COEF_A; // (coef.) + int ACC_COEF_B; // (coef.) + int ACC_COEF_C; // (coef.) + int ACC_COEF_D; // (coef.) + int IIR_COEF; // (coef.) + int FB_ALPHA; // (coef.) + int FB_X; // (coef.) + int IIR_DEST_A0; // (offset) + int IIR_DEST_A1; // (offset) + int ACC_SRC_A0; // (offset) + int ACC_SRC_A1; // (offset) + int ACC_SRC_B0; // (offset) + int ACC_SRC_B1; // (offset) + int IIR_SRC_A0; // (offset) + int IIR_SRC_A1; // (offset) + int IIR_DEST_B0; // (offset) + int IIR_DEST_B1; // (offset) + int ACC_SRC_C0; // (offset) + int ACC_SRC_C1; // (offset) + int ACC_SRC_D0; // (offset) + int ACC_SRC_D1; // (offset) + int IIR_SRC_B1; // (offset) + int IIR_SRC_B0; // (offset) + int MIX_DEST_A0; // (offset) + int MIX_DEST_A1; // (offset) + int MIX_DEST_B0; // (offset) + int MIX_DEST_B1; // (offset) + int IN_COEF_L; // (coef.) + int IN_COEF_R; // (coef.) +} REVERBInfo; + +#ifdef _WINDOWS +extern HINSTANCE hInst; +#define WM_MUTE (WM_USER+543) +#endif + +/////////////////////////////////////////////////////////// +// SPU.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_SPU + +// psx buffers / addresses + +extern unsigned short regArea[]; +extern unsigned short spuMem[]; +extern unsigned char * spuMemC; +extern unsigned char * pSpuIrq; +extern unsigned char * pSpuBuffer; + +// user settings + +extern int iUseXA; +extern int iVolume; +extern int iXAPitch; +extern int iUseTimer; +extern int iSPUIRQWait; +extern int iDebugMode; +extern int iRecordMode; +extern int iUseReverb; +extern int iUseInterpolation; +extern int iDisStereo; +extern int iUseDBufIrq; + +// MISC + +extern SPUCHAN s_chan[]; +extern REVERBInfo rvb; + +extern unsigned long dwNoiseVal; +extern unsigned short spuCtrl; +extern unsigned short spuStat; +extern unsigned short spuIrq; +extern unsigned long spuAddr; +extern int bEndThread; +extern int bThreadEnded; +extern int bSpuInit; +extern unsigned long dwNewChannel; + +extern int SSumR[]; +extern int SSumL[]; +extern int iCycle; +extern short * pS; + +extern int iSpuAsyncWait; + +#ifdef _WINDOWS +extern HWND hWMain; // window handle +extern HWND hWDebug; +#endif + +extern void (CALLBACK *cddavCallback)(unsigned short,unsigned short); + +#endif + +/////////////////////////////////////////////////////////// +// CFG.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_CFG + +#ifndef _WINDOWS +extern char * pConfigFile; +#endif + +#endif + +/////////////////////////////////////////////////////////// +// DSOUND.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_DSOUND + +#ifdef _WINDOWS +extern unsigned long LastWrite; +extern unsigned long LastPlay; +#endif + +#endif + +/////////////////////////////////////////////////////////// +// RECORD.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_RECORD + +#ifdef _WINDOWS +extern int iDoRecord; +#endif + +#endif + +/////////////////////////////////////////////////////////// +// XA.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_XA + +extern xa_decode_t * xapGlobal; + +extern unsigned long * XAFeed; +extern unsigned long * XAPlay; +extern unsigned long * XAStart; +extern unsigned long * XAEnd; + +extern unsigned long XARepeat; +extern unsigned long XALastVal; + +extern int iLeftXAVol; +extern int iRightXAVol; + +#endif + +/////////////////////////////////////////////////////////// +// REVERB.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_REVERB + +extern int * sRVBPlay; +extern int * sRVBEnd; +extern int * sRVBStart; +extern int iReverbOff; +extern int iReverbRepeat; +extern int iReverbNum; + +#endif diff --git a/macosx/plugins/PeopsSpu109/src/freeze.c b/macosx/plugins/PeopsSpu109/src/freeze.c new file mode 100755 index 00000000..401d1b94 --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/freeze.c @@ -0,0 +1,234 @@ +/*************************************************************************** + freeze.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/09/18 - Pete +// - corrected LDChen ADSRX values after save state loading +// +// 2003/03/20 - Pete +// - fix to prevent the new interpolations from crashing when loading a save state +// +// 2003/01/06 - Pete +// - small changes for version 1.3 adsr save state loading +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_FREEZE + +#include "externals.h" +#include "registers.h" +#include "spu.h" +#include "regs.h" + +//////////////////////////////////////////////////////////////////////// +// freeze structs +//////////////////////////////////////////////////////////////////////// + +typedef struct +{ + char szSPUName[8]; + unsigned long ulFreezeVersion; + unsigned long ulFreezeSize; + unsigned char cSPUPort[0x200]; + unsigned char cSPURam[0x80000]; + xa_decode_t xaS; +} SPUFreeze_t; + +typedef struct +{ + unsigned short spuIrq; + unsigned long pSpuIrq; + unsigned long dummy0; + unsigned long dummy1; + unsigned long dummy2; + unsigned long dummy3; + + SPUCHAN s_chan[MAXCHAN]; + +} SPUOSSFreeze_t; + +//////////////////////////////////////////////////////////////////////// + +void LoadStateV5(SPUFreeze_t * pF); // newest version +void LoadStateUnknown(SPUFreeze_t * pF); // unknown format + +//////////////////////////////////////////////////////////////////////// +// SPUFREEZE: called by main emu on savestate load/save +//////////////////////////////////////////////////////////////////////// + +long CALLBACK SPUfreeze(unsigned long ulFreezeMode,SPUFreeze_t * pF) +{ + int i;SPUOSSFreeze_t * pFO; + + if(!pF) return 0; // first check + + if(ulFreezeMode) // info or save? + {//--------------------------------------------------// + if(ulFreezeMode==1) + memset(pF,0,sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t)); + + strcpy(pF->szSPUName,"PBOSS"); + pF->ulFreezeVersion=5; + pF->ulFreezeSize=sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t); + + if(ulFreezeMode==2) return 1; // info mode? ok, bye + // save mode: + RemoveTimer(); // stop timer + + memcpy(pF->cSPURam,spuMem,0x80000); // copy common infos + memcpy(pF->cSPUPort,regArea,0x200); + + if(xapGlobal && XAPlay!=XAFeed) // some xa + { + pF->xaS=*xapGlobal; + } + else + memset(&pF->xaS,0,sizeof(xa_decode_t)); // or clean xa + + pFO=(SPUOSSFreeze_t *)(pF+1); // store special stuff + + pFO->spuIrq=spuIrq; + if(pSpuIrq) pFO->pSpuIrq = (unsigned long)pSpuIrq-(unsigned long)spuMemC; + + for(i=0;is_chan[i],(void *)&s_chan[i],sizeof(SPUCHAN)); + if(pFO->s_chan[i].pStart) + pFO->s_chan[i].pStart-=(unsigned long)spuMemC; + if(pFO->s_chan[i].pCurr) + pFO->s_chan[i].pCurr-=(unsigned long)spuMemC; + if(pFO->s_chan[i].pLoop) + pFO->s_chan[i].pLoop-=(unsigned long)spuMemC; + } + + SetupTimer(); // sound processing on again + + return 1; + //--------------------------------------------------// + } + + if(ulFreezeMode!=0) return 0; // bad mode? bye + +#ifdef _WINDOWS + if(iDebugMode && IsWindow(hWDebug)) // clean debug mute infos + SendMessage(hWDebug,WM_MUTE,0,0); + if(IsBadReadPtr(pF,sizeof(SPUFreeze_t))) // check bad emu stuff + return 0; +#endif + + RemoveTimer(); // we stop processing while doing the save! + + memcpy(spuMem,pF->cSPURam,0x80000); // get ram + memcpy(regArea,pF->cSPUPort,0x200); + + if(pF->xaS.nsamples<=4032) // start xa again + SPUplayADPCMchannel(&pF->xaS); + + xapGlobal=0; + + if(!strcmp(pF->szSPUName,"PBOSS") && + pF->ulFreezeVersion==5) + LoadStateV5(pF); + else LoadStateUnknown(pF); + + // repair some globals + for(i=0;i<=62;i+=2) + SPUwriteRegister(H_Reverb+i,regArea[(H_Reverb+i-0xc00)>>1]); + SPUwriteRegister(H_SPUReverbAddr,regArea[(H_SPUReverbAddr-0xc00)>>1]); + SPUwriteRegister(H_SPUrvolL,regArea[(H_SPUrvolL-0xc00)>>1]); + SPUwriteRegister(H_SPUrvolR,regArea[(H_SPUrvolR-0xc00)>>1]); + + SPUwriteRegister(H_SPUctrl,(unsigned short)(regArea[(H_SPUctrl-0xc00)>>1]|0x4000)); + SPUwriteRegister(H_SPUstat,regArea[(H_SPUstat-0xc00)>>1]); + SPUwriteRegister(H_CDLeft,regArea[(H_CDLeft-0xc00)>>1]); + SPUwriteRegister(H_CDRight,regArea[(H_CDRight-0xc00)>>1]); + + // fix to prevent new interpolations from crashing + for(i=0;ispuIrq; + if(pFO->pSpuIrq) pSpuIrq = pFO->pSpuIrq+spuMemC; else pSpuIrq=0; + + for(i=0;is_chan[i],sizeof(SPUCHAN)); + + s_chan[i].pStart+=(unsigned long)spuMemC; + s_chan[i].pCurr+=(unsigned long)spuMemC; + s_chan[i].pLoop+=(unsigned long)spuMemC; + s_chan[i].iMute=0; + s_chan[i].iIrqDone=0; + } +} + +//////////////////////////////////////////////////////////////////////// + +void LoadStateUnknown(SPUFreeze_t * pF) +{ + int i; + + for(i=0;i +#include "externals.h" + +#define kMaxSoundBuffers 20 + +//static int macBufferSize = 2, macBufferCount = 36; +//static float macSoundPitch = 1.0; +static long macSoundVolume = 100; +volatile int soundBufferAt = -1, soundPlayAt = -1, soundQueued = 0; +char *soundBuffer[kMaxSoundBuffers+1], *emptyBuffer; +SndChannelPtr sndChannel; +//ExtSoundHeader sndHeader; +CmpSoundHeader sndHeader; +SndCallBackUPP callBackUPP; +static int bufferIndex; + +//////////////////////////////////////////////////////////////////////// +// small linux time helper... only used for watchdog +//////////////////////////////////////////////////////////////////////// + +unsigned long timeGetTime() +{ + struct timeval tv; + gettimeofday(&tv, 0); // well, maybe there are better ways + return tv.tv_sec * 1000 + tv.tv_usec/1000; // to do that, but at least it works +} + +pascal void MacProcessSound(SndChannelPtr chan, SndCommand *cmd) +{ + #pragma unused (chan, cmd) + + if (soundQueued <= 0) + sndHeader.samplePtr = emptyBuffer; + else + { + sndHeader.samplePtr = soundBuffer[soundPlayAt]; + soundPlayAt++; + if (soundPlayAt >= kMaxSoundBuffers/*macBufferCount*/) + soundPlayAt = 0; + soundQueued--; + } + + SndCommand buffer = { bufferCmd, 0, (long) &sndHeader }; + SndDoImmediate(sndChannel, &buffer); + + SndCommand callback = { callBackCmd, 0, 0 }; + SndDoCommand(sndChannel, &callback, true); +} + +//////////////////////////////////////////////////////////////////////// +// SETUP SOUND +//////////////////////////////////////////////////////////////////////// + +static int buffer_size; +void SetupSound(void) +{ + int count; + + callBackUPP = NewSndCallBackUPP(MacProcessSound); + + if (sndChannel) + { + SndDisposeChannel(sndChannel, true); + sndChannel = nil; + } + + buffer_size = 1; + while (buffer_size < (44100 / 60)) + buffer_size <<= 1; + + memset(&sndHeader, 0, sizeof(sndHeader)); + sndHeader.numChannels = (iDisStereo ? 1 : 2); + sndHeader.sampleRate = 44100 << 16; + sndHeader.encode = cmpSH; + sndHeader.baseFrequency = kMiddleC; + sndHeader.numFrames = buffer_size; + sndHeader.sampleSize = 16; +#ifdef __POWERPC__ + sndHeader.format = k16BitBigEndianFormat; +#else + sndHeader.format = k16BitLittleEndianFormat; +#endif + sndHeader.compressionID = fixedCompression; + + if (soundBufferAt != -1) + { + free(soundBuffer[0]); + free(emptyBuffer); + } + + soundBuffer[0] = (char *) calloc(buffer_size << 2, kMaxSoundBuffers); + for (count = 1; count <= kMaxSoundBuffers; count++) + soundBuffer[count] = soundBuffer[count-1] + (buffer_size << 2); + emptyBuffer = (char *) calloc(buffer_size << 2, 1); + + soundBufferAt = soundPlayAt = soundQueued = 0; + bufferIndex = 0; + + SndNewChannel(&sndChannel, sampledSynth, initStereo, callBackUPP); + + SndCommand sndcmd; + UInt32 volume; + + volume = (UInt32) (256.0 * (float) macSoundVolume / 100.0); + + sndcmd.cmd = volumeCmd; + sndcmd.param1 = 0; + sndcmd.param2 = (volume << 16) | volume; + SndDoCommand(sndChannel, &sndcmd, true); + + sndcmd.cmd = callBackCmd; + sndcmd.param1 = 0; + sndcmd.param2 = 0; + SndDoCommand(sndChannel, &sndcmd, true); +} + +//////////////////////////////////////////////////////////////////////// +// REMOVE SOUND +//////////////////////////////////////////////////////////////////////// + +void RemoveSound(void) +{ + DisposeSndCallBackUPP(callBackUPP); +} + +//////////////////////////////////////////////////////////////////////// +// GET BYTES BUFFERED +//////////////////////////////////////////////////////////////////////// + +unsigned long SoundGetBytesBuffered(void) +{ + int bytes; + int playAt = soundPlayAt; + + if (soundBufferAt < playAt) { + bytes = (soundBuffer[kMaxSoundBuffers]-soundBuffer[playAt])+ + (soundBuffer[soundBufferAt]-soundBuffer[0]); + } else { + bytes = soundBuffer[soundBufferAt]-soundBuffer[playAt]; + } + //printf("sb=%i\n", bytes); + +// if (bytes < SOUNDSIZE/2) +// return 0; + + return bytes; +} + +//////////////////////////////////////////////////////////////////////// +// FEED SOUND DATA +//////////////////////////////////////////////////////////////////////// + +void SoundFeedStreamData(unsigned char* pSound,long lBytes) +{ + int rem; + + if (lBytes > (buffer_size<<2)*kMaxSoundBuffers) { + printf("sound feed overflow!\n"); + return; + } + + rem = soundBuffer[kMaxSoundBuffers]-(soundBuffer[soundBufferAt]+bufferIndex); + if (lBytes > rem) { + memcpy(soundBuffer[soundBufferAt]+bufferIndex, pSound, rem); + lBytes -= rem; pSound += rem; + soundQueued += kMaxSoundBuffers-soundBufferAt; + soundBufferAt = 0; bufferIndex = 0; + } + memcpy(soundBuffer[soundBufferAt]+bufferIndex, pSound, lBytes); + soundBufferAt += (lBytes+bufferIndex)/(buffer_size<<2); + soundQueued += (lBytes+bufferIndex)/(buffer_size<<2); + bufferIndex = (lBytes+bufferIndex)%(buffer_size<<2); + + if (soundQueued >= kMaxSoundBuffers) { + printf("sound buffer overflow!\n"); + } +} + +#endif diff --git a/macosx/plugins/PeopsSpu109/src/psemu.c b/macosx/plugins/PeopsSpu109/src/psemu.c new file mode 100755 index 00000000..95836722 --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/psemu.c @@ -0,0 +1,109 @@ +/*************************************************************************** + psemu.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_PSEMU + +#include "externals.h" +#include "regs.h" +#include "dma.h" +#include "swap.h" + +//////////////////////////////////////////////////////////////////////// +// OLD, SOMEWHAT (BUT NOT MUCH) SUPPORTED PSEMUPRO FUNCS +//////////////////////////////////////////////////////////////////////// + +unsigned short CALLBACK SPUgetOne(unsigned long val) +{ + if(spuAddr!=0xffffffff) + { + return SPUreadDMA(); + } + if(val>=512*1024) val=512*1024-1; + return LE2HOST16(spuMem[val>>1]); +} + +void CALLBACK SPUputOne(unsigned long val,unsigned short data) +{ + if(spuAddr!=0xffffffff) + { + SPUwriteDMA(data); + return; + } + if(val>=512*1024) val=512*1024-1; + spuMem[val>>1] = HOST2LE16(data); +} + +void CALLBACK SPUplaySample(unsigned char ch) +{ +} + +void CALLBACK SPUsetAddr(unsigned char ch, unsigned short waddr) +{ + s_chan[ch].pStart=spuMemC+((unsigned long) waddr<<3); +} + +void CALLBACK SPUsetPitch(unsigned char ch, unsigned short pitch) +{ + SetPitch(ch,pitch); +} + +void CALLBACK SPUsetVolumeL(unsigned char ch, short vol) +{ + SetVolumeR(ch,vol); +} + +void CALLBACK SPUsetVolumeR(unsigned char ch, short vol) +{ + SetVolumeL(ch,vol); +} + +void CALLBACK SPUstartChannels1(unsigned short channels) +{ + SoundOn(0,16,channels); +} + +void CALLBACK SPUstartChannels2(unsigned short channels) +{ + SoundOn(16,24,channels); +} + +void CALLBACK SPUstopChannels1(unsigned short channels) +{ + SoundOff(0,16,channels); +} + +void CALLBACK SPUstopChannels2(unsigned short channels) +{ + SoundOff(16,24,channels); +} + +void CALLBACK SPUplaySector(unsigned long mode, unsigned char * p) +{ + if(!iUseXA) return; // no XA? bye +} + diff --git a/macosx/plugins/PeopsSpu109/src/psemuxa.h b/macosx/plugins/PeopsSpu109/src/psemuxa.h new file mode 100755 index 00000000..84c62604 --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/psemuxa.h @@ -0,0 +1,28 @@ +//============================================ +//=== Audio XA decoding +//=== Kazzuya +//============================================ + +#ifndef DECODEXA_H +#define DECODEXA_H + +typedef struct +{ + long y0, y1; +} ADPCM_Decode_t; + +typedef struct +{ + int freq; + int nbits; + int stereo; + int nsamples; + ADPCM_Decode_t left, right; + short pcm[16384]; +} xa_decode_t; + +long xa_decode_sector( xa_decode_t *xdp, + unsigned char *sectorp, + int is_first_sector ); + +#endif diff --git a/macosx/plugins/PeopsSpu109/src/registers.c b/macosx/plugins/PeopsSpu109/src/registers.c new file mode 100755 index 00000000..aa72aacb --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/registers.c @@ -0,0 +1,615 @@ +/*************************************************************************** + registers.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/09/18 - LDChen +// - pre-calculated ADSRX values +// +// 2003/02/09 - kode54 +// - removed &0x3fff from reverb volume registers, fixes a few games, +// hopefully won't be breaking anything +// +// 2003/01/19 - Pete +// - added Neill's reverb +// +// 2003/01/06 - Pete +// - added Neill's ADSR timings +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_REGISTERS + +#include "externals.h" +#include "registers.h" +#include "regs.h" +#include "swap.h" + +/* +// adsr time values (in ms) by James Higgs ... see the end of +// the adsr.c source for details + +#define ATTACK_MS 514L +#define DECAYHALF_MS 292L +#define DECAY_MS 584L +#define SUSTAIN_MS 450L +#define RELEASE_MS 446L +*/ + +// we have a timebase of 1.020408f ms, not 1 ms... so adjust adsr defines +#define ATTACK_MS 494L +#define DECAYHALF_MS 286L +#define DECAY_MS 572L +#define SUSTAIN_MS 441L +#define RELEASE_MS 437L + +//////////////////////////////////////////////////////////////////////// +// WRITE REGISTERS: called by main emu +//////////////////////////////////////////////////////////////////////// + +void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val) +{ + const unsigned long r=reg&0xfff; + + regArea[(r-0xc00)>>1] = val; + + if(r>=0x0c00 && r<0x0d80) // some channel info? + { + int ch=(r>>4)-0xc0; // calc channel + switch(r&0x0f) + { + //------------------------------------------------// r volume + case 0: + SetVolumeL((unsigned char)ch,val); + break; + //------------------------------------------------// l volume + case 2: + SetVolumeR((unsigned char)ch,val); + break; + //------------------------------------------------// pitch + case 4: + SetPitch(ch,val); + break; + //------------------------------------------------// start + case 6: + s_chan[ch].pStart=spuMemC+((unsigned long) val<<3); + break; + //------------------------------------------------// level with pre-calcs + case 8: + { + const unsigned long lval=val;unsigned long lx; + //---------------------------------------------// + s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0; + s_chan[ch].ADSRX.AttackRate = ((lval>>8) & 0x007f)^0x7f; + s_chan[ch].ADSRX.DecayRate = 4*(((lval>>4) & 0x000f)^0x1f); + s_chan[ch].ADSRX.SustainLevel = (lval & 0x000f) << 27; + //---------------------------------------------// + if(!iDebugMode) break; + //---------------------------------------------// stuff below is only for debug mode + + s_chan[ch].ADSR.AttackModeExp=(lval&0x8000)?1:0; //0x007f + + lx=(((lval>>8) & 0x007f)>>2); // attack time to run from 0 to 100% volume + lx=min(31,lx); // no overflow on shift! + if(lx) + { + lx = (1<>4) & 0x000f; // decay: + if(lx) // our const decay value is time it takes from 100% to 0% of volume + { + lx = ((1<<(lx))*DECAY_MS)/10000L; + if(!lx) lx=1; + } + s_chan[ch].ADSR.DecayTime = // so calc how long does it take to run from 100% to the wanted sus level + (lx*(1024-s_chan[ch].ADSR.SustainLevel))/1024; + } + break; + //------------------------------------------------// adsr times with pre-calcs + case 10: + { + const unsigned long lval=val;unsigned long lx; + //----------------------------------------------// + s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0; + s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1; + s_chan[ch].ADSRX.SustainRate = ((lval>>6) & 0x007f)^0x7f; + s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0; + s_chan[ch].ADSRX.ReleaseRate = 4*((lval & 0x001f)^0x1f); + //----------------------------------------------// + if(!iDebugMode) break; + //----------------------------------------------// stuff below is only for debug mode + + s_chan[ch].ADSR.SustainModeExp = (lval&0x8000)?1:0; + s_chan[ch].ADSR.ReleaseModeExp = (lval&0x0020)?1:0; + + lx=((((lval>>6) & 0x007f)>>2)); // sustain time... often very high + lx=min(31,lx); // values are used to hold the volume + if(lx) // until a sound stop occurs + { // the highest value we reach (due to + lx = (1< no multithread fuckups + s_chan[ch].pLoop=spuMemC+((unsigned long) val<<3); + s_chan[ch].bIgnoreLoop=1; + //ReleaseMutex(s_chan[ch].hMutex); // -> oki, on with the thread + break; + //------------------------------------------------// + } + + iSpuAsyncWait=0; + + return; + } + + switch(r) + { + //-------------------------------------------------// + case H_SPUaddr: + spuAddr = (unsigned long) val<<3; + break; + //-------------------------------------------------// + case H_SPUdata: + spuMem[spuAddr>>1] = HOST2LE16(val); + spuAddr+=2; + if(spuAddr>0x7ffff) spuAddr=0; + break; + //-------------------------------------------------// + case H_SPUctrl: + spuCtrl=val; + break; + //-------------------------------------------------// + case H_SPUstat: + spuStat=val & 0xf800; + break; + //-------------------------------------------------// + case H_SPUReverbAddr: + if(val==0xFFFF || val<=0x200) + {rvb.StartAddr=rvb.CurrAddr=0;} + else + { + const long iv=(unsigned long)val<<2; + if(rvb.StartAddr!=iv) + { + rvb.StartAddr=(unsigned long)val<<2; + rvb.CurrAddr=rvb.StartAddr; + } + } + break; + //-------------------------------------------------// + case H_SPUirqAddr: + spuIrq = val; + pSpuIrq=spuMemC+((unsigned long) val<<3); + break; + //-------------------------------------------------// + case H_SPUrvolL: + rvb.VolLeft=val; + break; + //-------------------------------------------------// + case H_SPUrvolR: + rvb.VolRight=val; + break; + //-------------------------------------------------// + +/* + case H_ExtLeft: + //auxprintf("EL %d\n",val); + break; + //-------------------------------------------------// + case H_ExtRight: + //auxprintf("ER %d\n",val); + break; + //-------------------------------------------------// + case H_SPUmvolL: + //auxprintf("ML %d\n",val); + break; + //-------------------------------------------------// + case H_SPUmvolR: + //auxprintf("MR %d\n",val); + break; + //-------------------------------------------------// + case H_SPUMute1: + //auxprintf("M0 %04x\n",val); + break; + //-------------------------------------------------// + case H_SPUMute2: + //auxprintf("M1 %04x\n",val); + break; +*/ + //-------------------------------------------------// + case H_SPUon1: + SoundOn(0,16,val); + break; + //-------------------------------------------------// + case H_SPUon2: + SoundOn(16,24,val); + break; + //-------------------------------------------------// + case H_SPUoff1: + SoundOff(0,16,val); + break; + //-------------------------------------------------// + case H_SPUoff2: + SoundOff(16,24,val); + break; + //-------------------------------------------------// + case H_CDLeft: + iLeftXAVol=val & 0x7fff; + if(cddavCallback) cddavCallback(0,val); + break; + case H_CDRight: + iRightXAVol=val & 0x7fff; + if(cddavCallback) cddavCallback(1,val); + break; + //-------------------------------------------------// + case H_FMod1: + FModOn(0,16,val); + break; + //-------------------------------------------------// + case H_FMod2: + FModOn(16,24,val); + break; + //-------------------------------------------------// + case H_Noise1: + NoiseOn(0,16,val); + break; + //-------------------------------------------------// + case H_Noise2: + NoiseOn(16,24,val); + break; + //-------------------------------------------------// + case H_RVBon1: + ReverbOn(0,16,val); + break; + //-------------------------------------------------// + case H_RVBon2: + ReverbOn(16,24,val); + break; + //-------------------------------------------------// + case H_Reverb+0: + + rvb.FB_SRC_A=val; + + // OK, here's the fake REVERB stuff... + // depending on effect we do more or less delay and repeats... bah + // still... better than nothing :) + + SetREVERB(val); + break; + + + case H_Reverb+2 : rvb.FB_SRC_B=(short)val; break; + case H_Reverb+4 : rvb.IIR_ALPHA=(short)val; break; + case H_Reverb+6 : rvb.ACC_COEF_A=(short)val; break; + case H_Reverb+8 : rvb.ACC_COEF_B=(short)val; break; + case H_Reverb+10 : rvb.ACC_COEF_C=(short)val; break; + case H_Reverb+12 : rvb.ACC_COEF_D=(short)val; break; + case H_Reverb+14 : rvb.IIR_COEF=(short)val; break; + case H_Reverb+16 : rvb.FB_ALPHA=(short)val; break; + case H_Reverb+18 : rvb.FB_X=(short)val; break; + case H_Reverb+20 : rvb.IIR_DEST_A0=(short)val; break; + case H_Reverb+22 : rvb.IIR_DEST_A1=(short)val; break; + case H_Reverb+24 : rvb.ACC_SRC_A0=(short)val; break; + case H_Reverb+26 : rvb.ACC_SRC_A1=(short)val; break; + case H_Reverb+28 : rvb.ACC_SRC_B0=(short)val; break; + case H_Reverb+30 : rvb.ACC_SRC_B1=(short)val; break; + case H_Reverb+32 : rvb.IIR_SRC_A0=(short)val; break; + case H_Reverb+34 : rvb.IIR_SRC_A1=(short)val; break; + case H_Reverb+36 : rvb.IIR_DEST_B0=(short)val; break; + case H_Reverb+38 : rvb.IIR_DEST_B1=(short)val; break; + case H_Reverb+40 : rvb.ACC_SRC_C0=(short)val; break; + case H_Reverb+42 : rvb.ACC_SRC_C1=(short)val; break; + case H_Reverb+44 : rvb.ACC_SRC_D0=(short)val; break; + case H_Reverb+46 : rvb.ACC_SRC_D1=(short)val; break; + case H_Reverb+48 : rvb.IIR_SRC_B1=(short)val; break; + case H_Reverb+50 : rvb.IIR_SRC_B0=(short)val; break; + case H_Reverb+52 : rvb.MIX_DEST_A0=(short)val; break; + case H_Reverb+54 : rvb.MIX_DEST_A1=(short)val; break; + case H_Reverb+56 : rvb.MIX_DEST_B0=(short)val; break; + case H_Reverb+58 : rvb.MIX_DEST_B1=(short)val; break; + case H_Reverb+60 : rvb.IN_COEF_L=(short)val; break; + case H_Reverb+62 : rvb.IN_COEF_R=(short)val; break; + } + + iSpuAsyncWait=0; + +} + +//////////////////////////////////////////////////////////////////////// +// READ REGISTER: called by main emu +//////////////////////////////////////////////////////////////////////// + +unsigned short CALLBACK SPUreadRegister(unsigned long reg) +{ + const unsigned long r=reg&0xfff; + + iSpuAsyncWait=0; + + if(r>=0x0c00 && r<0x0d80) + { + switch(r&0x0f) + { + case 12: // get adsr vol + { + const int ch=(r>>4)-0xc0; + + if(s_chan[ch].bNew) return 1; // we are started, but not processed? return 1 + if(s_chan[ch].ADSRX.lVolume && // same here... we haven't decoded one sample yet, so no envelope yet. return 1 as well + !s_chan[ch].ADSRX.EnvelopeVol) + return 1; + return (unsigned short)(s_chan[ch].ADSRX.EnvelopeVol>>16); + } + + case 14: // get loop address + { + const int ch=(r>>4)-0xc0; + if(s_chan[ch].pLoop==NULL) return 0; + return (unsigned short)((s_chan[ch].pLoop-spuMemC)>>3); + } + } + } + + switch(r) + { + case H_SPUctrl: + return spuCtrl; + + case H_SPUstat: + return spuStat; + + case H_SPUaddr: + return (unsigned short)(spuAddr>>3); + + case H_SPUdata: + { + unsigned short s=LE2HOST16(spuMem[spuAddr>>1]); + spuAddr+=2; + if(spuAddr>0x7ffff) spuAddr=0; + return s; + } + + case H_SPUirqAddr: + return spuIrq; + + //case H_SPUIsOn1: + // return IsSoundOn(0,16); + + //case H_SPUIsOn2: + // return IsSoundOn(16,24); + + } + + return regArea[(r-0xc00)>>1]; +} + +//////////////////////////////////////////////////////////////////////// +// SOUND ON register write +//////////////////////////////////////////////////////////////////////// + +void SoundOn(int start,int end,unsigned short val) // SOUND ON PSX COMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if((val&1) && s_chan[ch].pStart) // mmm... start has to be set before key on !?! + { + s_chan[ch].bIgnoreLoop=0; + s_chan[ch].bNew=1; + dwNewChannel|=(1<>=1) // loop channels + { + if(val&1) // && s_chan[i].bOn) mmm... + { + s_chan[ch].bStop=1; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// FMOD register write +//////////////////////////////////////////////////////////////////////// + +void FModOn(int start,int end,unsigned short val) // FMOD ON PSX COMMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if(val&1) // -> fmod on/off + { + if(ch>0) + { + s_chan[ch].bFMod=1; // --> sound channel + s_chan[ch-1].bFMod=2; // --> freq channel + } + } + else + { + s_chan[ch].bFMod=0; // --> turn off fmod + } + } +} + +//////////////////////////////////////////////////////////////////////// +// NOISE register write +//////////////////////////////////////////////////////////////////////// + +void NoiseOn(int start,int end,unsigned short val) // NOISE ON PSX COMMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if(val&1) // -> noise on/off + { + s_chan[ch].bNoise=1; + } + else + { + s_chan[ch].bNoise=0; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// LEFT VOLUME register write +//////////////////////////////////////////////////////////////////////// + +// please note: sweep and phase invert are wrong... but I've never seen +// them used + +void SetVolumeL(unsigned char ch,short vol) // LEFT VOLUME +{ + s_chan[ch].iLeftVolRaw=vol; + + if(vol&0x8000) // sweep? + { + short sInc=1; // -> sweep up? + if(vol&0x2000) sInc=-1; // -> or down? + if(vol&0x1000) vol^=0xffff; // -> mmm... phase inverted? have to investigate this + vol=((vol&0x7f)+1)/2; // -> sweep: 0..127 -> 0..64 + vol+=vol/(2*sInc); // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half! + vol*=128; + } + else // no sweep: + { + if(vol&0x4000) // -> mmm... phase inverted? have to investigate this + //vol^=0xffff; + vol=0x3fff-(vol&0x3fff); + } + + vol&=0x3fff; + s_chan[ch].iLeftVolume=vol; // store volume +} + +//////////////////////////////////////////////////////////////////////// +// RIGHT VOLUME register write +//////////////////////////////////////////////////////////////////////// + +void SetVolumeR(unsigned char ch,short vol) // RIGHT VOLUME +{ + s_chan[ch].iRightVolRaw=vol; + + if(vol&0x8000) // comments... see above :) + { + short sInc=1; + if(vol&0x2000) sInc=-1; + if(vol&0x1000) vol^=0xffff; + vol=((vol&0x7f)+1)/2; + vol+=vol/(2*sInc); + vol*=128; + } + else + { + if(vol&0x4000) //vol=vol^=0xffff; + vol=0x3fff-(vol&0x3fff); + } + + vol&=0x3fff; + + s_chan[ch].iRightVolume=vol; +} + +//////////////////////////////////////////////////////////////////////// +// PITCH register write +//////////////////////////////////////////////////////////////////////// + +void SetPitch(int ch,unsigned short val) // SET PITCH +{ + int NP; + if(val>0x3fff) NP=0x3fff; // get pitch val + else NP=val; + + s_chan[ch].iRawPitch=NP; + + NP=(44100L*NP)/4096L; // calc frequency + if(NP<1) NP=1; // some security + s_chan[ch].iActFreq=NP; // store frequency +} + +//////////////////////////////////////////////////////////////////////// +// REVERB register write +//////////////////////////////////////////////////////////////////////// + +void ReverbOn(int start,int end,unsigned short val) // REVERB ON PSX COMMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if(val&1) // -> reverb on/off + { + s_chan[ch].bReverb=1; + } + else + { + s_chan[ch].bReverb=0; + } + } +} diff --git a/macosx/plugins/PeopsSpu109/src/registers.h b/macosx/plugins/PeopsSpu109/src/registers.h new file mode 100755 index 00000000..dc453cfa --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/registers.h @@ -0,0 +1,153 @@ +/*************************************************************************** + registers.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#define H_SPUReverbAddr 0x0da2 +#define H_SPUirqAddr 0x0da4 +#define H_SPUaddr 0x0da6 +#define H_SPUdata 0x0da8 +#define H_SPUctrl 0x0daa +#define H_SPUstat 0x0dae +#define H_SPUmvolL 0x0d80 +#define H_SPUmvolR 0x0d82 +#define H_SPUrvolL 0x0d84 +#define H_SPUrvolR 0x0d86 +#define H_SPUon1 0x0d88 +#define H_SPUon2 0x0d8a +#define H_SPUoff1 0x0d8c +#define H_SPUoff2 0x0d8e +#define H_FMod1 0x0d90 +#define H_FMod2 0x0d92 +#define H_Noise1 0x0d94 +#define H_Noise2 0x0d96 +#define H_RVBon1 0x0d98 +#define H_RVBon2 0x0d9a +#define H_SPUMute1 0x0d9c +#define H_SPUMute2 0x0d9e +#define H_CDLeft 0x0db0 +#define H_CDRight 0x0db2 +#define H_ExtLeft 0x0db4 +#define H_ExtRight 0x0db6 +#define H_Reverb 0x0dc0 +#define H_SPUPitch0 0x0c04 +#define H_SPUPitch1 0x0c14 +#define H_SPUPitch2 0x0c24 +#define H_SPUPitch3 0x0c34 +#define H_SPUPitch4 0x0c44 +#define H_SPUPitch5 0x0c54 +#define H_SPUPitch6 0x0c64 +#define H_SPUPitch7 0x0c74 +#define H_SPUPitch8 0x0c84 +#define H_SPUPitch9 0x0c94 +#define H_SPUPitch10 0x0ca4 +#define H_SPUPitch11 0x0cb4 +#define H_SPUPitch12 0x0cc4 +#define H_SPUPitch13 0x0cd4 +#define H_SPUPitch14 0x0ce4 +#define H_SPUPitch15 0x0cf4 +#define H_SPUPitch16 0x0d04 +#define H_SPUPitch17 0x0d14 +#define H_SPUPitch18 0x0d24 +#define H_SPUPitch19 0x0d34 +#define H_SPUPitch20 0x0d44 +#define H_SPUPitch21 0x0d54 +#define H_SPUPitch22 0x0d64 +#define H_SPUPitch23 0x0d74 + +#define H_SPUStartAdr0 0x0c06 +#define H_SPUStartAdr1 0x0c16 +#define H_SPUStartAdr2 0x0c26 +#define H_SPUStartAdr3 0x0c36 +#define H_SPUStartAdr4 0x0c46 +#define H_SPUStartAdr5 0x0c56 +#define H_SPUStartAdr6 0x0c66 +#define H_SPUStartAdr7 0x0c76 +#define H_SPUStartAdr8 0x0c86 +#define H_SPUStartAdr9 0x0c96 +#define H_SPUStartAdr10 0x0ca6 +#define H_SPUStartAdr11 0x0cb6 +#define H_SPUStartAdr12 0x0cc6 +#define H_SPUStartAdr13 0x0cd6 +#define H_SPUStartAdr14 0x0ce6 +#define H_SPUStartAdr15 0x0cf6 +#define H_SPUStartAdr16 0x0d06 +#define H_SPUStartAdr17 0x0d16 +#define H_SPUStartAdr18 0x0d26 +#define H_SPUStartAdr19 0x0d36 +#define H_SPUStartAdr20 0x0d46 +#define H_SPUStartAdr21 0x0d56 +#define H_SPUStartAdr22 0x0d66 +#define H_SPUStartAdr23 0x0d76 + +#define H_SPULoopAdr0 0x0c0e +#define H_SPULoopAdr1 0x0c1e +#define H_SPULoopAdr2 0x0c2e +#define H_SPULoopAdr3 0x0c3e +#define H_SPULoopAdr4 0x0c4e +#define H_SPULoopAdr5 0x0c5e +#define H_SPULoopAdr6 0x0c6e +#define H_SPULoopAdr7 0x0c7e +#define H_SPULoopAdr8 0x0c8e +#define H_SPULoopAdr9 0x0c9e +#define H_SPULoopAdr10 0x0cae +#define H_SPULoopAdr11 0x0cbe +#define H_SPULoopAdr12 0x0cce +#define H_SPULoopAdr13 0x0cde +#define H_SPULoopAdr14 0x0cee +#define H_SPULoopAdr15 0x0cfe +#define H_SPULoopAdr16 0x0d0e +#define H_SPULoopAdr17 0x0d1e +#define H_SPULoopAdr18 0x0d2e +#define H_SPULoopAdr19 0x0d3e +#define H_SPULoopAdr20 0x0d4e +#define H_SPULoopAdr21 0x0d5e +#define H_SPULoopAdr22 0x0d6e +#define H_SPULoopAdr23 0x0d7e + +#define H_SPU_ADSRLevel0 0x0c08 +#define H_SPU_ADSRLevel1 0x0c18 +#define H_SPU_ADSRLevel2 0x0c28 +#define H_SPU_ADSRLevel3 0x0c38 +#define H_SPU_ADSRLevel4 0x0c48 +#define H_SPU_ADSRLevel5 0x0c58 +#define H_SPU_ADSRLevel6 0x0c68 +#define H_SPU_ADSRLevel7 0x0c78 +#define H_SPU_ADSRLevel8 0x0c88 +#define H_SPU_ADSRLevel9 0x0c98 +#define H_SPU_ADSRLevel10 0x0ca8 +#define H_SPU_ADSRLevel11 0x0cb8 +#define H_SPU_ADSRLevel12 0x0cc8 +#define H_SPU_ADSRLevel13 0x0cd8 +#define H_SPU_ADSRLevel14 0x0ce8 +#define H_SPU_ADSRLevel15 0x0cf8 +#define H_SPU_ADSRLevel16 0x0d08 +#define H_SPU_ADSRLevel17 0x0d18 +#define H_SPU_ADSRLevel18 0x0d28 +#define H_SPU_ADSRLevel19 0x0d38 +#define H_SPU_ADSRLevel20 0x0d48 +#define H_SPU_ADSRLevel21 0x0d58 +#define H_SPU_ADSRLevel22 0x0d68 +#define H_SPU_ADSRLevel23 0x0d78 + diff --git a/macosx/plugins/PeopsSpu109/src/regs.h b/macosx/plugins/PeopsSpu109/src/regs.h new file mode 100755 index 00000000..ad928553 --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/regs.h @@ -0,0 +1,36 @@ +/*************************************************************************** + regs.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +void SoundOn(int start,int end,unsigned short val); +void SoundOff(int start,int end,unsigned short val); +void FModOn(int start,int end,unsigned short val); +void NoiseOn(int start,int end,unsigned short val); +void SetVolumeL(unsigned char ch,short vol); +void SetVolumeR(unsigned char ch,short vol); +void SetPitch(int ch,unsigned short val); +void ReverbOn(int start,int end,unsigned short val); +void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val); \ No newline at end of file diff --git a/macosx/plugins/PeopsSpu109/src/resource.h b/macosx/plugins/PeopsSpu109/src/resource.h new file mode 100755 index 00000000..8a3a8a03 --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/resource.h @@ -0,0 +1,148 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by spuPeopsSound.rc +// +#define IDC_SETS1 3 +#define IDC_SETS2 4 +#define IDOK2 5 +#define IDD_DIALOG1 130 +#define IDD_ABOUT 130 +#define IDD_CFGDLG 131 +#define IDD_DEBUG 135 +#define IDB_BITMAP1 136 +#define IDB_BITMAP2 137 +#define IDB_BITMAP3 138 +#define IDB_BITMAP4 139 +#define IDB_BITMAP5 140 +#define IDD_RECORD 141 +#define IDC_XAVOLUME 1004 +#define IDC_ENABXA 1005 +#define IDC_XAPITCH 1006 +#define IDC_XABLOCK 1007 +#define IDC_USETIMER 1007 +#define IDC_CMIXRATE 1008 +#define IDC_USEIRQ 1008 +#define IDC_USEREVERB 1008 +#define IDC_CMODE 1009 +#define IDC_VOLUME 1009 +#define IDC_CFILTER 1010 +#define IDC_IRQWAIT 1010 +#define IDC_CQUALITY 1011 +#define IDC_DEBUGMODE 1011 +#define IDC_CDSOUND 1012 +#define IDC_INTERPOL 1012 +#define IDC_PLAYALWAYS 1013 +#define IDC_RECORDMODE 1013 +#define IDC_IGNOREPITCH 1014 +#define IDC_DISSTEREO 1014 +#define IDC_AMPLIF 1015 +#define IDC_IRQDECODE 1015 +#define IDC_VENVELOPE 1016 +#define IDC_VOL1 1016 +#define IDC_REVERB 1017 +#define IDC_VOL2 1017 +#define IDC_VOL3 1018 +#define IDC_VOL4 1019 +#define IDC_SAREA 1022 +#define IDC_ADSR 1023 +#define IDC_MUTE1 1047 +#define IDC_MUTE2 1048 +#define IDC_MUTE3 1049 +#define IDC_MUTE4 1050 +#define IDC_MUTE5 1051 +#define IDC_MUTE6 1052 +#define IDC_MUTE7 1053 +#define IDC_MUTE8 1054 +#define IDC_MUTE9 1055 +#define IDC_MUTE10 1056 +#define IDC_MUTE11 1057 +#define IDC_MUTE12 1058 +#define IDC_MUTE13 1059 +#define IDC_MUTE14 1060 +#define IDC_MUTE15 1061 +#define IDC_MUTE16 1062 +#define IDC_MUTE17 1063 +#define IDC_MUTE18 1064 +#define IDC_MUTE19 1065 +#define IDC_MUTE20 1066 +#define IDC_MUTE21 1067 +#define IDC_MUTE22 1068 +#define IDC_MUTE23 1069 +#define IDC_MUTE24 1070 +#define IDC_CHAN1 1071 +#define IDC_CHAN2 1072 +#define IDC_CHAN3 1073 +#define IDC_CHAN4 1074 +#define IDC_CHAN5 1075 +#define IDC_CHAN6 1076 +#define IDC_CHAN7 1077 +#define IDC_CHAN8 1078 +#define IDC_CHAN9 1079 +#define IDC_CHAN10 1080 +#define IDC_CHAN11 1081 +#define IDC_CHAN12 1082 +#define IDC_CHAN13 1083 +#define IDC_CHAN14 1084 +#define IDC_CHAN15 1085 +#define IDC_CHAN16 1086 +#define IDC_CHAN17 1087 +#define IDC_CHAN18 1088 +#define IDC_CHAN19 1089 +#define IDC_CHAN20 1090 +#define IDC_CHAN21 1091 +#define IDC_CHAN22 1092 +#define IDC_CHAN23 1093 +#define IDC_CHAN24 1094 +#define IDC_SADSR1 1096 +#define IDC_SADSR2 1097 +#define IDC_SADSR3 1098 +#define IDC_SADSR4 1099 +#define IDC_SADSR5 1100 +#define IDC_SADSR6 1101 +#define IDC_CHANNUM 1102 +#define IDC_MUTEOFF 1103 +#define IDC_MUTEON 1104 +#define IDC_SADSR7 1105 +#define IDC_CI1 1106 +#define IDC_CI2 1107 +#define IDC_CI3 1108 +#define IDC_CI4 1109 +#define IDC_CI5 1110 +#define IDC_CI6 1111 +#define IDC_CI7 1112 +#define IDC_CI8 1113 +#define IDC_CI9 1114 +#define IDC_CI10 1115 +#define IDC_CI11 1116 +#define IDC_CI12 1117 +#define IDC_CI13 1118 +#define IDC_CI14 1119 +#define IDC_CI15 1120 +#define IDC_CI16 1121 +#define IDC_STA1 1122 +#define IDC_SADSR8 1123 +#define IDC_STA2 1124 +#define IDC_STA3 1125 +#define IDC_STA4 1126 +#define IDC_XA1 1127 +#define IDC_XA2 1128 +#define IDC_XA3 1129 +#define IDC_XA4 1130 +#define IDC_CI17 1131 +#define IDC_CI18 1132 +#define IDC_XA 1133 +#define IDC_WAVFILE 1134 +#define IDC_XA5 1135 +#define IDC_RECORD 1135 +#define IDC_XA6 1136 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 144 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1136 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/macosx/plugins/PeopsSpu109/src/reverb.c b/macosx/plugins/PeopsSpu109/src/reverb.c new file mode 100755 index 00000000..3a38afef --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/reverb.c @@ -0,0 +1,480 @@ +/*************************************************************************** + reverb.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/01/19 - Pete +// - added Neill's reverb (see at the end of file) +// +// 2002/12/26 - Pete +// - adjusted reverb handling +// +// 2002/08/14 - Pete +// - added extra reverb +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_REVERB + +// will be included from spu.c +#ifdef _IN_SPU + +//////////////////////////////////////////////////////////////////////// +// globals +//////////////////////////////////////////////////////////////////////// + +// REVERB info and timing vars... + +int * sRVBPlay = 0; +int * sRVBEnd = 0; +int * sRVBStart = 0; +int iReverbOff = -1; // some delay factor for reverb +int iReverbRepeat = 0; +int iReverbNum = 1; + +//////////////////////////////////////////////////////////////////////// +// SET REVERB +//////////////////////////////////////////////////////////////////////// + +void SetREVERB(unsigned short val) +{ + switch(val) + { + case 0x0000: iReverbOff=-1; break; // off + case 0x007D: iReverbOff=32; iReverbNum=2; iReverbRepeat=128; break; // ok room + + case 0x0033: iReverbOff=32; iReverbNum=2; iReverbRepeat=64; break; // studio small + case 0x00B1: iReverbOff=48; iReverbNum=2; iReverbRepeat=96; break; // ok studio medium + case 0x00E3: iReverbOff=64; iReverbNum=2; iReverbRepeat=128; break; // ok studio large ok + + case 0x01A5: iReverbOff=128; iReverbNum=4; iReverbRepeat=32; break; // ok hall + case 0x033D: iReverbOff=256; iReverbNum=4; iReverbRepeat=64; break; // space echo + case 0x0001: iReverbOff=184; iReverbNum=3; iReverbRepeat=128; break; // echo/delay + case 0x0017: iReverbOff=128; iReverbNum=2; iReverbRepeat=128; break; // half echo + default: iReverbOff=32; iReverbNum=1; iReverbRepeat=0; break; + } +} + +//////////////////////////////////////////////////////////////////////// +// START REVERB +//////////////////////////////////////////////////////////////////////// + +INLINE void StartREVERB(SPUCHAN * pChannel) +{ + if(pChannel->bReverb && (spuCtrl&0x80)) // reverb possible? + { + if(iUseReverb==2) pChannel->bRVBActive=1; + else + if(iUseReverb==1 && iReverbOff>0) // -> fake reverb used? + { + pChannel->bRVBActive=1; // -> activate it + pChannel->iRVBOffset=iReverbOff*45; + pChannel->iRVBRepeat=iReverbRepeat*45; + pChannel->iRVBNum =iReverbNum; + } + } + else pChannel->bRVBActive=0; // else -> no reverb +} + +//////////////////////////////////////////////////////////////////////// +// HELPER FOR NEILL'S REVERB: re-inits our reverb mixing buf +//////////////////////////////////////////////////////////////////////// + +INLINE void InitREVERB(void) +{ + if(iUseReverb==2) + {memset(sRVBStart,0,NSSIZE*2*4);} +} + +//////////////////////////////////////////////////////////////////////// +// STORE REVERB +//////////////////////////////////////////////////////////////////////// + +INLINE void StoreREVERB(SPUCHAN * pChannel,int ns) +{ + if(iUseReverb==0) return; + else + if(iUseReverb==2) // -------------------------------- // Neil's reverb + { + const int iRxl=(pChannel->sval*pChannel->iLeftVolume)>>14; + const int iRxr=(pChannel->sval*pChannel->iRightVolume)>>14; + + ns<<=1; + + *(sRVBStart+ns) +=iRxl; // -> we mix all active reverb channels into an extra buffer + *(sRVBStart+ns+1)+=iRxr; + } + else // --------------------------------------------- // Pete's easy fake reverb + { + int * pN;int iRn,iRr=0; + + // we use the half channel volume (/0x8000) for the first reverb effects, quarter for next and so on + + int iRxl=(pChannel->sval*pChannel->iLeftVolume)>>15; + int iRxr=(pChannel->sval*pChannel->iRightVolume)>>15; + + for(iRn=1;iRn<=pChannel->iRVBNum;iRn++,iRr+=pChannel->iRVBRepeat,iRxl>>=1,iRxr>>=1) + { + pN=sRVBPlay+((pChannel->iRVBOffset+iRr+ns)<<1); + if(pN>=sRVBEnd) pN=sRVBStart+(pN-sRVBEnd); + + (*pN)+=iRxl; + pN++; + (*pN)+=iRxr; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int g_buffer(int iOff) // get_buffer content helper: takes care about wraps +{ + short * p=(short *)spuMem; + iOff=(iOff*4)+rvb.CurrAddr; + while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000); + while(iOff0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000); + while(iOff32767L) iVal=32767L; + *(p+iOff)=HOST2LE16((short)iVal); +} + +//////////////////////////////////////////////////////////////////////// + +INLINE void s_buffer1(int iOff,int iVal) // set_buffer (+1 sample) content helper: takes care about wraps and clipping +{ + short * p=(short *)spuMem; + iOff=(iOff*4)+rvb.CurrAddr+1; + while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000); + while(iOff32767L) iVal=32767L; + *(p+iOff)=HOST2LE16((short)iVal); +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int MixREVERBLeft(int ns) +{ + if(iUseReverb==0) return 0; + else + if(iUseReverb==2) + { + static int iCnt=0; // this func will be called with 44.1 khz + + if(!rvb.StartAddr) // reverb is off + { + rvb.iLastRVBLeft=rvb.iLastRVBRight=rvb.iRVBLeft=rvb.iRVBRight=0; + return 0; + } + + iCnt++; + + if(iCnt&1) // we work on every second left value: downsample to 22 khz + { + if(spuCtrl&0x80) // -> reverb on? oki + { + int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1; + + const int INPUT_SAMPLE_L=*(sRVBStart+(ns<<1)); + const int INPUT_SAMPLE_R=*(sRVBStart+(ns<<1)+1); + + const int IIR_INPUT_A0 = (g_buffer(rvb.IIR_SRC_A0) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb.IN_COEF_L)/32768L; + const int IIR_INPUT_A1 = (g_buffer(rvb.IIR_SRC_A1) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb.IN_COEF_R)/32768L; + const int IIR_INPUT_B0 = (g_buffer(rvb.IIR_SRC_B0) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb.IN_COEF_L)/32768L; + const int IIR_INPUT_B1 = (g_buffer(rvb.IIR_SRC_B1) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb.IN_COEF_R)/32768L; + + const int IIR_A0 = (IIR_INPUT_A0 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_A0) * (32768L - rvb.IIR_ALPHA))/32768L; + const int IIR_A1 = (IIR_INPUT_A1 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_A1) * (32768L - rvb.IIR_ALPHA))/32768L; + const int IIR_B0 = (IIR_INPUT_B0 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_B0) * (32768L - rvb.IIR_ALPHA))/32768L; + const int IIR_B1 = (IIR_INPUT_B1 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_B1) * (32768L - rvb.IIR_ALPHA))/32768L; + + s_buffer1(rvb.IIR_DEST_A0, IIR_A0); + s_buffer1(rvb.IIR_DEST_A1, IIR_A1); + s_buffer1(rvb.IIR_DEST_B0, IIR_B0); + s_buffer1(rvb.IIR_DEST_B1, IIR_B1); + + ACC0 = (g_buffer(rvb.ACC_SRC_A0) * rvb.ACC_COEF_A)/32768L + + (g_buffer(rvb.ACC_SRC_B0) * rvb.ACC_COEF_B)/32768L + + (g_buffer(rvb.ACC_SRC_C0) * rvb.ACC_COEF_C)/32768L + + (g_buffer(rvb.ACC_SRC_D0) * rvb.ACC_COEF_D)/32768L; + ACC1 = (g_buffer(rvb.ACC_SRC_A1) * rvb.ACC_COEF_A)/32768L + + (g_buffer(rvb.ACC_SRC_B1) * rvb.ACC_COEF_B)/32768L + + (g_buffer(rvb.ACC_SRC_C1) * rvb.ACC_COEF_C)/32768L + + (g_buffer(rvb.ACC_SRC_D1) * rvb.ACC_COEF_D)/32768L; + + FB_A0 = g_buffer(rvb.MIX_DEST_A0 - rvb.FB_SRC_A); + FB_A1 = g_buffer(rvb.MIX_DEST_A1 - rvb.FB_SRC_A); + FB_B0 = g_buffer(rvb.MIX_DEST_B0 - rvb.FB_SRC_B); + FB_B1 = g_buffer(rvb.MIX_DEST_B1 - rvb.FB_SRC_B); + + s_buffer(rvb.MIX_DEST_A0, ACC0 - (FB_A0 * rvb.FB_ALPHA)/32768L); + s_buffer(rvb.MIX_DEST_A1, ACC1 - (FB_A1 * rvb.FB_ALPHA)/32768L); + + s_buffer(rvb.MIX_DEST_B0, (rvb.FB_ALPHA * ACC0)/32768L - (FB_A0 * (int)(rvb.FB_ALPHA^0xFFFF8000))/32768L - (FB_B0 * rvb.FB_X)/32768L); + s_buffer(rvb.MIX_DEST_B1, (rvb.FB_ALPHA * ACC1)/32768L - (FB_A1 * (int)(rvb.FB_ALPHA^0xFFFF8000))/32768L - (FB_B1 * rvb.FB_X)/32768L); + + rvb.iLastRVBLeft = rvb.iRVBLeft; + rvb.iLastRVBRight = rvb.iRVBRight; + + rvb.iRVBLeft = (g_buffer(rvb.MIX_DEST_A0)+g_buffer(rvb.MIX_DEST_B0))/3; + rvb.iRVBRight = (g_buffer(rvb.MIX_DEST_A1)+g_buffer(rvb.MIX_DEST_B1))/3; + + rvb.iRVBLeft = (rvb.iRVBLeft * rvb.VolLeft) / 0x4000; + rvb.iRVBRight = (rvb.iRVBRight * rvb.VolRight) / 0x4000; + + rvb.CurrAddr++; + if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr; + + return rvb.iLastRVBLeft+(rvb.iRVBLeft-rvb.iLastRVBLeft)/2; + } + else // -> reverb off + { + rvb.iLastRVBLeft=rvb.iLastRVBRight=rvb.iRVBLeft=rvb.iRVBRight=0; + } + + rvb.CurrAddr++; + if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr; + } + + return rvb.iLastRVBLeft; + } + else // easy fake reverb: + { + const int iRV=*sRVBPlay; // -> simply take the reverb mix buf value + *sRVBPlay++=0; // -> init it after + if(sRVBPlay>=sRVBEnd) sRVBPlay=sRVBStart; // -> and take care about wrap arounds + return iRV; // -> return reverb mix buf val + } +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int MixREVERBRight(void) +{ + if(iUseReverb==0) return 0; + else + if(iUseReverb==2) // Neill's reverb: + { + int i=rvb.iLastRVBRight+(rvb.iRVBRight-rvb.iLastRVBRight)/2; + rvb.iLastRVBRight=rvb.iRVBRight; + return i; // -> just return the last right reverb val (little bit scaled by the previous right val) + } + else // easy fake reverb: + { + const int iRV=*sRVBPlay; // -> simply take the reverb mix buf value + *sRVBPlay++=0; // -> init it after + if(sRVBPlay>=sRVBEnd) sRVBPlay=sRVBStart; // -> and take care about wrap arounds + return iRV; // -> return reverb mix buf val + } +} + +//////////////////////////////////////////////////////////////////////// + +#endif + +/* +----------------------------------------------------------------------------- +PSX reverb hardware notes +by Neill Corlett +----------------------------------------------------------------------------- + +Yadda yadda disclaimer yadda probably not perfect yadda well it's okay anyway +yadda yadda. + +----------------------------------------------------------------------------- + +Basics +------ + +- The reverb buffer is 22khz 16-bit mono PCM. +- It starts at the reverb address given by 1DA2, extends to + the end of sound RAM, and wraps back to the 1DA2 address. + +Setting the address at 1DA2 resets the current reverb work address. + +This work address ALWAYS increments every 1/22050 sec., regardless of +whether reverb is enabled (bit 7 of 1DAA set). + +And the contents of the reverb buffer ALWAYS play, scaled by the +"reverberation depth left/right" volumes (1D84/1D86). +(which, by the way, appear to be scaled so 3FFF=approx. 1.0, 4000=-1.0) + +----------------------------------------------------------------------------- + +Register names +-------------- + +These are probably not their real names. +These are probably not even correct names. +We will use them anyway, because we can. + +1DC0: FB_SRC_A (offset) +1DC2: FB_SRC_B (offset) +1DC4: IIR_ALPHA (coef.) +1DC6: ACC_COEF_A (coef.) +1DC8: ACC_COEF_B (coef.) +1DCA: ACC_COEF_C (coef.) +1DCC: ACC_COEF_D (coef.) +1DCE: IIR_COEF (coef.) +1DD0: FB_ALPHA (coef.) +1DD2: FB_X (coef.) +1DD4: IIR_DEST_A0 (offset) +1DD6: IIR_DEST_A1 (offset) +1DD8: ACC_SRC_A0 (offset) +1DDA: ACC_SRC_A1 (offset) +1DDC: ACC_SRC_B0 (offset) +1DDE: ACC_SRC_B1 (offset) +1DE0: IIR_SRC_A0 (offset) +1DE2: IIR_SRC_A1 (offset) +1DE4: IIR_DEST_B0 (offset) +1DE6: IIR_DEST_B1 (offset) +1DE8: ACC_SRC_C0 (offset) +1DEA: ACC_SRC_C1 (offset) +1DEC: ACC_SRC_D0 (offset) +1DEE: ACC_SRC_D1 (offset) +1DF0: IIR_SRC_B1 (offset) +1DF2: IIR_SRC_B0 (offset) +1DF4: MIX_DEST_A0 (offset) +1DF6: MIX_DEST_A1 (offset) +1DF8: MIX_DEST_B0 (offset) +1DFA: MIX_DEST_B1 (offset) +1DFC: IN_COEF_L (coef.) +1DFE: IN_COEF_R (coef.) + +The coefficients are signed fractional values. +-32768 would be -1.0 + 32768 would be 1.0 (if it were possible... the highest is of course 32767) + +The offsets are (byte/8) offsets into the reverb buffer. +i.e. you multiply them by 8, you get byte offsets. +You can also think of them as (samples/4) offsets. +They appear to be signed. They can be negative. +None of the documented presets make them negative, though. + +Yes, 1DF0 and 1DF2 appear to be backwards. Not a typo. + +----------------------------------------------------------------------------- + +What it does +------------ + +We take all reverb sources: +- regular channels that have the reverb bit on +- cd and external sources, if their reverb bits are on +and mix them into one stereo 44100hz signal. + +Lowpass/downsample that to 22050hz. The PSX uses a proper bandlimiting +algorithm here, but I haven't figured out the hysterically exact specifics. +I use an 8-tap filter with these coefficients, which are nice but probably +not the real ones: + +0.037828187894 +0.157538631280 +0.321159685278 +0.449322115345 +0.449322115345 +0.321159685278 +0.157538631280 +0.037828187894 + +So we have two input samples (INPUT_SAMPLE_L, INPUT_SAMPLE_R) every 22050hz. + +* IN MY EMULATION, I divide these by 2 to make it clip less. + (and of course the L/R output coefficients are adjusted to compensate) + The real thing appears to not do this. + +At every 22050hz tick: +- If the reverb bit is enabled (bit 7 of 1DAA), execute the reverb + steady-state algorithm described below +- AFTERWARDS, retrieve the "wet out" L and R samples from the reverb buffer + (This part may not be exactly right and I guessed at the coefs. TODO: check later.) + L is: 0.333 * (buffer[MIX_DEST_A0] + buffer[MIX_DEST_B0]) + R is: 0.333 * (buffer[MIX_DEST_A1] + buffer[MIX_DEST_B1]) +- Advance the current buffer position by 1 sample + +The wet out L and R are then upsampled to 44100hz and played at the +"reverberation depth left/right" (1D84/1D86) volume, independent of the main +volume. + +----------------------------------------------------------------------------- + +Reverb steady-state +------------------- + +The reverb steady-state algorithm is fairly clever, and of course by +"clever" I mean "batshit insane". + +buffer[x] is relative to the current buffer position, not the beginning of +the buffer. Note that all buffer offsets must wrap around so they're +contained within the reverb work area. + +Clipping is performed at the end... maybe also sooner, but definitely at +the end. + +IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L; +IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R; +IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L; +IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R; + +IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA); +IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA); +IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA); +IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA); + +buffer[IIR_DEST_A0 + 1sample] = IIR_A0; +buffer[IIR_DEST_A1 + 1sample] = IIR_A1; +buffer[IIR_DEST_B0 + 1sample] = IIR_B0; +buffer[IIR_DEST_B1 + 1sample] = IIR_B1; + +ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A + + buffer[ACC_SRC_B0] * ACC_COEF_B + + buffer[ACC_SRC_C0] * ACC_COEF_C + + buffer[ACC_SRC_D0] * ACC_COEF_D; +ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A + + buffer[ACC_SRC_B1] * ACC_COEF_B + + buffer[ACC_SRC_C1] * ACC_COEF_C + + buffer[ACC_SRC_D1] * ACC_COEF_D; + +FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A]; +FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A]; +FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B]; +FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B]; + +buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA; +buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA; +buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X; +buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X; + +----------------------------------------------------------------------------- +*/ + diff --git a/macosx/plugins/PeopsSpu109/src/reverb.h b/macosx/plugins/PeopsSpu109/src/reverb.h new file mode 100755 index 00000000..275e561d --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/reverb.h @@ -0,0 +1,30 @@ +/*************************************************************************** + reverb.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +void SetREVERB(unsigned short val); +INLINE void StartREVERB(SPUCHAN * pChannel); +INLINE void StoreREVERB(SPUCHAN * pChannel,int ns); \ No newline at end of file diff --git a/macosx/plugins/PeopsSpu109/src/spu.c b/macosx/plugins/PeopsSpu109/src/spu.c new file mode 100755 index 00000000..4010cb47 --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/spu.c @@ -0,0 +1,1359 @@ +/*************************************************************************** + spu.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/09/19 - Pete +// - added option: IRQ handling in the decoded sound buffer areas (Crash Team Racing) +// +// 2004/09/18 - Pete +// - changed global channel var handling to local pointers (hopefully it will help LDChen's port) +// +// 2004/04/22 - Pete +// - finally fixed frequency modulation and made some cleanups +// +// 2003/04/07 - Eric +// - adjusted cubic interpolation algorithm +// +// 2003/03/16 - Eric +// - added cubic interpolation +// +// 2003/03/01 - linuzappz +// - libraryName changes using ALSA +// +// 2003/02/28 - Pete +// - added option for type of interpolation +// - adjusted spu irqs again (Thousant Arms, Valkyrie Profile) +// - added MONO support for MSWindows DirectSound +// +// 2003/02/20 - kode54 +// - amended interpolation code, goto GOON could skip initialization of gpos and cause segfault +// +// 2003/02/19 - kode54 +// - moved SPU IRQ handler and changed sample flag processing +// +// 2003/02/18 - kode54 +// - moved ADSR calculation outside of the sample decode loop, somehow I doubt that +// ADSR timing is relative to the frequency at which a sample is played... I guess +// this remains to be seen, and I don't know whether ADSR is applied to noise channels... +// +// 2003/02/09 - kode54 +// - one-shot samples now process the end block before stopping +// - in light of removing fmod hack, now processing ADSR on frequency channel as well +// +// 2003/02/08 - kode54 +// - replaced easy interpolation with gaussian +// - removed fmod averaging hack +// - changed .sinc to be updated from .iRawPitch, no idea why it wasn't done this way already (<- Pete: because I sometimes fail to see the obvious, haharhar :) +// +// 2003/02/08 - linuzappz +// - small bugfix for one usleep that was 1 instead of 1000 +// - added iDisStereo for no stereo (Linux) +// +// 2003/01/22 - Pete +// - added easy interpolation & small noise adjustments +// +// 2003/01/19 - Pete +// - added Neill's reverb +// +// 2003/01/12 - Pete +// - added recording window handlers +// +// 2003/01/06 - Pete +// - added Neill's ADSR timings +// +// 2002/12/28 - Pete +// - adjusted spu irq handling, fmod handling and loop handling +// +// 2002/08/14 - Pete +// - added extra reverb +// +// 2002/06/08 - linuzappz +// - SPUupdate changed for SPUasync +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_SPU + +#include "externals.h" +#include "regs.h" +#include "resource.h" +#include "swap.h" + +//////////////////////////////////////////////////////////////////////// +// spu version infos/name +//////////////////////////////////////////////////////////////////////// + +const unsigned char version = 1; +const unsigned char revision = 1; +const unsigned char build = 9; +#ifdef _WINDOWS +static char * libraryName = "P.E.Op.S. DSound Audio Driver"; +#else +#ifndef USEALSA +static char * libraryName = "P.E.Op.S. OSS Audio Driver"; +#else +static char * libraryName = "P.E.Op.S. ALSA Audio Driver"; +#endif +#endif +static char * libraryInfo = "P.E.Op.S. OSS Driver V1.9\nCoded by Pete Bernert and the P.E.Op.S. team\n"; + +//////////////////////////////////////////////////////////////////////// +// globals +//////////////////////////////////////////////////////////////////////// + +// psx buffer / addresses + +unsigned short regArea[10000]; +unsigned short spuMem[256*1024]; +unsigned char * spuMemC; +unsigned char * pSpuIrq=0; +unsigned char * pSpuBuffer; +unsigned char * pMixIrq=0; + + +// user settings + +int iUseXA=1; +int iVolume=3; +int iXAPitch=1; +int iUseTimer=2; +int iSPUIRQWait=1; +int iDebugMode=0; +int iRecordMode=0; +int iUseReverb=2; +int iUseInterpolation=2; +int iDisStereo=0; +int iUseDBufIrq=0; + +// MAIN infos struct for each channel + +SPUCHAN s_chan[MAXCHAN+1]; // channel + 1 infos (1 is security for fmod handling) +REVERBInfo rvb; + +unsigned long dwNoiseVal=1; // global noise generator + +unsigned short spuCtrl=0; // some vars to store psx reg infos +unsigned short spuStat=0; +unsigned short spuIrq=0; +unsigned long spuAddr=0xffffffff; // address into spu mem +int bEndThread=0; // thread handlers +int bThreadEnded=0; +int bSpuInit=0; +int bSPUIsOpen=0; + +#ifdef _WINDOWS +HWND hWMain=0; // window handle +HWND hWDebug=0; +HWND hWRecord=0; +static HANDLE hMainThread; +#else +// 2003/06/07 - Pete +#ifndef NOTHREADLIB +static pthread_t thread = -1; // thread id (linux) +#endif +#endif + +unsigned long dwNewChannel=0; // flags for faster testing, if new channel starts + +void (CALLBACK *irqCallback)(void)=0; // func of main emu, called on spu irq +void (CALLBACK *cddavCallback)(unsigned short,unsigned short)=0; +void (CALLBACK *irqQSound)(unsigned char *,long *,long)=0; + +// certain globals (were local before, but with the new timeproc I need em global) + +const int f[5][2] = { { 0, 0 }, + { 60, 0 }, + { 115, -52 }, + { 98, -55 }, + { 122, -60 } }; +int SSumR[NSSIZE]; +int SSumL[NSSIZE]; +int iFMod[NSSIZE]; +int iCycle=0; +short * pS; + +static int lastch=-1; // last channel processed on spu irq in timer mode +static int lastns=0; // last ns pos +static int iSecureStart=0; // secure start counter + +//////////////////////////////////////////////////////////////////////// +// CODE AREA +//////////////////////////////////////////////////////////////////////// + +// dirty inline func includes + +#include "reverb.c" +#include "adsr.c" + +//////////////////////////////////////////////////////////////////////// +// helpers for simple interpolation + +// +// easy interpolation on upsampling, no special filter, just "Pete's common sense" tm +// +// instead of having n equal sample values in a row like: +// ____ +// |____ +// +// we compare the current delta change with the next delta change. +// +// if curr_delta is positive, +// +// - and next delta is smaller (or changing direction): +// \. +// -__ +// +// - and next delta significant (at least twice) bigger: +// --_ +// \. +// +// - and next delta is nearly same: +// \. +// \. +// +// +// if curr_delta is negative, +// +// - and next delta is smaller (or changing direction): +// _-- +// / +// +// - and next delta significant (at least twice) bigger: +// / +// __- +// +// - and next delta is nearly same: +// / +// / +// + + +INLINE void InterpolateUp(SPUCHAN * pChannel) +{ + if(pChannel->SB[32]==1) // flag == 1? calc step and set flag... and don't change the value in this pass + { + const int id1=pChannel->SB[30]-pChannel->SB[29]; // curr delta to next val + const int id2=pChannel->SB[31]-pChannel->SB[30]; // and next delta to next-next val :) + + pChannel->SB[32]=0; + + if(id1>0) // curr delta positive + { + if(id2SB[28]=id1;pChannel->SB[32]=2;} + else + if(id2<(id1<<1)) + pChannel->SB[28]=(id1*pChannel->sinc)/0x10000L; + else + pChannel->SB[28]=(id1*pChannel->sinc)/0x20000L; + } + else // curr delta negative + { + if(id2>id1) + {pChannel->SB[28]=id1;pChannel->SB[32]=2;} + else + if(id2>(id1<<1)) + pChannel->SB[28]=(id1*pChannel->sinc)/0x10000L; + else + pChannel->SB[28]=(id1*pChannel->sinc)/0x20000L; + } + } + else + if(pChannel->SB[32]==2) // flag 1: calc step and set flag... and don't change the value in this pass + { + pChannel->SB[32]=0; + + pChannel->SB[28]=(pChannel->SB[28]*pChannel->sinc)/0x20000L; + if(pChannel->sinc<=0x8000) + pChannel->SB[29]=pChannel->SB[30]-(pChannel->SB[28]*((0x10000/pChannel->sinc)-1)); + else pChannel->SB[29]+=pChannel->SB[28]; + } + else // no flags? add bigger val (if possible), calc smaller step, set flag1 + pChannel->SB[29]+=pChannel->SB[28]; +} + +// +// even easier interpolation on downsampling, also no special filter, again just "Pete's common sense" tm +// + +INLINE void InterpolateDown(SPUCHAN * pChannel) +{ + if(pChannel->sinc>=0x20000L) // we would skip at least one val? + { + pChannel->SB[29]+=(pChannel->SB[30]-pChannel->SB[29])/2; // add easy weight + if(pChannel->sinc>=0x30000L) // we would skip even more vals? + pChannel->SB[29]+=(pChannel->SB[31]-pChannel->SB[30])/2; // add additional next weight + } +} + +//////////////////////////////////////////////////////////////////////// +// helpers for gauss interpolation + +#define gval0 (((short*)(&pChannel->SB[29]))[gpos]) +#define gval(x) (((short*)(&pChannel->SB[29]))[(gpos+x)&3]) + +#include "gauss_i.h" + +//////////////////////////////////////////////////////////////////////// + +#include "xa.c" + +//////////////////////////////////////////////////////////////////////// +// START SOUND... called by main thread to setup a new sound on a channel +//////////////////////////////////////////////////////////////////////// + +INLINE void StartSound(SPUCHAN * pChannel) +{ + StartADSR(pChannel); + StartREVERB(pChannel); + + pChannel->pCurr=pChannel->pStart; // set sample start + + pChannel->s_1=0; // init mixing vars + pChannel->s_2=0; + pChannel->iSBPos=28; + + pChannel->bNew=0; // init channel flags + pChannel->bStop=0; + pChannel->bOn=1; + + pChannel->SB[29]=0; // init our interpolation helpers + pChannel->SB[30]=0; + + if(iUseInterpolation>=2) // gauss interpolation? + {pChannel->spos=0x30000L;pChannel->SB[28]=0;} // -> start with more decoding + else {pChannel->spos=0x10000L;pChannel->SB[31]=0;} // -> no/simple interpolation starts with one 44100 decoding +} + +//////////////////////////////////////////////////////////////////////// +// ALL KIND OF HELPERS +//////////////////////////////////////////////////////////////////////// + +INLINE void VoiceChangeFrequency(SPUCHAN * pChannel) +{ + pChannel->iUsedFreq=pChannel->iActFreq; // -> take it and calc steps + pChannel->sinc=pChannel->iRawPitch<<4; + if(!pChannel->sinc) pChannel->sinc=1; + if(iUseInterpolation==1) pChannel->SB[32]=1; // -> freq change in simle imterpolation mode: set flag +} + +//////////////////////////////////////////////////////////////////////// + +INLINE void FModChangeFrequency(SPUCHAN * pChannel,int ns) +{ + int NP=pChannel->iRawPitch; + + NP=((32768L+iFMod[ns])*NP)/32768L; + + if(NP>0x3fff) NP=0x3fff; + if(NP<0x1) NP=0x1; + + NP=(44100L*NP)/(4096L); // calc frequency + + pChannel->iActFreq=NP; + pChannel->iUsedFreq=NP; + pChannel->sinc=(((NP/10)<<16)/4410); + if(!pChannel->sinc) pChannel->sinc=1; + if(iUseInterpolation==1) pChannel->SB[32]=1; // freq change in simple interpolation mode + + iFMod[ns]=0; +} + +//////////////////////////////////////////////////////////////////////// + +// noise handler... just produces some noise data +// surely wrong... and no noise frequency (spuCtrl&0x3f00) will be used... +// and sometimes the noise will be used as fmod modulation... pfff + +INLINE int iGetNoiseVal(SPUCHAN * pChannel) +{ + int fa; + + if((dwNoiseVal<<=1)&0x80000000L) + { + dwNoiseVal^=0x0040001L; + fa=((dwNoiseVal>>2)&0x7fff); + fa=-fa; + } + else fa=(dwNoiseVal>>2)&0x7fff; + + // mmm... depending on the noise freq we allow bigger/smaller changes to the previous val + fa=pChannel->iOldNoise+((fa-pChannel->iOldNoise)/((0x001f-((spuCtrl&0x3f00)>>9))+1)); + if(fa>32767L) fa=32767L; + if(fa<-32767L) fa=-32767L; + pChannel->iOldNoise=fa; + + if(iUseInterpolation<2) // no gauss/cubic interpolation? + pChannel->SB[29] = fa; // -> store noise val in "current sample" slot + return fa; +} + +//////////////////////////////////////////////////////////////////////// + +INLINE void StoreInterpolationVal(SPUCHAN * pChannel,int fa) +{ + if(pChannel->bFMod==2) // fmod freq channel + pChannel->SB[29]=fa; + else + { + if((spuCtrl&0x4000)==0) fa=0; // muted? + else // else adjust + { + if(fa>32767L) fa=32767L; + if(fa<-32767L) fa=-32767L; + } + + if(iUseInterpolation>=2) // gauss/cubic interpolation + { + int gpos = pChannel->SB[28]; + gval0 = fa; + gpos = (gpos+1) & 3; + pChannel->SB[28] = gpos; + } + else + if(iUseInterpolation==1) // simple interpolation + { + pChannel->SB[28] = 0; + pChannel->SB[29] = pChannel->SB[30]; // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour' + pChannel->SB[30] = pChannel->SB[31]; + pChannel->SB[31] = fa; + pChannel->SB[32] = 1; // -> flag: calc new interolation + } + else pChannel->SB[29]=fa; // no interpolation + } +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int iGetInterpolationVal(SPUCHAN * pChannel) +{ + int fa; + + if(pChannel->bFMod==2) return pChannel->SB[29]; + + switch(iUseInterpolation) + { + //--------------------------------------------------// + case 3: // cubic interpolation + { + long xd;int gpos; + xd = ((pChannel->spos) >> 1)+1; + gpos = pChannel->SB[28]; + + fa = gval(3) - 3*gval(2) + 3*gval(1) - gval0; + fa *= (xd - (2<<15)) / 6; + fa >>= 15; + fa += gval(2) - gval(1) - gval(1) + gval0; + fa *= (xd - (1<<15)) >> 1; + fa >>= 15; + fa += gval(1) - gval0; + fa *= xd; + fa >>= 15; + fa = fa + gval0; + + } break; + //--------------------------------------------------// + case 2: // gauss interpolation + { + int vl, vr;int gpos; + vl = (pChannel->spos >> 6) & ~3; + gpos = pChannel->SB[28]; + vr=(gauss[vl]*gval0)&~2047; + vr+=(gauss[vl+1]*gval(1))&~2047; + vr+=(gauss[vl+2]*gval(2))&~2047; + vr+=(gauss[vl+3]*gval(3))&~2047; + fa = vr>>11; + } break; + //--------------------------------------------------// + case 1: // simple interpolation + { + if(pChannel->sinc<0x10000L) // -> upsampling? + InterpolateUp(pChannel); // --> interpolate up + else InterpolateDown(pChannel); // --> else down + fa=pChannel->SB[29]; + } break; + //--------------------------------------------------// + default: // no interpolation + { + fa=pChannel->SB[29]; + } break; + //--------------------------------------------------// + } + + return fa; +} + +//////////////////////////////////////////////////////////////////////// +// MAIN SPU FUNCTION +// here is the main job handler... thread, timer or direct func call +// basically the whole sound processing is done in this fat func! +//////////////////////////////////////////////////////////////////////// + +// 5 ms waiting phase, if buffer is full and no new sound has to get started +// .. can be made smaller (smallest val: 1 ms), but bigger waits give +// better performance + +#define PAUSE_W 5 +#define PAUSE_L 5000 + +//////////////////////////////////////////////////////////////////////// + +int iSpuAsyncWait=0; + +#ifdef _WINDOWS +static VOID CALLBACK MAINProc(UINT nTimerId,UINT msg,DWORD dwUser,DWORD dwParam1, DWORD dwParam2) +#else +static void *MAINThread(void *arg) +#endif +{ + int s_1,s_2,fa,ns; +#ifndef _MACOSX + int voldiv=iVolume; +#else + const int voldiv=1; +#endif + unsigned char * start;unsigned int nSample; + int ch,predict_nr,shift_factor,flags,d,s; + int bIRQReturn=0;SPUCHAN * pChannel; + + + while(!bEndThread) // until we are shutting down + { + //--------------------------------------------------// + // ok, at the beginning we are looking if there is + // enuff free place in the dsound/oss buffer to + // fill in new data, or if there is a new channel to start. + // if not, we wait (thread) or return (timer/spuasync) + // until enuff free place is available/a new channel gets + // started + + if(dwNewChannel) // new channel should start immedately? + { // (at least one bit 0 ... MAXCHANNEL is set?) + iSecureStart++; // -> set iSecure + if(iSecureStart>5) iSecureStart=0; // (if it is set 5 times - that means on 5 tries a new samples has been started - in a row, we will reset it, to give the sound update a chance) + } + else iSecureStart=0; // 0: no new channel should start + + while(!iSecureStart && !bEndThread && // no new start? no thread end? + (SoundGetBytesBuffered()>TESTSIZE)) // and still enuff data in sound buffer? + { + iSecureStart=0; // reset secure + +#ifdef _WINDOWS + if(iUseTimer) // no-thread mode? + { + if(iUseTimer==1) // -> ok, timer mode 1: setup a oneshot timer of x ms to wait + timeSetEvent(PAUSE_W,1,MAINProc,0,TIME_ONESHOT); + return; // -> and done this time (timer mode 1 or 2) + } + // win thread mode: + Sleep(PAUSE_W); // sleep for x ms (win) +#else + if(iUseTimer) return 0; // linux no-thread mode? bye + usleep(PAUSE_L); // else sleep for x ms (linux) +#endif + + if(dwNewChannel) iSecureStart=1; // if a new channel kicks in (or, of course, sound buffer runs low), we will leave the loop + } + + //--------------------------------------------------// continue from irq handling in timer mode? + + if(lastch>=0) // will be -1 if no continue is pending + { + ch=lastch; ns=lastns; lastch=-1; // -> setup all kind of vars to continue + pChannel=&s_chan[ch]; + goto GOON; // -> directly jump to the continue point + } + + //--------------------------------------------------// + //- main channel loop -// + //--------------------------------------------------// + { + pChannel=s_chan; + for(ch=0;chbNew) + { + StartSound(pChannel); // start new sound + dwNewChannel&=~(1<bOn) continue; // channel not playing? next + + if(pChannel->iActFreq!=pChannel->iUsedFreq) // new psx frequency? + VoiceChangeFrequency(pChannel); + + ns=0; + while(nsbFMod==1 && iFMod[ns]) // fmod freq channel + FModChangeFrequency(pChannel,ns); + + while(pChannel->spos>=0x10000L) + { + if(pChannel->iSBPos==28) // 28 reached? + { + start=pChannel->pCurr; // set up the current pos + + if (start == (unsigned char*)-1) // special "stop" sign + { + pChannel->bOn=0; // -> turn everything off + pChannel->ADSRX.lVolume=0; + pChannel->ADSRX.EnvelopeVol=0; + goto ENDX; // -> and done for this channel + } + + pChannel->iSBPos=0; + + //////////////////////////////////////////// spu irq handler here? mmm... do it later + + s_1=pChannel->s_1; + s_2=pChannel->s_2; + + predict_nr=(int)*start;start++; + shift_factor=predict_nr&0xf; + predict_nr >>= 4; + flags=(int)*start;start++; + + // -------------------------------------- // + + for (nSample=0;nSample<28;start++) + { + d=(int)*start; + s=((d&0xf)<<12); + if(s&0x8000) s|=0xffff0000; + + fa=(s >> shift_factor); + fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2=s_1;s_1=fa; + s=((d & 0xf0) << 8); + + pChannel->SB[nSample++]=fa; + + if(s&0x8000) s|=0xffff0000; + fa=(s>>shift_factor); + fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2=s_1;s_1=fa; + + pChannel->SB[nSample++]=fa; + } + + //////////////////////////////////////////// irq check + + if(irqCallback && (spuCtrl&0x40)) // some callback and irq active? + { + if((pSpuIrq > start-16 && // irq address reached? + pSpuIrq <= start) || + ((flags&1) && // special: irq on looping addr, when stop/loop flag is set + (pSpuIrq > pChannel->pLoop-16 && + pSpuIrq <= pChannel->pLoop))) + { + pChannel->iIrqDone=1; // -> debug flag + irqCallback(); // -> call main emu + + if(iSPUIRQWait) // -> option: wait after irq for main emu + { + iSpuAsyncWait=1; + bIRQReturn=1; + } + } + } + + //////////////////////////////////////////// flag handler + + if((flags&4) && (!pChannel->bIgnoreLoop)) + pChannel->pLoop=start-16; // loop adress + + if(flags&1) // 1: stop/loop + { + // We play this block out first... + //if(!(flags&2)) // 1+2: do loop... otherwise: stop + if(flags!=3 || pChannel->pLoop==NULL) // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example) + { // and checking if pLoop is set avoids crashes, yeah + start = (unsigned char*)-1; + } + else + { + start = pChannel->pLoop; + } + } + + pChannel->pCurr=start; // store values for next cycle + pChannel->s_1=s_1; + pChannel->s_2=s_2; + + //////////////////////////////////////////// + + if(bIRQReturn) // special return for "spu irq - wait for cpu action" + { + bIRQReturn=0; + if(iUseTimer!=2) + { + DWORD dwWatchTime=timeGetTime()+2500; + + while(iSpuAsyncWait && !bEndThread && + timeGetTime()SB[pChannel->iSBPos++]; // get sample data + + StoreInterpolationVal(pChannel,fa); // store val for later interpolation + + pChannel->spos -= 0x10000L; + } + + //////////////////////////////////////////////// + + if(pChannel->bNoise) + fa=iGetNoiseVal(pChannel); // get noise val + else fa=iGetInterpolationVal(pChannel); // get sample val + + pChannel->sval=(MixADSR(pChannel)*fa)/1024; // mix adsr + + if(pChannel->bFMod==2) // fmod freq channel + iFMod[ns]=pChannel->sval; // -> store 1T sample data, use that to do fmod on next channel + else // no fmod freq channel + { + ////////////////////////////////////////////// + // ok, left/right sound volume (psx volume goes from 0 ... 0x3fff) + + if(pChannel->iMute) + pChannel->sval=0; // debug mute + else + { + SSumL[ns]+=(pChannel->sval*pChannel->iLeftVolume)/0x4000L; + SSumR[ns]+=(pChannel->sval*pChannel->iRightVolume)/0x4000L; + } + + ////////////////////////////////////////////// + // now let us store sound data for reverb + + if(pChannel->bRVBActive) StoreREVERB(pChannel,ns); + } + + //////////////////////////////////////////////// + // ok, go on until 1 ms data of this channel is collected + + ns++; + pChannel->spos += pChannel->sinc; + + } +ENDX: ; + } + } + + //---------------------------------------------------// + //- here we have another 1 ms of sound data + //---------------------------------------------------// + // mix XA infos (if any) + + if(XAPlay!=XAFeed || XARepeat) MixXA(); + + /////////////////////////////////////////////////////// + // mix all channels (including reverb) into one buffer + + if(iDisStereo) // no stereo? + { + int dl,dr; + for(ns=0;ns32767) dl=32767; + + SSumR[ns]+=MixREVERBRight(); + + dr=SSumR[ns]/voldiv;SSumR[ns]=0; + if(dr<-32767) dr=-32767;if(dr>32767) dr=32767; + *pS++=(dl+dr)/2; + } + } + else // stereo: + for(ns=0;ns32767) d=32767; + *pS++=d; + + SSumR[ns]+=MixREVERBRight(); + + d=SSumR[ns]/voldiv;SSumR[ns]=0; + if(d<-32767) d=-32767;if(d>32767) d=32767; + *pS++=d; + } + + ////////////////////////////////////////////////////// + // special irq handling in the decode buffers (0x0000-0x1000) + // we know: + // the decode buffers are located in spu memory in the following way: + // 0x0000-0x03ff CD audio left + // 0x0400-0x07ff CD audio right + // 0x0800-0x0bff Voice 1 + // 0x0c00-0x0fff Voice 3 + // and decoded data is 16 bit for one sample + // we assume: + // even if voices 1/3 are off or no cd audio is playing, the internal + // play positions will move on and wrap after 0x400 bytes. + // Therefore: we just need a pointer from spumem+0 to spumem+3ff, and + // increase this pointer on each sample by 2 bytes. If this pointer + // (or 0x400 offsets of this pointer) hits the spuirq address, we generate + // an IRQ. Only problem: the "wait for cpu" option is kinda hard to do here + // in some of Peops timer modes. So: we ignore this option here (for now). + // Also note: we abuse the channel 0-3 irq debug display for those irqs + // (since that's the easiest way to display such irqs in debug mode :)) + + if(pMixIrq && irqCallback) // pMixIRQ will only be set, if the config option is active + { + for(ns=0;ns=pMixIrq+(ch*0x400) && pSpuIrqspuMemC+0x3ff) pMixIrq=spuMemC; + } + } + + InitREVERB(); + + ////////////////////////////////////////////////////// + // feed the sound + // wanna have around 1/60 sec (16.666 ms) updates + + if(iCycle++>16) + { + //- zn qsound mixer callback ----------------------// + + if(irqQSound) + { + long * pl=(long *)XAPlay; + short * ps=(short *)pSpuBuffer; + int g,iBytes=((unsigned char *)pS)-((unsigned char *)pSpuBuffer); + iBytes/=2; + for(g=0;g no init, no call + +#ifdef _WINDOWS + MAINProc(0,0,0,0,0); // -> experimental win mode... not really tested... don't like the drawbacks +#else + MAINThread(0); // -> linux high-compat mode +#endif + } +} + +//////////////////////////////////////////////////////////////////////// +// SPU UPDATE... new epsxe func +// 1 time every 32 hsync lines +// (312/32)x50 in pal +// (262/32)x60 in ntsc +//////////////////////////////////////////////////////////////////////// + +#ifndef _WINDOWS + +// since epsxe 1.5.2 (linux) uses SPUupdate, not SPUasync, I will +// leave that func in the linux port, until epsxe linux is using +// the async function as well + +void CALLBACK SPUupdate(void) +{ + SPUasync(0); +} + +#endif + +//////////////////////////////////////////////////////////////////////// +// XA AUDIO +//////////////////////////////////////////////////////////////////////// + +void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap) +{ + if(!iUseXA) return; // no XA? bye + if(!xap) return; + if(!xap->freq) return; // no xa freq ? bye + + FeedXA(xap); // call main XA feeder +} + +//////////////////////////////////////////////////////////////////////// +// INIT/EXIT STUFF +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// SPUINIT: this func will be called first by the main emu +//////////////////////////////////////////////////////////////////////// + +long CALLBACK SPUinit(void) +{ + spuMemC=(unsigned char *)spuMem; // just small setup + memset((void *)s_chan,0,MAXCHAN*sizeof(SPUCHAN)); + memset((void *)&rvb,0,sizeof(REVERBInfo)); + InitADSR(); + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// SETUPTIMER: init of certain buffers and threads/timers +//////////////////////////////////////////////////////////////////////// + +void SetupTimer(void) +{ + memset(SSumR,0,NSSIZE*sizeof(int)); // init some mixing buffers + memset(SSumL,0,NSSIZE*sizeof(int)); + memset(iFMod,0,NSSIZE*sizeof(int)); + + pS=(short *)pSpuBuffer; // setup soundbuffer pointer + + bEndThread=0; // init thread vars + bThreadEnded=0; + bSpuInit=1; // flag: we are inited + +#ifdef _WINDOWS + + if(iUseTimer==1) // windows: use timer + { + timeBeginPeriod(1); + timeSetEvent(1,1,MAINProc,0,TIME_ONESHOT); + } + else + if(iUseTimer==0) // windows: use thread + { + //_beginthread(MAINThread,0,NULL); + DWORD dw; + hMainThread=CreateThread(NULL,0,MAINThreadEx,0,0,&dw); + SetThreadPriority(hMainThread, + //THREAD_PRIORITY_TIME_CRITICAL); + THREAD_PRIORITY_HIGHEST); + } + +#else + +#ifndef NOTHREADLIB + if(!iUseTimer) // linux: use thread + { + pthread_create(&thread, NULL, MAINThread, NULL); + } +#endif + +#endif +} + +//////////////////////////////////////////////////////////////////////// +// REMOVETIMER: kill threads/timers +//////////////////////////////////////////////////////////////////////// + +void RemoveTimer(void) +{ + bEndThread=1; // raise flag to end thread + +#ifdef _WINDOWS + + if(iUseTimer!=2) // windows thread? + { + while(!bThreadEnded) {Sleep(5L);} // -> wait till thread has ended + Sleep(5L); + } + if(iUseTimer==1) timeEndPeriod(1); // windows timer? stop it + +#else + +#ifndef NOTHREADLIB + if(!iUseTimer) // linux tread? + { + int i=0; + while(!bThreadEnded && i<2000) {usleep(1000L);i++;} // -> wait until thread has ended + if(thread!=-1) {pthread_cancel(thread);thread=-1;} // -> cancel thread anyway + } +#endif + +#endif + + bThreadEnded=0; // no more spu is running + bSpuInit=0; +} + +//////////////////////////////////////////////////////////////////////// +// SETUPSTREAMS: init most of the spu buffers +//////////////////////////////////////////////////////////////////////// + +void SetupStreams(void) +{ + int i; + + pSpuBuffer=(unsigned char *)malloc(32768); // alloc mixing buffer + + if(iUseReverb==1) i=88200*2; + else i=NSSIZE*2; + + sRVBStart = (int *)malloc(i*4); // alloc reverb buffer + memset(sRVBStart,0,i*4); + sRVBEnd = sRVBStart + i; + sRVBPlay = sRVBStart; + + XAStart = // alloc xa buffer + (unsigned long *)malloc(44100*4); + XAPlay = XAStart; + XAFeed = XAStart; + XAEnd = XAStart + 44100; + + for(i=0;i init sustain + s_chan[i].iMute=0; + s_chan[i].iIrqDone=0; + s_chan[i].pLoop=spuMemC; + s_chan[i].pStart=spuMemC; + s_chan[i].pCurr=spuMemC; + } + + if(iUseDBufIrq) pMixIrq=spuMemC; // enable decoded buffer irqs by setting the address +} + +//////////////////////////////////////////////////////////////////////// +// REMOVESTREAMS: free most buffer +//////////////////////////////////////////////////////////////////////// + +void RemoveStreams(void) +{ + free(pSpuBuffer); // free mixing buffer + pSpuBuffer=NULL; + free(sRVBStart); // free reverb buffer + sRVBStart=0; + free(XAStart); // free XA buffer + XAStart=0; + +/* + int i; + for(i=0;i +#include +#include +#include +#include +#ifndef _MACOSX +#include +#endif +#include +#ifndef NOTHREADLIB +#include +#endif +#define RRand(range) (random()%range) +#include +#include +#include + +#undef CALLBACK +#define CALLBACK +#define DWORD unsigned long +#define LOWORD(l) ((unsigned short)(l)) +#define HIWORD(l) ((unsigned short)(((unsigned long)(l) >> 16) & 0xFFFF)) + +#undef INLINE +#define INLINE inline + +#include "psemuxa.h" diff --git a/macosx/plugins/PeopsSpu109/src/swap.h b/macosx/plugins/PeopsSpu109/src/swap.h new file mode 100755 index 00000000..23ec297b --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/swap.h @@ -0,0 +1,21 @@ + +// byteswappings + +#define SWAP16(x) (((x)>>8 & 0xff) | ((x)<<8 & 0xff00)) +#define SWAP32(x) (((x)>>24 & 0xfful) | ((x)>>8 & 0xff00ul) | ((x)<<8 & 0xff0000ul) | ((x)<<24 & 0xff000000ul)) + +#ifdef __POWERPC__ + +#define HOST2LE16(x) SWAP16(x) +#define HOST2BE16(x) (x) +#define LE2HOST16(x) SWAP16(x) +#define BE2HOST16(x) (x) + +#else + +#define HOST2LE16(x) (x) +#define HOST2BE16(x) SWAP16(x) +#define LE2HOST16(x) (x) +#define BE2HOST16(x) SWAP16(x) + +#endif diff --git a/macosx/plugins/PeopsSpu109/src/xa.c b/macosx/plugins/PeopsSpu109/src/xa.c new file mode 100755 index 00000000..651ad7ce --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/xa.c @@ -0,0 +1,367 @@ +/*************************************************************************** + xa.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/02/18 - kode54 +// - added gaussian interpolation +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_XA + +// will be included from spu.c +#ifdef _IN_SPU + +#define XA_HACK + +//////////////////////////////////////////////////////////////////////// +// XA GLOBALS +//////////////////////////////////////////////////////////////////////// + +xa_decode_t * xapGlobal=0; + +unsigned long * XAFeed = NULL; +unsigned long * XAPlay = NULL; +unsigned long * XAStart = NULL; +unsigned long * XAEnd = NULL; +unsigned long XARepeat = 0; +unsigned long XALastVal = 0; + +int iLeftXAVol = 32767; +int iRightXAVol = 32767; + +static int gauss_ptr = 0; +static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + +#define gvall0 gauss_window[gauss_ptr] +#define gvall(x) gauss_window[(gauss_ptr+x)&3] +#define gvalr0 gauss_window[4+gauss_ptr] +#define gvalr(x) gauss_window[4+((gauss_ptr+x)&3)] + +//////////////////////////////////////////////////////////////////////// +// MIX XA +//////////////////////////////////////////////////////////////////////// + +INLINE void MixXA(void) +{ + int ns; + + for(ns=0;ns>16)&0xffff)) * iRightXAVol)/32768; + } + + if(XAPlay==XAFeed && XARepeat) + { + XARepeat--; + for(;ns>16)&0xffff)) * iRightXAVol)/32768; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// FEED XA +//////////////////////////////////////////////////////////////////////// + +INLINE void FeedXA(xa_decode_t *xap) +{ + int sinc,spos,i,iSize,iPlace,vl,vr; + + if(!bSPUIsOpen) return; + + xapGlobal = xap; // store info for save states + XARepeat = 100; // set up repeat + +#ifdef XA_HACK + iSize=((45500*xap->nsamples)/xap->freq); // get size +#else + iSize=((44100*xap->nsamples)/xap->freq); // get size +#endif + if(!iSize) return; // none? bye + + if(XAFeed=10) + { + if(!dwFPS) dwFPS=1; + dw1=1000000/dwFPS; + if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1; + else dwL1=dw1; + dw2=(xap->freq*100/xap->nsamples); + if((!dw1)||((dw2+100)>=dw1)) iLastSize=0; + else + { + iLastSize=iSize*dw2/dw1; + if(iLastSize>iPlace) iLastSize=iPlace; + iSize=iLastSize; + } + iFPSCnt=0;dwFPS=0; + } + else + { + if(iLastSize) iSize=iLastSize; + } + } + //----------------------------------------------------// + + spos=0x10000L; + sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size + + if(xap->stereo) + { + unsigned long * pS=(unsigned long *)xap->pcm; + unsigned long l=0; + + if(iXAPitch) + { + long l1,l2;short s; + for(i=0;i=0x10000L) + { + l = *pS++; + gauss_window[gauss_ptr] = (short)LOWORD(l); + gauss_window[4+gauss_ptr] = (short)HIWORD(l); + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l= (vr >> 11) & 0xffff; + vr=(gauss[vl]*gvalr0)&~2047; + vr+=(gauss[vl+1]*gvalr(1))&~2047; + vr+=(gauss[vl+2]*gvalr(2))&~2047; + vr+=(gauss[vl+3]*gvalr(3))&~2047; + l |= vr << 5; + } + else + { + while(spos>=0x10000L) + { + l = *pS++; + spos -= 0x10000L; + } + } + + s=(short)LOWORD(l); + l1=s; + l1=(l1*iPlace)/iSize; + if(l1<-32767) l1=-32767; + if(l1> 32767) l1=32767; + s=(short)HIWORD(l); + l2=s; + l2=(l2*iPlace)/iSize; + if(l2<-32767) l2=-32767; + if(l2> 32767) l2=32767; + l=(l1&0xffff)|(l2<<16); + + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + else + { + for(i=0;i=0x10000L) + { + l = *pS++; + gauss_window[gauss_ptr] = (short)LOWORD(l); + gauss_window[4+gauss_ptr] = (short)HIWORD(l); + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l= (vr >> 11) & 0xffff; + vr=(gauss[vl]*gvalr0)&~2047; + vr+=(gauss[vl+1]*gvalr(1))&~2047; + vr+=(gauss[vl+2]*gvalr(2))&~2047; + vr+=(gauss[vl+3]*gvalr(3))&~2047; + l |= vr << 5; + } + else + { + while(spos>=0x10000L) + { + l = *pS++; + spos -= 0x10000L; + } + } + + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + } + else + { + unsigned short * pS=(unsigned short *)xap->pcm; + unsigned long l;short s=0; + + if(iXAPitch) + { + long l1; + for(i=0;i=0x10000L) + { + gauss_window[gauss_ptr] = (short)*pS++; + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l1=s= vr >> 11; + l1 &= 0xffff; + } + else + { + while(spos>=0x10000L) + { + s = *pS++; + spos -= 0x10000L; + } + l1=s; + } + + l1=(l1*iPlace)/iSize; + if(l1<-32767) l1=-32767; + if(l1> 32767) l1=32767; + l=(l1&0xffff)|(l1<<16); + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + else + { + for(i=0;i=0x10000L) + { + gauss_window[gauss_ptr] = (short)*pS++; + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l=s= vr >> 11; + l &= 0xffff; + } + else + { + while(spos>=0x10000L) + { + s = *pS++; + spos -= 0x10000L; + } + l=s; + } + + *XAFeed++=(l|(l<<16)); + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + } +} + +#endif \ No newline at end of file diff --git a/macosx/plugins/PeopsSpu109/src/xa.h b/macosx/plugins/PeopsSpu109/src/xa.h new file mode 100755 index 00000000..0430552a --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/xa.h @@ -0,0 +1,29 @@ +/*************************************************************************** + xa.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +INLINE void MixXA(void); +INLINE void FeedXA(xa_decode_t *xap); diff --git a/macosx/plugins/PeopsSpu109/src/zn.c b/macosx/plugins/PeopsSpu109/src/zn.c new file mode 100755 index 00000000..1cc8a6b2 --- /dev/null +++ b/macosx/plugins/PeopsSpu109/src/zn.c @@ -0,0 +1,183 @@ +/*************************************************************************** + zn.c - description + -------------------- + begin : Wed April 23 2004 + copyright : (C) 2004 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/04/23 - Pete +// - added ZINC zn interface +// +//*************************************************************************// + +#include "stdafx.h" +#include "xa.h" + +//*************************************************************************// +// global marker, if ZINC is running + +int iZincEmu=0; + +//-------------------------------------------------------------------------// +// not used by ZINC + +void CALLBACK SPUasync(unsigned long cycle); + +void CALLBACK ZN_SPUupdate(void) +{ + SPUasync(0); +} + +//-------------------------------------------------------------------------// + +void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val); + +void CALLBACK ZN_SPUwriteRegister(unsigned long reg, unsigned short val) +{ + SPUwriteRegister(reg,val); +} + +//-------------------------------------------------------------------------// + +unsigned short CALLBACK SPUreadRegister(unsigned long reg); + +unsigned short CALLBACK ZN_SPUreadRegister(unsigned long reg) +{ + return SPUreadRegister(reg); +} + +//-------------------------------------------------------------------------// +// not used by ZINC + +unsigned short CALLBACK SPUreadDMA(void); + +unsigned short CALLBACK ZN_SPUreadDMA(void) +{ + return SPUreadDMA(); +} + +//-------------------------------------------------------------------------// +// not used by ZINC + +void CALLBACK SPUwriteDMA(unsigned short val); + +void CALLBACK ZN_SPUwriteDMA(unsigned short val) +{ + SPUwriteDMA(val); +} + +//-------------------------------------------------------------------------// +// not used by ZINC + +void CALLBACK SPUwriteDMAMem(unsigned short * pusPSXMem,int iSize); + +void CALLBACK ZN_SPUwriteDMAMem(unsigned short * pusPSXMem,int iSize) +{ + SPUwriteDMAMem(pusPSXMem,iSize); +} + +//-------------------------------------------------------------------------// +// not used by ZINC + +void CALLBACK SPUreadDMAMem(unsigned short * pusPSXMem,int iSize); + +void CALLBACK ZN_SPUreadDMAMem(unsigned short * pusPSXMem,int iSize) +{ + SPUreadDMAMem(pusPSXMem,iSize); +} + +//-------------------------------------------------------------------------// +// not used by ZINC + +void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap); + +void CALLBACK ZN_SPUplayADPCMchannel(xa_decode_t *xap) +{ + SPUplayADPCMchannel(xap); +} + +//-------------------------------------------------------------------------// +// attention: no separate SPUInit/Shutdown funcs in ZN interface + +long CALLBACK SPUinit(void); + +#ifdef _WINDOWS + +long CALLBACK SPUopen(HWND hW); + +long CALLBACK ZN_SPUopen(HWND hW) +{ + iZincEmu=1; + SPUinit(); + return SPUopen(hW); +} + +#else + +long SPUopen(void); + +long ZN_SPUopen(void) +{ + iZincEmu=1; + SPUinit(); + return SPUopen(); +} + +#endif + +//-------------------------------------------------------------------------// + +long CALLBACK SPUshutdown(void); +long CALLBACK SPUclose(void); + +long CALLBACK ZN_SPUclose(void) +{ + long lret=SPUclose(); + SPUshutdown(); + return lret; +} + +//-------------------------------------------------------------------------// +// not used by ZINC + +void CALLBACK SPUregisterCallback(void (CALLBACK *callback)(void)); + +void CALLBACK ZN_SPUregisterCallback(void (CALLBACK *callback)(void)) +{ + SPUregisterCallback(callback); +} + +//-------------------------------------------------------------------------// +// not used by ZINC + +long CALLBACK SPUfreeze(unsigned long ulFreezeMode,void * pF); + +long CALLBACK ZN_SPUfreeze(unsigned long ulFreezeMode,void * pF) +{ + return SPUfreeze(ulFreezeMode,pF); +} + +//-------------------------------------------------------------------------// + +extern void (CALLBACK *irqQSound)(unsigned char *,long *,long); + +void CALLBACK ZN_SPUqsound(void (CALLBACK *callback)(unsigned char *,long *,long)) +{ + irqQSound = callback; +} + +//-------------------------------------------------------------------------// -- cgit v1.2.3