Replaced AudioOverload with HighlyComplete

This commit is contained in:
Chris Moeller 2013-09-30 03:36:30 -07:00
parent b9d451c96f
commit fdabbca701
282 changed files with 386188 additions and 89870 deletions

View file

@ -90,7 +90,6 @@
17B7CF5C0F5A05EE00A47027 /* pauseBadge.png in Resources */ = {isa = PBXBuildFile; fileRef = 17B7CF590F5A05EE00A47027 /* pauseBadge.png */; };
17B7CF5D0F5A05EE00A47027 /* playBadge.png in Resources */ = {isa = PBXBuildFile; fileRef = 17B7CF5A0F5A05EE00A47027 /* playBadge.png */; };
17B7CF5E0F5A05EE00A47027 /* stopBadge.png in Resources */ = {isa = PBXBuildFile; fileRef = 17B7CF5B0F5A05EE00A47027 /* stopBadge.png */; };
17B7CF970F5A0A4D00A47027 /* AudioOverload.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17B7CF7C0F5A09FD00A47027 /* AudioOverload.bundle */; };
17BB5CED0B8A86010009ACB1 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17BB5CEC0B8A86010009ACB1 /* AudioToolbox.framework */; };
17BB5CF90B8A86350009ACB1 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17BB5CF60B8A86350009ACB1 /* AudioUnit.framework */; };
17BB5CFA0B8A86350009ACB1 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17BB5CF70B8A86350009ACB1 /* CoreAudio.framework */; };
@ -146,6 +145,7 @@
56C63D910D647DF300EAE25A /* NSComparisonPredicate+CogPredicate.m in Sources */ = {isa = PBXBuildFile; fileRef = 56C63D900D647DF300EAE25A /* NSComparisonPredicate+CogPredicate.m */; };
56DB084C0D6717DC00453B6A /* NSNumber+CogSort.m in Sources */ = {isa = PBXBuildFile; fileRef = 56DB084B0D6717DC00453B6A /* NSNumber+CogSort.m */; };
56DB08550D67185300453B6A /* NSArray+CogSort.m in Sources */ = {isa = PBXBuildFile; fileRef = 56DB08540D67185300453B6A /* NSArray+CogSort.m */; };
8360EF6D17F92E56005208A4 /* HighlyComplete.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8360EF0517F92B24005208A4 /* HighlyComplete.bundle */; };
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
@ -177,20 +177,6 @@
remoteGlobalIDString = 99B989F30CC7E10400C256E9;
remoteInfo = "APL Plugin";
};
17B7CF7B0F5A09FD00A47027 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 17B7CF770F5A09FD00A47027 /* AudioOverload.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 8D5B49B6048680CD000E48DA;
remoteInfo = AudioOverload;
};
17B7CF950F5A0A3700A47027 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 17B7CF770F5A09FD00A47027 /* AudioOverload.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = 8D5B49AC048680CD000E48DA;
remoteInfo = "AudioOverload Plugin";
};
17C808780C3BD167005707C4 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 17C808710C3BD167005707C4 /* FileSource.xcodeproj */;
@ -422,6 +408,13 @@
remoteGlobalIDString = 99B989F40CC7E10400C256E9;
remoteInfo = "APL Plugin";
};
8360EF0417F92B24005208A4 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 8360EF0017F92B23005208A4 /* HighlyComplete.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 8360EEE417F92AC8005208A4;
remoteInfo = HighlyComplete;
};
8E8D40860CBB036600135C1B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 8E8D40820CBB036600135C1B /* M3u.xcodeproj */;
@ -475,7 +468,7 @@
dstPath = "";
dstSubfolderSpec = 13;
files = (
17B7CF970F5A0A4D00A47027 /* AudioOverload.bundle in CopyFiles */,
8360EF6D17F92E56005208A4 /* HighlyComplete.bundle in CopyFiles */,
99EAACA80DD1BB7A00423C38 /* APL.bundle in CopyFiles */,
17C8F7D80CBEF3EF008D969D /* Dumb.bundle in CopyFiles */,
17C8F3CF0CBED66C008D969D /* GME.bundle in CopyFiles */,
@ -638,7 +631,6 @@
17B7CF590F5A05EE00A47027 /* pauseBadge.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = pauseBadge.png; path = Images/pauseBadge.png; sourceTree = "<group>"; };
17B7CF5A0F5A05EE00A47027 /* playBadge.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = playBadge.png; path = Images/playBadge.png; sourceTree = "<group>"; };
17B7CF5B0F5A05EE00A47027 /* stopBadge.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = stopBadge.png; path = Images/stopBadge.png; sourceTree = "<group>"; };
17B7CF770F5A09FD00A47027 /* AudioOverload.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AudioOverload.xcodeproj; path = Plugins/AudioOverload/AudioOverload.xcodeproj; sourceTree = "<group>"; };
17BB5CEC0B8A86010009ACB1 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = "<absolute>"; };
17BB5CF60B8A86350009ACB1 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = /System/Library/Frameworks/AudioUnit.framework; sourceTree = "<absolute>"; };
17BB5CF70B8A86350009ACB1 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = "<absolute>"; };
@ -722,6 +714,7 @@
56DB084B0D6717DC00453B6A /* NSNumber+CogSort.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSNumber+CogSort.m"; path = "Spotlight/NSNumber+CogSort.m"; sourceTree = "<group>"; };
56DB08530D67185300453B6A /* NSArray+CogSort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+CogSort.h"; path = "Spotlight/NSArray+CogSort.h"; sourceTree = "<group>"; };
56DB08540D67185300453B6A /* NSArray+CogSort.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+CogSort.m"; path = "Spotlight/NSArray+CogSort.m"; sourceTree = "<group>"; };
8360EF0017F92B23005208A4 /* HighlyComplete.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = HighlyComplete.xcodeproj; path = Plugins/HighlyComplete/HighlyComplete.xcodeproj; sourceTree = "<group>"; };
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
8E07AB760AAC930B00A4B32F /* PreferencesController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PreferencesController.h; path = Preferences/PreferencesController.h; sourceTree = "<group>"; };
8E07AB770AAC930B00A4B32F /* PreferencesController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = PreferencesController.m; path = Preferences/PreferencesController.m; sourceTree = "<group>"; };
@ -985,7 +978,7 @@
17B619FF0B909ED400BC003F /* PlugIns */ = {
isa = PBXGroup;
children = (
17B7CF770F5A09FD00A47027 /* AudioOverload.xcodeproj */,
8360EF0017F92B23005208A4 /* HighlyComplete.xcodeproj */,
B09E94300D747F7B0064F138 /* WMA.xcodeproj */,
566D32160D538550004466A5 /* APL.xcodeproj */,
17C8F7D20CBEF3E8008D969D /* Dumb.xcodeproj */,
@ -1008,14 +1001,6 @@
name = PlugIns;
sourceTree = "<group>";
};
17B7CF780F5A09FD00A47027 /* Products */ = {
isa = PBXGroup;
children = (
17B7CF7C0F5A09FD00A47027 /* AudioOverload.bundle */,
);
name = Products;
sourceTree = "<group>";
};
17C808720C3BD167005707C4 /* Products */ = {
isa = PBXGroup;
children = (
@ -1336,6 +1321,14 @@
name = Categories;
sourceTree = "<group>";
};
8360EF0117F92B23005208A4 /* Products */ = {
isa = PBXGroup;
children = (
8360EF0517F92B24005208A4 /* HighlyComplete.bundle */,
);
name = Products;
sourceTree = "<group>";
};
8E07AAEA0AAC90DC00A4B32F /* Preferences */ = {
isa = PBXGroup;
children = (
@ -1484,7 +1477,6 @@
17C8F44C0CBEDD37008D969D /* PBXTargetDependency */,
17C8F7DA0CBEF3F9008D969D /* PBXTargetDependency */,
17643CBC0D5BD44900F0A9FE /* PBXTargetDependency */,
17B7CF960F5A0A3700A47027 /* PBXTargetDependency */,
);
name = Cog;
productInstallPath = "$(HOME)/Applications";
@ -1520,10 +1512,6 @@
ProductGroup = 566D32170D538550004466A5 /* Products */;
ProjectRef = 566D32160D538550004466A5 /* APL.xcodeproj */;
},
{
ProductGroup = 17B7CF780F5A09FD00A47027 /* Products */;
ProjectRef = 17B7CF770F5A09FD00A47027 /* AudioOverload.xcodeproj */;
},
{
ProductGroup = 17F5612B0C3BD4DC0019975C /* Products */;
ProjectRef = 17F5612A0C3BD4DC0019975C /* CogAudio.xcodeproj */;
@ -1556,6 +1544,10 @@
ProductGroup = 17C8F3C90CBED663008D969D /* Products */;
ProjectRef = 17C8F3C80CBED663008D969D /* GME.xcodeproj */;
},
{
ProductGroup = 8360EF0117F92B23005208A4 /* Products */;
ProjectRef = 8360EF0017F92B23005208A4 /* HighlyComplete.xcodeproj */;
},
{
ProductGroup = 17C808840C3BD181005707C4 /* Products */;
ProjectRef = 17C808830C3BD181005707C4 /* HTTPSource.xcodeproj */;
@ -1609,13 +1601,6 @@
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
17B7CF7C0F5A09FD00A47027 /* AudioOverload.bundle */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = AudioOverload.bundle;
remoteRef = 17B7CF7B0F5A09FD00A47027 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
17C808790C3BD167005707C4 /* FileSource.bundle */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
@ -1735,6 +1720,13 @@
remoteRef = 566D321A0D538550004466A5 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
8360EF0517F92B24005208A4 /* HighlyComplete.bundle */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = HighlyComplete.bundle;
remoteRef = 8360EF0417F92B24005208A4 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
8E8D40870CBB036600135C1B /* M3u.bundle */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
@ -1916,11 +1908,6 @@
name = "APL Plugin";
targetProxy = 17643CBB0D5BD44900F0A9FE /* PBXContainerItemProxy */;
};
17B7CF960F5A0A3700A47027 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = "AudioOverload Plugin";
targetProxy = 17B7CF950F5A0A3700A47027 /* PBXContainerItemProxy */;
};
17C8097E0C3BD1F5005707C4 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = Musepack;

View file

@ -1,647 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 45;
objects = {
/* Begin PBXBuildFile section */
176038910F5A2BA000294631 /* ao.h in Headers */ = {isa = PBXBuildFile; fileRef = 176038900F5A2BA000294631 /* ao.h */; settings = {ATTRIBUTES = (Public, ); }; };
17F0D79A0F5A1E46008C62A7 /* corlett.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D72E0F5A1E46008C62A7 /* corlett.c */; };
17F0D79B0F5A1E46008C62A7 /* corlett.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D72F0F5A1E46008C62A7 /* corlett.h */; };
17F0D79C0F5A1E46008C62A7 /* cpuintrf.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7300F5A1E46008C62A7 /* cpuintrf.h */; };
17F0D79E0F5A1E46008C62A7 /* aica.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7330F5A1E46008C62A7 /* aica.c */; };
17F0D79F0F5A1E46008C62A7 /* aica.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7340F5A1E46008C62A7 /* aica.h */; };
17F0D7A00F5A1E46008C62A7 /* aicadsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7350F5A1E46008C62A7 /* aicadsp.c */; };
17F0D7A10F5A1E46008C62A7 /* aicadsp.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7360F5A1E46008C62A7 /* aicadsp.h */; };
17F0D7A30F5A1E46008C62A7 /* arm7.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7380F5A1E46008C62A7 /* arm7.c */; };
17F0D7A40F5A1E46008C62A7 /* arm7.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7390F5A1E46008C62A7 /* arm7.h */; };
17F0D7A50F5A1E46008C62A7 /* arm7i.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D73A0F5A1E46008C62A7 /* arm7i.c */; };
17F0D7A60F5A1E46008C62A7 /* arm7i.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D73B0F5A1E46008C62A7 /* arm7i.h */; };
17F0D7A90F5A1E46008C62A7 /* arm7thumb.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D73E0F5A1E46008C62A7 /* arm7thumb.h */; };
17F0D7AA0F5A1E46008C62A7 /* dc_hw.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D73F0F5A1E46008C62A7 /* dc_hw.c */; };
17F0D7AB0F5A1E46008C62A7 /* dc_hw.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7400F5A1E46008C62A7 /* dc_hw.h */; };
17F0D7AC0F5A1E46008C62A7 /* eng_dsf.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7410F5A1E46008C62A7 /* eng_dsf.c */; };
17F0D7AD0F5A1E46008C62A7 /* eng_protos.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7420F5A1E46008C62A7 /* eng_protos.h */; settings = {ATTRIBUTES = (Public, ); }; };
17F0D7AE0F5A1E46008C62A7 /* cpuintrf.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7440F5A1E46008C62A7 /* cpuintrf.h */; };
17F0D7AF0F5A1E46008C62A7 /* eng_psf.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7450F5A1E46008C62A7 /* eng_psf.c */; };
17F0D7B00F5A1E46008C62A7 /* eng_psf2.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7460F5A1E46008C62A7 /* eng_psf2.c */; };
17F0D7B10F5A1E46008C62A7 /* eng_spu.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7470F5A1E46008C62A7 /* eng_spu.c */; };
17F0D7B20F5A1E46008C62A7 /* mamemem.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7480F5A1E46008C62A7 /* mamemem.h */; };
17F0D7D20F5A1E46008C62A7 /* psx.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D76A0F5A1E46008C62A7 /* psx.c */; };
17F0D7D30F5A1E46008C62A7 /* psx.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D76B0F5A1E46008C62A7 /* psx.h */; };
17F0D7D40F5A1E46008C62A7 /* psx_hw.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D76C0F5A1E46008C62A7 /* psx_hw.c */; };
17F0D7D50F5A1E46008C62A7 /* eng_qsf.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D76E0F5A1E46008C62A7 /* eng_qsf.c */; };
17F0D7D60F5A1E46008C62A7 /* kabuki.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D76F0F5A1E46008C62A7 /* kabuki.c */; };
17F0D7D70F5A1E46008C62A7 /* qsound.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7700F5A1E46008C62A7 /* qsound.c */; };
17F0D7D80F5A1E46008C62A7 /* qsound.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7710F5A1E46008C62A7 /* qsound.h */; };
17F0D7D90F5A1E46008C62A7 /* z80.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7720F5A1E46008C62A7 /* z80.c */; };
17F0D7DA0F5A1E46008C62A7 /* z80.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7730F5A1E46008C62A7 /* z80.h */; };
17F0D7DB0F5A1E46008C62A7 /* z80dasm.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7740F5A1E46008C62A7 /* z80dasm.c */; };
17F0D7DC0F5A1E46008C62A7 /* z80dasm.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7750F5A1E46008C62A7 /* z80dasm.h */; };
17F0D7DD0F5A1E46008C62A7 /* eng_ssf.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7770F5A1E46008C62A7 /* eng_ssf.c */; };
17F0D7DE0F5A1E46008C62A7 /* m68k.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7780F5A1E46008C62A7 /* m68k.h */; };
17F0D7E00F5A1E46008C62A7 /* m68kconf.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D77A0F5A1E46008C62A7 /* m68kconf.h */; };
17F0D7E10F5A1E46008C62A7 /* m68kcpu.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D77B0F5A1E46008C62A7 /* m68kcpu.c */; };
17F0D7E20F5A1E46008C62A7 /* m68kcpu.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D77C0F5A1E46008C62A7 /* m68kcpu.h */; };
17F0D7E40F5A1E46008C62A7 /* m68kmame.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D77E0F5A1E46008C62A7 /* m68kmame.h */; };
17F0D7E50F5A1E46008C62A7 /* m68kopac.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D77F0F5A1E46008C62A7 /* m68kopac.c */; };
17F0D7E60F5A1E46008C62A7 /* m68kopdm.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7800F5A1E46008C62A7 /* m68kopdm.c */; };
17F0D7E70F5A1E46008C62A7 /* m68kopnz.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7810F5A1E46008C62A7 /* m68kopnz.c */; };
17F0D7E80F5A1E46008C62A7 /* m68kops.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7820F5A1E46008C62A7 /* m68kops.c */; };
17F0D7E90F5A1E46008C62A7 /* m68kops.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7830F5A1E46008C62A7 /* m68kops.h */; };
17F0D7EA0F5A1E46008C62A7 /* sat_hw.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7840F5A1E46008C62A7 /* sat_hw.c */; };
17F0D7EB0F5A1E46008C62A7 /* sat_hw.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7850F5A1E46008C62A7 /* sat_hw.h */; };
17F0D7EC0F5A1E46008C62A7 /* scsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7860F5A1E46008C62A7 /* scsp.c */; };
17F0D7ED0F5A1E46008C62A7 /* scsp.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7870F5A1E46008C62A7 /* scsp.h */; };
17F0D7EE0F5A1E46008C62A7 /* scspdsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7880F5A1E46008C62A7 /* scspdsp.c */; };
17F0D7EF0F5A1E46008C62A7 /* scspdsp.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7890F5A1E46008C62A7 /* scspdsp.h */; };
17F0D7F50F5A1E46008C62A7 /* mem.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D78F0F5A1E46008C62A7 /* mem.h */; };
17F0D7F60F5A1E46008C62A7 /* osd_cpu.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F0D7900F5A1E46008C62A7 /* osd_cpu.h */; };
17F0D8240F5A1F1E008C62A7 /* spu.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7550F5A1E46008C62A7 /* spu.c */; };
17F0D8340F5A1F80008C62A7 /* spu.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7660F5A1E46008C62A7 /* spu.c */; };
17F0D8350F5A1F83008C62A7 /* dma.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D75B0F5A1E46008C62A7 /* dma.c */; };
17F0D8360F5A1F86008C62A7 /* registers.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D7610F5A1E46008C62A7 /* registers.c */; };
17F0D8A60F5A24E9008C62A7 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 17F0D8A50F5A24E9008C62A7 /* main.c */; };
17F0D9160F5A268F008C62A7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 17F0D9150F5A268F008C62A7 /* libz.dylib */; };
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
176038900F5A2BA000294631 /* ao.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ao.h; path = aosdk/ao.h; sourceTree = "<group>"; };
17F0D72E0F5A1E46008C62A7 /* corlett.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = corlett.c; path = aosdk/corlett.c; sourceTree = "<group>"; };
17F0D72F0F5A1E46008C62A7 /* corlett.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = corlett.h; path = aosdk/corlett.h; sourceTree = "<group>"; };
17F0D7300F5A1E46008C62A7 /* cpuintrf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cpuintrf.h; path = aosdk/cpuintrf.h; sourceTree = "<group>"; };
17F0D7330F5A1E46008C62A7 /* aica.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aica.c; sourceTree = "<group>"; };
17F0D7340F5A1E46008C62A7 /* aica.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aica.h; sourceTree = "<group>"; };
17F0D7350F5A1E46008C62A7 /* aicadsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aicadsp.c; sourceTree = "<group>"; };
17F0D7360F5A1E46008C62A7 /* aicadsp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aicadsp.h; sourceTree = "<group>"; };
17F0D7370F5A1E46008C62A7 /* aicalfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aicalfo.c; sourceTree = "<group>"; };
17F0D7380F5A1E46008C62A7 /* arm7.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arm7.c; sourceTree = "<group>"; };
17F0D7390F5A1E46008C62A7 /* arm7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arm7.h; sourceTree = "<group>"; };
17F0D73A0F5A1E46008C62A7 /* arm7i.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arm7i.c; sourceTree = "<group>"; };
17F0D73B0F5A1E46008C62A7 /* arm7i.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arm7i.h; sourceTree = "<group>"; };
17F0D73C0F5A1E46008C62A7 /* arm7memil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arm7memil.c; sourceTree = "<group>"; };
17F0D73D0F5A1E46008C62A7 /* arm7thumb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arm7thumb.c; sourceTree = "<group>"; };
17F0D73E0F5A1E46008C62A7 /* arm7thumb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arm7thumb.h; sourceTree = "<group>"; };
17F0D73F0F5A1E46008C62A7 /* dc_hw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_hw.c; sourceTree = "<group>"; };
17F0D7400F5A1E46008C62A7 /* dc_hw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dc_hw.h; sourceTree = "<group>"; };
17F0D7410F5A1E46008C62A7 /* eng_dsf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eng_dsf.c; sourceTree = "<group>"; };
17F0D7420F5A1E46008C62A7 /* eng_protos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eng_protos.h; path = aosdk/eng_protos.h; sourceTree = "<group>"; };
17F0D7440F5A1E46008C62A7 /* cpuintrf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpuintrf.h; sourceTree = "<group>"; };
17F0D7450F5A1E46008C62A7 /* eng_psf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eng_psf.c; sourceTree = "<group>"; };
17F0D7460F5A1E46008C62A7 /* eng_psf2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eng_psf2.c; sourceTree = "<group>"; };
17F0D7470F5A1E46008C62A7 /* eng_spu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eng_spu.c; sourceTree = "<group>"; };
17F0D7480F5A1E46008C62A7 /* mamemem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mamemem.h; sourceTree = "<group>"; };
17F0D74A0F5A1E46008C62A7 /* adsr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adsr.c; sourceTree = "<group>"; };
17F0D74B0F5A1E46008C62A7 /* adsr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = adsr.h; sourceTree = "<group>"; };
17F0D74C0F5A1E46008C62A7 /* dma.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dma.c; sourceTree = "<group>"; };
17F0D74D0F5A1E46008C62A7 /* dma.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dma.h; sourceTree = "<group>"; };
17F0D74E0F5A1E46008C62A7 /* externals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = externals.h; sourceTree = "<group>"; };
17F0D74F0F5A1E46008C62A7 /* gauss_i.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gauss_i.h; sourceTree = "<group>"; };
17F0D7500F5A1E46008C62A7 /* License.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = License.txt; sourceTree = "<group>"; };
17F0D7510F5A1E46008C62A7 /* registers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = registers.c; sourceTree = "<group>"; };
17F0D7520F5A1E46008C62A7 /* registers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = registers.h; sourceTree = "<group>"; };
17F0D7530F5A1E46008C62A7 /* regs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regs.h; sourceTree = "<group>"; };
17F0D7540F5A1E46008C62A7 /* reverb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = reverb.c; sourceTree = "<group>"; };
17F0D7550F5A1E46008C62A7 /* spu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = spu.c; sourceTree = "<group>"; };
17F0D7560F5A1E46008C62A7 /* spu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = spu.h; sourceTree = "<group>"; };
17F0D7570F5A1E46008C62A7 /* stdafx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stdafx.h; sourceTree = "<group>"; };
17F0D7590F5A1E46008C62A7 /* adsr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adsr.c; sourceTree = "<group>"; };
17F0D75A0F5A1E46008C62A7 /* adsr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = adsr.h; sourceTree = "<group>"; };
17F0D75B0F5A1E46008C62A7 /* dma.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dma.c; sourceTree = "<group>"; };
17F0D75C0F5A1E46008C62A7 /* dma.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dma.h; sourceTree = "<group>"; };
17F0D75D0F5A1E46008C62A7 /* externals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = externals.h; sourceTree = "<group>"; };
17F0D75E0F5A1E46008C62A7 /* gauss_i.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gauss_i.h; sourceTree = "<group>"; };
17F0D75F0F5A1E46008C62A7 /* License.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = License.txt; sourceTree = "<group>"; };
17F0D7600F5A1E46008C62A7 /* psemuxa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = psemuxa.h; sourceTree = "<group>"; };
17F0D7610F5A1E46008C62A7 /* registers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = registers.c; sourceTree = "<group>"; };
17F0D7620F5A1E46008C62A7 /* registers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = registers.h; sourceTree = "<group>"; };
17F0D7630F5A1E46008C62A7 /* regs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regs.h; sourceTree = "<group>"; };
17F0D7640F5A1E46008C62A7 /* reverb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = reverb.c; sourceTree = "<group>"; };
17F0D7650F5A1E46008C62A7 /* reverb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reverb.h; sourceTree = "<group>"; };
17F0D7660F5A1E46008C62A7 /* spu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = spu.c; sourceTree = "<group>"; };
17F0D7670F5A1E46008C62A7 /* spu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = spu.h; sourceTree = "<group>"; };
17F0D7680F5A1E46008C62A7 /* stdafx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stdafx.h; sourceTree = "<group>"; };
17F0D7690F5A1E46008C62A7 /* xa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xa.c; sourceTree = "<group>"; };
17F0D76A0F5A1E46008C62A7 /* psx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx.c; sourceTree = "<group>"; };
17F0D76B0F5A1E46008C62A7 /* psx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = psx.h; sourceTree = "<group>"; };
17F0D76C0F5A1E46008C62A7 /* psx_hw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_hw.c; sourceTree = "<group>"; };
17F0D76E0F5A1E46008C62A7 /* eng_qsf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eng_qsf.c; sourceTree = "<group>"; };
17F0D76F0F5A1E46008C62A7 /* kabuki.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kabuki.c; sourceTree = "<group>"; };
17F0D7700F5A1E46008C62A7 /* qsound.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = qsound.c; sourceTree = "<group>"; };
17F0D7710F5A1E46008C62A7 /* qsound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = qsound.h; sourceTree = "<group>"; };
17F0D7720F5A1E46008C62A7 /* z80.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = z80.c; sourceTree = "<group>"; };
17F0D7730F5A1E46008C62A7 /* z80.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = z80.h; sourceTree = "<group>"; };
17F0D7740F5A1E46008C62A7 /* z80dasm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = z80dasm.c; sourceTree = "<group>"; };
17F0D7750F5A1E46008C62A7 /* z80dasm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = z80dasm.h; sourceTree = "<group>"; };
17F0D7770F5A1E46008C62A7 /* eng_ssf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eng_ssf.c; sourceTree = "<group>"; };
17F0D7780F5A1E46008C62A7 /* m68k.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m68k.h; sourceTree = "<group>"; };
17F0D7790F5A1E46008C62A7 /* m68k_in.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m68k_in.c; sourceTree = "<group>"; };
17F0D77A0F5A1E46008C62A7 /* m68kconf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m68kconf.h; sourceTree = "<group>"; };
17F0D77B0F5A1E46008C62A7 /* m68kcpu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m68kcpu.c; sourceTree = "<group>"; };
17F0D77C0F5A1E46008C62A7 /* m68kcpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m68kcpu.h; sourceTree = "<group>"; };
17F0D77D0F5A1E46008C62A7 /* m68kmake.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m68kmake.c; sourceTree = "<group>"; };
17F0D77E0F5A1E46008C62A7 /* m68kmame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m68kmame.h; sourceTree = "<group>"; };
17F0D77F0F5A1E46008C62A7 /* m68kopac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m68kopac.c; sourceTree = "<group>"; };
17F0D7800F5A1E46008C62A7 /* m68kopdm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m68kopdm.c; sourceTree = "<group>"; };
17F0D7810F5A1E46008C62A7 /* m68kopnz.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m68kopnz.c; sourceTree = "<group>"; };
17F0D7820F5A1E46008C62A7 /* m68kops.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m68kops.c; sourceTree = "<group>"; };
17F0D7830F5A1E46008C62A7 /* m68kops.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m68kops.h; sourceTree = "<group>"; };
17F0D7840F5A1E46008C62A7 /* sat_hw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sat_hw.c; sourceTree = "<group>"; };
17F0D7850F5A1E46008C62A7 /* sat_hw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sat_hw.h; sourceTree = "<group>"; };
17F0D7860F5A1E46008C62A7 /* scsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scsp.c; sourceTree = "<group>"; };
17F0D7870F5A1E46008C62A7 /* scsp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scsp.h; sourceTree = "<group>"; };
17F0D7880F5A1E46008C62A7 /* scspdsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scspdsp.c; sourceTree = "<group>"; };
17F0D7890F5A1E46008C62A7 /* scspdsp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scspdsp.h; sourceTree = "<group>"; };
17F0D78A0F5A1E46008C62A7 /* scsplfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scsplfo.c; sourceTree = "<group>"; };
17F0D78F0F5A1E46008C62A7 /* mem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mem.h; path = aosdk/mem.h; sourceTree = "<group>"; };
17F0D7900F5A1E46008C62A7 /* osd_cpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = osd_cpu.h; path = aosdk/osd_cpu.h; sourceTree = "<group>"; };
17F0D8A50F5A24E9008C62A7 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = aosdk/main.c; sourceTree = "<group>"; };
17F0D9150F5A268F008C62A7 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = "<absolute>"; };
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8DC2EF5B0486A6940098B216 /* AudioOverload.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AudioOverload.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
8DC2EF560486A6940098B216 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
17F0D9160F5A268F008C62A7 /* libz.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
034768DFFF38A50411DB9C8B /* Products */ = {
isa = PBXGroup;
children = (
8DC2EF5B0486A6940098B216 /* AudioOverload.framework */,
);
name = Products;
sourceTree = "<group>";
};
0867D691FE84028FC02AAC07 /* AudioOverload */ = {
isa = PBXGroup;
children = (
08FB77AEFE84172EC02AAC07 /* Source */,
089C1665FE841158C02AAC07 /* Resources */,
0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
034768DFFF38A50411DB9C8B /* Products */,
);
name = AudioOverload;
sourceTree = "<group>";
};
0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = {
isa = PBXGroup;
children = (
1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */,
1058C7B2FEA5585E11CA2CBB /* Other Frameworks */,
);
name = "External Frameworks and Libraries";
sourceTree = "<group>";
};
089C1665FE841158C02AAC07 /* Resources */ = {
isa = PBXGroup;
children = (
8DC2EF5A0486A6940098B216 /* Info.plist */,
089C1666FE841158C02AAC07 /* InfoPlist.strings */,
);
name = Resources;
sourceTree = "<group>";
};
08FB77AEFE84172EC02AAC07 /* Source */ = {
isa = PBXGroup;
children = (
176038900F5A2BA000294631 /* ao.h */,
17F0D8A50F5A24E9008C62A7 /* main.c */,
17F0D72E0F5A1E46008C62A7 /* corlett.c */,
17F0D72F0F5A1E46008C62A7 /* corlett.h */,
17F0D7300F5A1E46008C62A7 /* cpuintrf.h */,
17F0D7320F5A1E46008C62A7 /* eng_dsf */,
17F0D7420F5A1E46008C62A7 /* eng_protos.h */,
17F0D7430F5A1E46008C62A7 /* eng_psf */,
17F0D76D0F5A1E46008C62A7 /* eng_qsf */,
17F0D7760F5A1E46008C62A7 /* eng_ssf */,
17F0D78F0F5A1E46008C62A7 /* mem.h */,
17F0D7900F5A1E46008C62A7 /* osd_cpu.h */,
);
name = Source;
sourceTree = "<group>";
};
1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */ = {
isa = PBXGroup;
children = (
17F0D9150F5A268F008C62A7 /* libz.dylib */,
);
name = "Linked Frameworks";
sourceTree = "<group>";
};
1058C7B2FEA5585E11CA2CBB /* Other Frameworks */ = {
isa = PBXGroup;
children = (
);
name = "Other Frameworks";
sourceTree = "<group>";
};
17F0D7320F5A1E46008C62A7 /* eng_dsf */ = {
isa = PBXGroup;
children = (
17F0D7330F5A1E46008C62A7 /* aica.c */,
17F0D7340F5A1E46008C62A7 /* aica.h */,
17F0D7350F5A1E46008C62A7 /* aicadsp.c */,
17F0D7360F5A1E46008C62A7 /* aicadsp.h */,
17F0D7370F5A1E46008C62A7 /* aicalfo.c */,
17F0D7380F5A1E46008C62A7 /* arm7.c */,
17F0D7390F5A1E46008C62A7 /* arm7.h */,
17F0D73A0F5A1E46008C62A7 /* arm7i.c */,
17F0D73B0F5A1E46008C62A7 /* arm7i.h */,
17F0D73C0F5A1E46008C62A7 /* arm7memil.c */,
17F0D73D0F5A1E46008C62A7 /* arm7thumb.c */,
17F0D73E0F5A1E46008C62A7 /* arm7thumb.h */,
17F0D73F0F5A1E46008C62A7 /* dc_hw.c */,
17F0D7400F5A1E46008C62A7 /* dc_hw.h */,
17F0D7410F5A1E46008C62A7 /* eng_dsf.c */,
);
name = eng_dsf;
path = aosdk/eng_dsf;
sourceTree = "<group>";
};
17F0D7430F5A1E46008C62A7 /* eng_psf */ = {
isa = PBXGroup;
children = (
17F0D7440F5A1E46008C62A7 /* cpuintrf.h */,
17F0D7450F5A1E46008C62A7 /* eng_psf.c */,
17F0D7460F5A1E46008C62A7 /* eng_psf2.c */,
17F0D7470F5A1E46008C62A7 /* eng_spu.c */,
17F0D7480F5A1E46008C62A7 /* mamemem.h */,
17F0D7490F5A1E46008C62A7 /* peops */,
17F0D7580F5A1E46008C62A7 /* peops2 */,
17F0D76A0F5A1E46008C62A7 /* psx.c */,
17F0D76B0F5A1E46008C62A7 /* psx.h */,
17F0D76C0F5A1E46008C62A7 /* psx_hw.c */,
);
name = eng_psf;
path = aosdk/eng_psf;
sourceTree = "<group>";
};
17F0D7490F5A1E46008C62A7 /* peops */ = {
isa = PBXGroup;
children = (
17F0D74A0F5A1E46008C62A7 /* adsr.c */,
17F0D74B0F5A1E46008C62A7 /* adsr.h */,
17F0D74C0F5A1E46008C62A7 /* dma.c */,
17F0D74D0F5A1E46008C62A7 /* dma.h */,
17F0D74E0F5A1E46008C62A7 /* externals.h */,
17F0D74F0F5A1E46008C62A7 /* gauss_i.h */,
17F0D7500F5A1E46008C62A7 /* License.txt */,
17F0D7510F5A1E46008C62A7 /* registers.c */,
17F0D7520F5A1E46008C62A7 /* registers.h */,
17F0D7530F5A1E46008C62A7 /* regs.h */,
17F0D7540F5A1E46008C62A7 /* reverb.c */,
17F0D7550F5A1E46008C62A7 /* spu.c */,
17F0D7560F5A1E46008C62A7 /* spu.h */,
17F0D7570F5A1E46008C62A7 /* stdafx.h */,
);
path = peops;
sourceTree = "<group>";
};
17F0D7580F5A1E46008C62A7 /* peops2 */ = {
isa = PBXGroup;
children = (
17F0D7590F5A1E46008C62A7 /* adsr.c */,
17F0D75A0F5A1E46008C62A7 /* adsr.h */,
17F0D75B0F5A1E46008C62A7 /* dma.c */,
17F0D75C0F5A1E46008C62A7 /* dma.h */,
17F0D75D0F5A1E46008C62A7 /* externals.h */,
17F0D75E0F5A1E46008C62A7 /* gauss_i.h */,
17F0D75F0F5A1E46008C62A7 /* License.txt */,
17F0D7600F5A1E46008C62A7 /* psemuxa.h */,
17F0D7610F5A1E46008C62A7 /* registers.c */,
17F0D7620F5A1E46008C62A7 /* registers.h */,
17F0D7630F5A1E46008C62A7 /* regs.h */,
17F0D7640F5A1E46008C62A7 /* reverb.c */,
17F0D7650F5A1E46008C62A7 /* reverb.h */,
17F0D7660F5A1E46008C62A7 /* spu.c */,
17F0D7670F5A1E46008C62A7 /* spu.h */,
17F0D7680F5A1E46008C62A7 /* stdafx.h */,
17F0D7690F5A1E46008C62A7 /* xa.c */,
);
path = peops2;
sourceTree = "<group>";
};
17F0D76D0F5A1E46008C62A7 /* eng_qsf */ = {
isa = PBXGroup;
children = (
17F0D76E0F5A1E46008C62A7 /* eng_qsf.c */,
17F0D76F0F5A1E46008C62A7 /* kabuki.c */,
17F0D7700F5A1E46008C62A7 /* qsound.c */,
17F0D7710F5A1E46008C62A7 /* qsound.h */,
17F0D7720F5A1E46008C62A7 /* z80.c */,
17F0D7730F5A1E46008C62A7 /* z80.h */,
17F0D7740F5A1E46008C62A7 /* z80dasm.c */,
17F0D7750F5A1E46008C62A7 /* z80dasm.h */,
);
name = eng_qsf;
path = aosdk/eng_qsf;
sourceTree = "<group>";
};
17F0D7760F5A1E46008C62A7 /* eng_ssf */ = {
isa = PBXGroup;
children = (
17F0D7770F5A1E46008C62A7 /* eng_ssf.c */,
17F0D7780F5A1E46008C62A7 /* m68k.h */,
17F0D7790F5A1E46008C62A7 /* m68k_in.c */,
17F0D77A0F5A1E46008C62A7 /* m68kconf.h */,
17F0D77B0F5A1E46008C62A7 /* m68kcpu.c */,
17F0D77C0F5A1E46008C62A7 /* m68kcpu.h */,
17F0D77D0F5A1E46008C62A7 /* m68kmake.c */,
17F0D77E0F5A1E46008C62A7 /* m68kmame.h */,
17F0D77F0F5A1E46008C62A7 /* m68kopac.c */,
17F0D7800F5A1E46008C62A7 /* m68kopdm.c */,
17F0D7810F5A1E46008C62A7 /* m68kopnz.c */,
17F0D7820F5A1E46008C62A7 /* m68kops.c */,
17F0D7830F5A1E46008C62A7 /* m68kops.h */,
17F0D7840F5A1E46008C62A7 /* sat_hw.c */,
17F0D7850F5A1E46008C62A7 /* sat_hw.h */,
17F0D7860F5A1E46008C62A7 /* scsp.c */,
17F0D7870F5A1E46008C62A7 /* scsp.h */,
17F0D7880F5A1E46008C62A7 /* scspdsp.c */,
17F0D7890F5A1E46008C62A7 /* scspdsp.h */,
17F0D78A0F5A1E46008C62A7 /* scsplfo.c */,
);
name = eng_ssf;
path = aosdk/eng_ssf;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
8DC2EF500486A6940098B216 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
17F0D79B0F5A1E46008C62A7 /* corlett.h in Headers */,
17F0D79C0F5A1E46008C62A7 /* cpuintrf.h in Headers */,
17F0D79F0F5A1E46008C62A7 /* aica.h in Headers */,
17F0D7A10F5A1E46008C62A7 /* aicadsp.h in Headers */,
17F0D7A40F5A1E46008C62A7 /* arm7.h in Headers */,
17F0D7A60F5A1E46008C62A7 /* arm7i.h in Headers */,
17F0D7A90F5A1E46008C62A7 /* arm7thumb.h in Headers */,
17F0D7AB0F5A1E46008C62A7 /* dc_hw.h in Headers */,
17F0D7AD0F5A1E46008C62A7 /* eng_protos.h in Headers */,
17F0D7AE0F5A1E46008C62A7 /* cpuintrf.h in Headers */,
17F0D7B20F5A1E46008C62A7 /* mamemem.h in Headers */,
17F0D7D30F5A1E46008C62A7 /* psx.h in Headers */,
17F0D7D80F5A1E46008C62A7 /* qsound.h in Headers */,
17F0D7DA0F5A1E46008C62A7 /* z80.h in Headers */,
17F0D7DC0F5A1E46008C62A7 /* z80dasm.h in Headers */,
17F0D7DE0F5A1E46008C62A7 /* m68k.h in Headers */,
17F0D7E00F5A1E46008C62A7 /* m68kconf.h in Headers */,
17F0D7E20F5A1E46008C62A7 /* m68kcpu.h in Headers */,
17F0D7E40F5A1E46008C62A7 /* m68kmame.h in Headers */,
17F0D7E90F5A1E46008C62A7 /* m68kops.h in Headers */,
17F0D7EB0F5A1E46008C62A7 /* sat_hw.h in Headers */,
17F0D7ED0F5A1E46008C62A7 /* scsp.h in Headers */,
17F0D7EF0F5A1E46008C62A7 /* scspdsp.h in Headers */,
17F0D7F50F5A1E46008C62A7 /* mem.h in Headers */,
17F0D7F60F5A1E46008C62A7 /* osd_cpu.h in Headers */,
176038910F5A2BA000294631 /* ao.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
8DC2EF4F0486A6940098B216 /* AudioOverload */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "AudioOverload" */;
buildPhases = (
8DC2EF500486A6940098B216 /* Headers */,
8DC2EF520486A6940098B216 /* Resources */,
8DC2EF540486A6940098B216 /* Sources */,
8DC2EF560486A6940098B216 /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = AudioOverload;
productInstallPath = "$(HOME)/Library/Frameworks";
productName = AudioOverload;
productReference = 8DC2EF5B0486A6940098B216 /* AudioOverload.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
0867D690FE84028FC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
};
buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "AudioOverload" */;
compatibilityVersion = "Xcode 3.1";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
en,
);
mainGroup = 0867D691FE84028FC02AAC07 /* AudioOverload */;
productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
8DC2EF4F0486A6940098B216 /* AudioOverload */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
8DC2EF520486A6940098B216 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
8DC2EF540486A6940098B216 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
17F0D79A0F5A1E46008C62A7 /* corlett.c in Sources */,
17F0D79E0F5A1E46008C62A7 /* aica.c in Sources */,
17F0D7A00F5A1E46008C62A7 /* aicadsp.c in Sources */,
17F0D7A30F5A1E46008C62A7 /* arm7.c in Sources */,
17F0D7A50F5A1E46008C62A7 /* arm7i.c in Sources */,
17F0D7AA0F5A1E46008C62A7 /* dc_hw.c in Sources */,
17F0D7AC0F5A1E46008C62A7 /* eng_dsf.c in Sources */,
17F0D7AF0F5A1E46008C62A7 /* eng_psf.c in Sources */,
17F0D7B00F5A1E46008C62A7 /* eng_psf2.c in Sources */,
17F0D7B10F5A1E46008C62A7 /* eng_spu.c in Sources */,
17F0D7D20F5A1E46008C62A7 /* psx.c in Sources */,
17F0D7D40F5A1E46008C62A7 /* psx_hw.c in Sources */,
17F0D7D50F5A1E46008C62A7 /* eng_qsf.c in Sources */,
17F0D7D60F5A1E46008C62A7 /* kabuki.c in Sources */,
17F0D7D70F5A1E46008C62A7 /* qsound.c in Sources */,
17F0D7D90F5A1E46008C62A7 /* z80.c in Sources */,
17F0D7DB0F5A1E46008C62A7 /* z80dasm.c in Sources */,
17F0D7DD0F5A1E46008C62A7 /* eng_ssf.c in Sources */,
17F0D7E10F5A1E46008C62A7 /* m68kcpu.c in Sources */,
17F0D7E50F5A1E46008C62A7 /* m68kopac.c in Sources */,
17F0D7E60F5A1E46008C62A7 /* m68kopdm.c in Sources */,
17F0D7E70F5A1E46008C62A7 /* m68kopnz.c in Sources */,
17F0D7E80F5A1E46008C62A7 /* m68kops.c in Sources */,
17F0D7EA0F5A1E46008C62A7 /* sat_hw.c in Sources */,
17F0D7EC0F5A1E46008C62A7 /* scsp.c in Sources */,
17F0D7EE0F5A1E46008C62A7 /* scspdsp.c in Sources */,
17F0D8240F5A1F1E008C62A7 /* spu.c in Sources */,
17F0D8340F5A1F80008C62A7 /* spu.c in Sources */,
17F0D8350F5A1F83008C62A7 /* dma.c in Sources */,
17F0D8360F5A1F86008C62A7 /* registers.c in Sources */,
17F0D8A60F5A24E9008C62A7 /* main.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
089C1666FE841158C02AAC07 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
089C1667FE841158C02AAC07 /* English */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
1DEB91AE08733DA50010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
COPY_PHASE_STRIP = NO;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
FRAMEWORK_VERSION = A;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
"GCC_PREPROCESSOR_DEFINITIONS[arch=i386]" = (
"HAS_PSXCPU=1",
"LSB_FIRST=1",
"PATH_MAX=1024",
);
"GCC_PREPROCESSOR_DEFINITIONS[arch=ppc]" = (
"HAS_PSXCPU=1",
"LSB_FIRST=0",
"PATH_MAX=1024",
);
HEADER_SEARCH_PATHS = aosdk;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "@loader_path/../Frameworks";
PRODUCT_NAME = AudioOverload;
SDKROOT = macosx10.6;
USE_HEADERMAP = NO;
WRAPPER_EXTENSION = framework;
};
name = Debug;
};
1DEB91AF08733DA50010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = (
i386,
ppc,
);
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
FRAMEWORK_VERSION = A;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_MODEL_TUNING = G5;
"GCC_PREPROCESSOR_DEFINITIONS[arch=i386]" = (
"HAS_PSXCPU=1",
"LSB_FIRST=1",
"PATH_MAX=1024",
);
"GCC_PREPROCESSOR_DEFINITIONS[arch=ppc]" = (
"HAS_PSXCPU=1",
"LSB_FIRST=0",
"PATH_MAX=1024",
);
HEADER_SEARCH_PATHS = aosdk;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "@loader_path/../Frameworks";
PRODUCT_NAME = AudioOverload;
SDKROOT = macosx10.6;
USE_HEADERMAP = NO;
WRAPPER_EXTENSION = framework;
};
name = Release;
};
1DEB91B208733DA50010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
ONLY_ACTIVE_ARCH = YES;
PREBINDING = NO;
SDKROOT = macosx10.6;
SYMROOT = ../../build;
};
name = Debug;
};
1DEB91B308733DA50010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
SDKROOT = macosx10.6;
SYMROOT = ../../build;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "AudioOverload" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB91AE08733DA50010E9CD /* Debug */,
1DEB91AF08733DA50010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "AudioOverload" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB91B208733DA50010E9CD /* Debug */,
1DEB91B308733DA50010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
}

View file

@ -1,97 +0,0 @@
#
# Makefile for Audio Overload SDK
#
# Copyright (c) 2007-2008, R. Belmont and Richard Bannister.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
# * Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# NOTE: this makefile will auto-detect Linux and MinGW and work appropriately. Other OSes will likely
# need some help.
CC = gcc
LD = gcc
CPP = g++
CFLAGS = -c -O3 -DPATH_MAX=1024 -DHAS_PSXCPU=1 -I. -I.. -Ieng_ssf -Ieng_qsf -Ieng_dsf -Izlib
# set for Linux 64-bit
# CFLAGS += -DLONG_IS_64BIT=1
# set for little-endian, make "0" for big-endian
CFLAGS += -DLSB_FIRST=1
LDFLAGS =
EXE = aosdk
LIBS = -lm -lz
# main objects
OBJS = corlett.o main_original.o
# port objects
#ifeq ($(OSTYPE),linux)
#OBJS += oss.o
#else
#OBJS += dsnd.o
#LIBS += -ldsound -ldxguid
#endif
OBJS += file.o
# DSF engine
OBJS += eng_dsf/eng_dsf.o eng_dsf/dc_hw.o eng_dsf/aica.o eng_dsf/aicadsp.o eng_dsf/arm7.o eng_dsf/arm7i.o
# SSF engine
OBJS += eng_ssf/m68kcpu.o eng_ssf/m68kopac.o eng_ssf/m68kopdm.o eng_ssf/m68kopnz.o eng_ssf/m68kops.o
OBJS += eng_ssf/scsp.o eng_ssf/scspdsp.o eng_ssf/sat_hw.o eng_ssf/eng_ssf.o
# QSF engine
OBJS += eng_qsf/eng_qsf.o eng_qsf/kabuki.o eng_qsf/qsound.o eng_qsf/z80.o eng_qsf/z80dasm.o
# PSF engine
OBJS += eng_psf/eng_psf.o eng_psf/psx.o eng_psf/psx_hw.o eng_psf/peops/spu.o
# PSF2 extentions
OBJS += eng_psf/eng_psf2.o eng_psf/peops2/spu.o eng_psf/peops2/dma.o eng_psf/peops2/registers.o
# SPU engine (requires PSF engine)
OBJS += eng_psf/eng_spu.o
# zlib (included for max portability)
#OBJS += zlib/adler32.o zlib/compress.o zlib/crc32.o zlib/gzio.o zlib/uncompr.o zlib/deflate.o zlib/trees.o
#OBJS += zlib/zutil.o zlib/inflate.o zlib/infback.o zlib/inftrees.o zlib/inffast.o
SRCS=$(OBJS:.o=.c)
%.o: %.c
@echo $(CC) $(CFLAGS) $< -o $@
@$(CC) $(CFLAGS) $< -o $@
%.o: %.cpp
@echo $(CPP) $(CFLAGS) $< -o $@
@$(CPP) $(CFLAGS) $< -o $@
all: $(EXE)
$(EXE): $(OBJS)
@echo $(LD) $(LDFLAGS) -g -o $(EXE) $(OBJS) $(LIBS)
@$(LD) $(LDFLAGS) -g -o $(EXE) $(OBJS) $(LIBS)
clean:
rm -f $(OBJS) $(EXE)

View file

@ -1,185 +0,0 @@
//
// Audio Overload SDK
//
// Fake ao.h to set up the general Audio Overload style environment
//
#ifndef __AO_H
#define __AO_H
#define AO_SUCCESS 1
#define AO_FAIL 0
#define AO_FAIL_DECOMPRESSION -1
#define MAX_DISP_INFO_LENGTH 256
#define AUDIO_RATE (44100)
enum
{
COMMAND_NONE = 0,
COMMAND_PREV,
COMMAND_NEXT,
COMMAND_RESTART,
COMMAND_HAS_PREV,
COMMAND_HAS_NEXT,
COMMAND_GET_MIN,
COMMAND_GET_MAX,
COMMAND_JUMP
};
/* Compiler defines for Xcode */
#ifdef __BIG_ENDIAN__
#undef LSB_FIRST
#endif
#ifdef __LITTLE_ENDIAN__
#define LSB_FIRST 1
#endif
typedef unsigned char ao_bool;
#ifdef __GNUC__
#include <stddef.h> // get NULL
#include <stdbool.h>
#ifndef nil
#define nil NULL
#endif
#ifndef TRUE
#define TRUE (1)
#endif
#ifndef FALSE
#define FALSE (0)
#endif
#define xmalloc(a) malloc(a)
#endif
#ifdef _MSC_VER
#include <stddef.h> // get NULL
#include <wchar.h> // for off_t
#ifndef nil
#define nil NULL
#endif
#ifndef TRUE
#define TRUE (1)
#endif
#ifndef FALSE
#define FALSE (0)
#endif
#define true (1)
#define false (0)
#define xmalloc(a) malloc(a)
#define strcasecmp _strcmpi
#endif
#ifndef PATH_MAX
#define PATH_MAX 2048
#endif
typedef struct
{
char title[9][MAX_DISP_INFO_LENGTH];
char info[9][MAX_DISP_INFO_LENGTH];
} ao_display_info;
typedef unsigned char uint8;
typedef unsigned char UINT8;
typedef signed char int8;
typedef signed char INT8;
typedef unsigned short uint16;
typedef unsigned short UINT16;
typedef signed short int16;
typedef signed short INT16;
typedef signed int int32;
typedef unsigned int uint32;
#ifdef LONG_IS_64BIT
typedef signed long int64;
typedef unsigned long uint64;
#else
typedef signed long long int64;
typedef unsigned long long uint64;
#endif
#ifdef WIN32
#ifndef _BASETSD_H
typedef signed int INT32;
typedef unsigned int UINT32;
typedef signed long long INT64;
typedef unsigned long long UINT64;
#endif
#else
typedef signed int INT32;
typedef unsigned int UINT32;
#ifdef LONG_IS_64BIT
typedef signed long INT64;
typedef unsigned long UINT64;
#else
typedef signed long long INT64;
typedef unsigned long long UINT64;
#endif
#endif
#ifndef INLINE
#if defined(_MSC_VER)
#define INLINE __forceinline
#elif defined(__GNUC__)
#define INLINE __inline__
#elif defined(_MWERKS_)
#define INLINE inline
#elif defined(__powerc)
#define INLINE inline
#else
#define INLINE
#endif
#endif
#if LSB_FIRST
#define LE16(x) (x)
#define LE32(x) (x)
#ifndef __ENDIAN__ /* Mac OS X Endian header has this function in it */
static unsigned long INLINE Endian32_Swap(unsigned long addr)
{
unsigned long res = (((addr&0xff000000)>>24) |
((addr&0x00ff0000)>>8) |
((addr&0x0000ff00)<<8) |
((addr&0x000000ff)<<24));
return res;
}
#endif
#else
static unsigned short INLINE LE16(unsigned short x)
{
unsigned short res = (((x & 0xFF00) >> 8) | ((x & 0xFF) << 8));
return res;
}
static unsigned long INLINE LE32(unsigned long addr)
{
unsigned long res = (((addr&0xff000000)>>24) |
((addr&0x00ff0000)>>8) |
((addr&0x0000ff00)<<8) |
((addr&0x000000ff)<<24));
return res;
}
#endif
int ao_get_lib(char *filename, uint8 **buffer, uint64 *length);
void ao_set_get_lib_callback(int (*callback)(char *, uint8 **, uint64 *));
#endif // AO_H

View file

@ -1,380 +0,0 @@
/*
Audio Overload SDK
Copyright (c) 2007-2008, R. Belmont and Richard Bannister.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// corlett.c
// Decodes file format designed by Neill Corlett (PSF, QSF, ...)
/*
- First 3 bytes: ASCII signature: "PSF" (case sensitive)
- Next 1 byte: Version byte
The version byte is used to determine the type of PSF file. It does NOT
affect the basic structure of the file in any way.
Currently accepted version bytes are:
0x01: Playstation (PSF1)
0x02: Playstation 2 (PSF2)
0x11: Saturn (SSF) [TENTATIVE]
0x12: Dreamcast (DSF) [TENTATIVE]
0x21: Nintendo 64 (USF) [RESERVED]
0x41: Capcom QSound (QSF)
- Next 4 bytes: Size of reserved area (R), little-endian unsigned long
- Next 4 bytes: Compressed program length (N), little-endian unsigned long
This is the length of the program data _after_ compression.
- Next 4 bytes: Compressed program CRC-32, little-endian unsigned long
This is the CRC-32 of the program data _after_ compression. Filling in
this value is mandatory, as a PSF file may be regarded as corrupt if it
does not match.
- Next R bytes: Reserved area.
May be empty if R is 0 bytes.
- Next N bytes: Compressed program, in zlib compress() format.
May be empty if N is 0 bytes.
The following data is optional and may be omitted:
- Next 5 bytes: ASCII signature: "[TAG]" (case sensitive)
If these 5 bytes do not match, then the remainder of the file may be
regarded as invalid and discarded.
- Remainder of file: Uncompressed ASCII tag data.
*/
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "ao.h"
#include "corlett.h"
#include <zlib.h>
#include <stdlib.h>
#define DECOMP_MAX_SIZE ((32 * 1024 * 1024) + 12)
int corlett_decode(uint8 *input, uint32 input_len, uint8 **output, uint64 *size, corlett_t **c)
{
uint32 *buf;
uint32 res_area, comp_crc, actual_crc;
uint8 *decomp_dat, *tag_dec;
uLongf decomp_length, comp_length;
// 32-bit pointer to data
buf = (uint32 *)input;
// Check we have a PSF format file.
if ((input[0] != 'P') || (input[1] != 'S') || (input[2] != 'F'))
{
return AO_FAIL;
}
// Get our values
res_area = LE32(buf[1]);
comp_length = LE32(buf[2]);
comp_crc = LE32(buf[3]);
if (comp_length > 0)
{
// Check length
if (input_len < comp_length + 16)
return AO_FAIL;
// Check CRC is correct
actual_crc = crc32(0, (unsigned char *)&buf[4+(res_area/4)], comp_length);
if (actual_crc != comp_crc)
return AO_FAIL;
// Decompress data if any
decomp_dat = malloc(DECOMP_MAX_SIZE);
if (NULL == decomp_dat) {
return AO_FAIL;
}
decomp_length = DECOMP_MAX_SIZE;
if (uncompress(decomp_dat, &decomp_length, (unsigned char *)&buf[4+(res_area/4)], comp_length) != Z_OK)
{
free(decomp_dat);
return AO_FAIL;
}
// Resize memory buffer to what we actually need
decomp_dat = realloc(decomp_dat, (size_t)decomp_length + 1);
}
else
{
decomp_dat = NULL;
decomp_length = 0;
}
// Make structure
*c = malloc(sizeof(corlett_t));
if (!(*c))
{
free(decomp_dat);
return AO_FAIL;
}
memset(*c, 0, sizeof(corlett_t));
strcpy((*c)->inf_title, "n/a");
strcpy((*c)->inf_copy, "n/a");
strcpy((*c)->inf_artist, "n/a");
strcpy((*c)->inf_game, "n/a");
strcpy((*c)->inf_year, "n/a");
strcpy((*c)->inf_length, "n/a");
strcpy((*c)->inf_fade, "n/a");
// set reserved section pointer
(*c)->res_section = &buf[4];
(*c)->res_size = res_area;
// Return it
*output = decomp_dat;
*size = decomp_length;
// Next check for tags
input_len -= (comp_length + 16 + res_area);
if (input_len < 5)
return AO_SUCCESS;
// printf("\n\nNew corlett: input len %d\n", input_len);
tag_dec = input + (comp_length + res_area + 16);
if ((tag_dec[0] == '[') && (tag_dec[1] == 'T') && (tag_dec[2] == 'A') && (tag_dec[3] == 'G') && (tag_dec[4] == ']'))
{
int tag, l, num_tags, data;
// Tags found!
tag_dec += 5;
input_len -= 5;
tag = 0;
data = false;
num_tags = 0;
l = 0;
while (input_len && (num_tags < MAX_UNKNOWN_TAGS))
{
if (data)
{
if ((*tag_dec == 0xA) || (*tag_dec == 0x00))
{
(*c)->tag_data[num_tags][l] = 0;
data = false;
num_tags++;
l = 0;
}
else
{
(*c)->tag_data[num_tags][l++] = *tag_dec;
}
}
else
{
if (*tag_dec == '=')
{
(*c)->tag_name[num_tags][l] = 0;
l = 0;
data = true;
}
else
{
(*c)->tag_name[num_tags][l++] = *tag_dec;
}
}
tag_dec++;
input_len--;
}
// Now, process that tag array into what we expect
for (num_tags = 0; num_tags < MAX_UNKNOWN_TAGS; num_tags++)
{
// See if tag belongs in one of the special fields we have
if (!strcasecmp((*c)->tag_name[num_tags], "_lib"))
{
strcpy((*c)->lib, (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
else if (!strncmp((*c)->tag_name[num_tags], "_lib2", 5))
{
strcpy((*c)->libaux[0], (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
else if (!strncmp((*c)->tag_name[num_tags], "_lib3", 5))
{
strcpy((*c)->libaux[1], (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
else if (!strncmp((*c)->tag_name[num_tags], "_lib4", 5))
{
strcpy((*c)->libaux[2], (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
else if (!strncmp((*c)->tag_name[num_tags], "_lib5", 5))
{
strcpy((*c)->libaux[3], (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
else if (!strncmp((*c)->tag_name[num_tags], "_lib6", 5))
{
strcpy((*c)->libaux[4], (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
else if (!strncmp((*c)->tag_name[num_tags], "_lib7", 5))
{
strcpy((*c)->libaux[5], (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
else if (!strncmp((*c)->tag_name[num_tags], "_lib8", 5))
{
strcpy((*c)->libaux[6], (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
else if (!strncmp((*c)->tag_name[num_tags], "_lib9", 5))
{
strcpy((*c)->libaux[7], (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
else if (!strncmp((*c)->tag_name[num_tags], "_refresh", 8))
{
strcpy((*c)->inf_refresh, (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
else if (!strncmp((*c)->tag_name[num_tags], "title", 5))
{
strcpy((*c)->inf_title, (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
else if (!strncmp((*c)->tag_name[num_tags], "copyright", 9))
{
strcpy((*c)->inf_copy, (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
else if (!strncmp((*c)->tag_name[num_tags], "artist", 6))
{
strcpy((*c)->inf_artist, (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
else if (!strncmp((*c)->tag_name[num_tags], "game", 4))
{
strcpy((*c)->inf_game, (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
else if (!strncmp((*c)->tag_name[num_tags], "year", 4))
{
strcpy((*c)->inf_year, (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
else if (!strncmp((*c)->tag_name[num_tags], "length", 6))
{
strcpy((*c)->inf_length, (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
else if (!strncmp((*c)->tag_name[num_tags], "fade", 4))
{
strcpy((*c)->inf_fade, (*c)->tag_data[num_tags]);
(*c)->tag_data[num_tags][0] = 0;
(*c)->tag_name[num_tags][0] = 0;
}
}
}
// Bingo
return AO_SUCCESS;
}
uint32 psfTimeToMS(char *str)
{
int x, c=0;
uint32 acc=0;
char s[100];
strncpy(s,str,100);
s[99]=0;
for (x=strlen(s); x>=0; x--)
{
if (s[x]=='.' || s[x]==',')
{
acc=atoi(s+x+1);
s[x]=0;
}
else if (s[x]==':')
{
if(c==0)
{
acc+=atoi(s+x+1)*10;
}
else if(c==1)
{
acc+=atoi(s+x+(x?1:0))*10*60;
}
c++;
s[x]=0;
}
else if (x==0)
{
if(c==0)
{
acc+=atoi(s+x)*10;
}
else if(c==1)
{
acc+=atoi(s+x)*10*60;
}
else if(c==2)
{
acc+=atoi(s+x)*10*60*60;
}
}
}
acc*=100;
return(acc);
}

View file

@ -1,35 +0,0 @@
//
// Audio Overload
// Emulated music player
//
// (C) 2000-2008 Richard F. Bannister
//
// corlett.h
#define MAX_UNKNOWN_TAGS 32
typedef struct {
char lib[256];
char libaux[8][256];
char inf_title[256];
char inf_copy[256];
char inf_artist[256];
char inf_game[256];
char inf_year[256];
char inf_length[256];
char inf_fade[256];
char inf_refresh[256];
char tag_name[MAX_UNKNOWN_TAGS][256];
char tag_data[MAX_UNKNOWN_TAGS][256];
uint32 *res_section;
uint32 res_size;
} corlett_t;
int corlett_decode(uint8 *input, uint32 input_len, uint8 **output, uint64 *size, corlett_t **c);
uint32 psfTimeToMS(char *str);

View file

@ -1,668 +0,0 @@
#ifndef CPUINTRF_H
#define CPUINTRF_H
#include "osd_cpu.h"
/* The old system is obsolete and no longer supported by the core */
#define NEW_INTERRUPT_SYSTEM 1
#define MAX_IRQ_LINES 8 /* maximum number of IRQ lines per CPU */
#define CLEAR_LINE 0 /* clear (a fired, held or pulsed) line */
#define ASSERT_LINE 1 /* assert an interrupt immediately */
#define HOLD_LINE 2 /* hold interrupt line until enable is true */
#define PULSE_LINE 3 /* pulse interrupt line for one instruction */
#define MAX_REGS 64 /* maximum number of register of any CPU */
#define IRQ_LINE_NMI 10
/* Values passed to the cpu_info function of a core to retrieve information */
enum {
CPU_INFO_REG,
CPU_INFO_FLAGS=MAX_REGS,
CPU_INFO_NAME,
CPU_INFO_FAMILY,
CPU_INFO_VERSION,
CPU_INFO_FILE,
CPU_INFO_CREDITS,
CPU_INFO_REG_LAYOUT,
CPU_INFO_WIN_LAYOUT
};
#define CPU_IS_LE 0 /* emulated CPU is little endian */
#define CPU_IS_BE 1 /* emulated CPU is big endian */
/*
* This value is passed to cpu_get_reg to retrieve the previous
* program counter value, ie. before a CPU emulation started
* to fetch opcodes and arguments for the current instrution.
*/
#define REG_PREVIOUSPC -1
/*
* This value is passed to cpu_get_reg/cpu_set_reg, instead of one of
* the names from the enum a CPU core defines for it's registers,
* to get or set the contents of the memory pointed to by a stack pointer.
* You can specify the n'th element on the stack by (REG_SP_CONTENTS-n),
* ie. lower negative values. The actual element size (UINT16 or UINT32)
* depends on the CPU core.
* This is also used to replace the cpu_geturnpc() function.
*/
#define REG_SP_CONTENTS -2
/*
* These flags can be defined in the makefile (or project) to
* exclude (zero) or include (non zero) specific CPU cores
*/
#ifndef HAS_GENSYNC
#define HAS_GENSYNC 0
#endif
#ifndef HAS_Z80
#define HAS_Z80 0
#endif
#ifndef HAS_Z80_VM
#define HAS_Z80_VM 0
#endif
#ifndef HAS_8080
#define HAS_8080 0
#endif
#ifndef HAS_8085A
#define HAS_8085A 0
#endif
#ifndef HAS_M6502
#define HAS_M6502 0
#endif
#ifndef HAS_M65C02
#define HAS_M65C02 0
#endif
#ifndef HAS_M65SC02
#define HAS_M65SC02 0
#endif
#ifndef HAS_M65CE02
#define HAS_M65CE02 0
#endif
#ifndef HAS_M6509
#define HAS_M6509 0
#endif
#ifndef HAS_M6510
#define HAS_M6510 0
#endif
#ifndef HAS_N2A03
#define HAS_N2A03 0
#endif
#ifndef HAS_H6280
#define HAS_H6280 0
#endif
#ifndef HAS_I86
#define HAS_I86 0
#endif
#ifndef HAS_V20
#define HAS_V20 0
#endif
#ifndef HAS_V30
#define HAS_V30 0
#endif
#ifndef HAS_V33
#define HAS_V33 0
#endif
#ifndef HAS_I8035
#define HAS_I8035 0
#endif
#ifndef HAS_I8039
#define HAS_I8039 0
#endif
#ifndef HAS_I8048
#define HAS_I8048 0
#endif
#ifndef HAS_N7751
#define HAS_N7751 0
#endif
#ifndef HAS_M6800
#define HAS_M6800 0
#endif
#ifndef HAS_M6801
#define HAS_M6801 0
#endif
#ifndef HAS_M6802
#define HAS_M6802 0
#endif
#ifndef HAS_M6803
#define HAS_M6803 0
#endif
#ifndef HAS_M6808
#define HAS_M6808 0
#endif
#ifndef HAS_HD63701
#define HAS_HD63701 0
#endif
#ifndef HAS_M6805
#define HAS_M6805 0
#endif
#ifndef HAS_M68705
#define HAS_M68705 0
#endif
#ifndef HAS_HD63705
#define HAS_HD63705 0
#endif
#ifndef HAS_HD6309
#define HAS_HD6309 0
#endif
#ifndef HAS_M6809
#define HAS_M6809 0
#endif
#ifndef HAS_KONAMI
#define HAS_KONAMI 0
#endif
#ifndef HAS_M68000
#define HAS_M68000 0
#endif
#ifndef HAS_M68010
#define HAS_M68010 0
#endif
#ifndef HAS_M68020
#define HAS_M68020 0
#endif
#ifndef HAS_T11
#define HAS_T11 0
#endif
#ifndef HAS_S2650
#define HAS_S2650 0
#endif
#ifndef HAS_TMS34010
#define HAS_TMS34010 0
#endif
#ifndef HAS_TMS9900
#define HAS_TMS9900 0
#endif
#ifndef HAS_TMS9940
#define HAS_TMS9940 0
#endif
#ifndef HAS_TMS9980
#define HAS_TMS9980 0
#endif
#ifndef HAS_TMS9985
#define HAS_TMS9985 0
#endif
#ifndef HAS_TMS9989
#define HAS_TMS9989 0
#endif
#ifndef HAS_TMS9995
#define HAS_TMS9995 0
#endif
#ifndef HAS_TMS99105A
#define HAS_TMS99105A 0
#endif
#ifndef HAS_TMS99110A
#define HAS_TMS99110A 0
#endif
#ifndef HAS_Z8000
#define HAS_Z8000 0
#endif
#ifndef HAS_TMS320C10
#define HAS_TMS320C10 0
#endif
#ifndef HAS_CCPU
#define HAS_CCPU 0
#endif
#ifndef HAS_PDP1
#define HAS_PDP1 0
#endif
#ifndef HAS_ADSP2100
#define HAS_ADSP2100 0
#endif
/* ASG 971222 -- added this generic structure */
struct cpu_interface
{
unsigned cpu_num;
void (*reset)(void *param);
void (*exit)(void);
int (*execute)(int cycles);
void (*burn)(int cycles);
unsigned (*get_context)(void *reg);
void (*set_context)(void *reg);
unsigned (*get_pc)(void);
void (*set_pc)(unsigned val);
unsigned (*get_sp)(void);
void (*set_sp)(unsigned val);
unsigned (*get_reg)(int regnum);
void (*set_reg)(int regnum, unsigned val);
void (*set_nmi_line)(int linestate);
void (*set_irq_line)(int irqline, int linestate);
void (*set_irq_callback)(int(*callback)(int irqline));
void (*internal_interrupt)(int type);
void (*cpu_state_save)(void *file);
void (*cpu_state_load)(void *file);
const char* (*cpu_info)(void *context,int regnum);
unsigned (*cpu_dasm)(char *buffer,unsigned pc);
unsigned num_irqs;
int default_vector;
int *icount;
double overclock;
int no_int, irq_int, nmi_int;
int (*memory_read)(int offset);
void (*memory_write)(int offset, int data);
void (*set_op_base)(int pc);
int address_shift;
unsigned address_bits, endianess, align_unit, max_inst_len;
unsigned abits1, abits2, abitsmin;
};
extern struct cpu_interface cpuintf[];
void cpu_init(void);
void cpu_run(void);
/* optional watchdog */
void watchdog_reset_w(int offset,int data);
int watchdog_reset_r(int offset);
/* Use this function to reset the machine */
void machine_reset(void);
/* Use this function to reset a single CPU */
void cpu_set_reset_line(int cpu,int state);
/* Use this function to halt a single CPU */
void cpu_set_halt_line(int cpu,int state);
/* This function returns CPUNUM current status (running or halted) */
int cpu_getstatus(int cpunum);
int cpu_gettotalcpu(void);
int cpu_getactivecpu(void);
void cpu_setactivecpu(int cpunum);
/* Returns the current program counter */
unsigned cpu_get_pc(void);
/* Set the current program counter */
void cpu_set_pc(unsigned val);
/* Returns the current stack pointer */
unsigned cpu_get_sp(void);
/* Set the current stack pointer */
void cpu_set_sp(unsigned val);
/* Get the active CPUs context and return it's size */
unsigned cpu_get_context(void *context);
/* Set the active CPUs context */
void cpu_set_context(void *context);
/* Returns a specific register value (mamedbg) */
unsigned cpu_get_reg(int regnum);
/* Sets a specific register value (mamedbg) */
void cpu_set_reg(int regnum, unsigned val);
/* Returns previous pc (start of opcode causing read/write) */
/* int cpu_getpreviouspc(void); */
#define cpu_getpreviouspc() cpu_get_reg(REG_PREVIOUSPC)
/* Returns the return address from the top of the stack (Z80 only) */
/* int cpu_getreturnpc(void); */
/* This can now be handled with a generic function */
#define cpu_geturnpc() cpu_get_reg(REG_SP_CONTENTS)
int cycles_currently_ran(void);
int cycles_left_to_run(void);
/* Returns the number of CPU cycles which take place in one video frame */
int cpu_gettotalcycles(void);
/* Returns the number of CPU cycles before the next interrupt handler call */
int cpu_geticount(void);
/* Returns the number of CPU cycles before the end of the current video frame */
int cpu_getfcount(void);
/* Returns the number of CPU cycles in one video frame */
int cpu_getfperiod(void);
/* Scales a given value by the ratio of fcount / fperiod */
int cpu_scalebyfcount(int value);
/* Returns the current scanline number */
int cpu_getscanline(void);
/* Returns the amount of time until a given scanline */
double cpu_getscanlinetime(int scanline);
/* Returns the duration of a single scanline */
double cpu_getscanlineperiod(void);
/* Returns the duration of a single scanline in cycles */
int cpu_getscanlinecycles(void);
/* Returns the number of cycles since the beginning of this frame */
int cpu_getcurrentcycles(void);
/* Returns the current horizontal beam position in pixels */
int cpu_gethorzbeampos(void);
/*
Returns the number of times the interrupt handler will be called before
the end of the current video frame. This is can be useful to interrupt
handlers to synchronize their operation. If you call this from outside
an interrupt handler, add 1 to the result, i.e. if it returns 0, it means
that the interrupt handler will be called once.
*/
int cpu_getiloops(void);
/* Returns the current VBLANK state */
int cpu_getvblank(void);
/* Returns the number of the video frame we are currently playing */
int cpu_getcurrentframe(void);
/* generate a trigger after a specific period of time */
void cpu_triggertime (double duration, int trigger);
/* generate a trigger now */
void cpu_trigger (int trigger);
/* burn CPU cycles until a timer trigger */
void cpu_spinuntil_trigger (int trigger);
/* burn CPU cycles until the next interrupt */
void cpu_spinuntil_int (void);
/* burn CPU cycles until our timeslice is up */
void cpu_spin (void);
/* burn CPU cycles for a specific period of time */
void cpu_spinuntil_time (double duration);
/* yield our timeslice for a specific period of time */
void cpu_yielduntil_trigger (int trigger);
/* yield our timeslice until the next interrupt */
void cpu_yielduntil_int (void);
/* yield our current timeslice */
void cpu_yield (void);
/* yield our timeslice for a specific period of time */
void cpu_yielduntil_time (double duration);
/* set the NMI line state for a CPU, normally use PULSE_LINE */
void cpu_set_nmi_line(int cpunum, int state);
/* set the IRQ line state for a specific irq line of a CPU */
/* normally use state HOLD_LINE, irqline 0 for first IRQ type of a cpu */
void cpu_set_irq_line(int cpunum, int irqline, int state);
/* this is to be called by CPU cores only! */
void cpu_generate_internal_interrupt(int cpunum, int type);
/* set the vector to be returned during a CPU's interrupt acknowledge cycle */
void cpu_irq_line_vector_w(int cpunum, int irqline, int vector);
/* use these in your write memory/port handles to set an IRQ vector */
/* offset corresponds to the irq line number here */
void cpu_0_irq_line_vector_w(int offset, int data);
void cpu_1_irq_line_vector_w(int offset, int data);
void cpu_2_irq_line_vector_w(int offset, int data);
void cpu_3_irq_line_vector_w(int offset, int data);
void cpu_4_irq_line_vector_w(int offset, int data);
void cpu_5_irq_line_vector_w(int offset, int data);
void cpu_6_irq_line_vector_w(int offset, int data);
void cpu_7_irq_line_vector_w(int offset, int data);
/* Obsolete functions: avoid to use them in new drivers if possible. */
/* cause an interrupt on a CPU */
void cpu_cause_interrupt(int cpu,int type);
void cpu_clear_pending_interrupts(int cpu);
void interrupt_enable_w(int offset,int data);
void interrupt_vector_w(int offset,int data);
int interrupt(void);
int nmi_interrupt(void);
int m68_level1_irq(void);
int m68_level2_irq(void);
int m68_level3_irq(void);
int m68_level4_irq(void);
int m68_level5_irq(void);
int m68_level6_irq(void);
int m68_level7_irq(void);
int ignore_interrupt(void);
/* CPU context access */
void* cpu_getcontext (int _activecpu);
int cpu_is_saving_context(int _activecpu);
/***************************************************************************
* Get information for the currently active CPU
* cputype is a value from the CPU enum in driver.h
***************************************************************************/
/* Return number of address bits */
unsigned cpu_address_bits(void);
/* Return address mask */
unsigned cpu_address_mask(void);
/* Return address shift factor (TMS34010 bit addressing mode) */
int cpu_address_shift(void);
/* Return endianess of the emulated CPU (CPU_IS_LE or CPU_IS_BE) */
unsigned cpu_endianess(void);
/* Return opcode align unit (1 byte, 2 word, 4 dword) */
unsigned cpu_align_unit(void);
/* Return maximum instruction length */
unsigned cpu_max_inst_len(void);
/* Return name of the active CPU */
const char *cpu_name(void);
/* Return family name of the active CPU */
const char *cpu_core_family(void);
/* Return core version of the active CPU */
const char *cpu_core_version(void);
/* Return core filename of the active CPU */
const char *cpu_core_file(void);
/* Return credits info for of the active CPU */
const char *cpu_core_credits(void);
/* Return register layout definition for the active CPU */
const char *cpu_reg_layout(void);
/* Return (debugger) window layout definition for the active CPU */
const char *cpu_win_layout(void);
/* Disassemble an instruction at PC into the given buffer */
unsigned cpu_dasm(char *buffer, unsigned pc);
/* Return a string describing the currently set flag (status) bits of the active CPU */
const char *cpu_flags(void);
/* Return a string with a register name and hex value for the active CPU */
/* regnum is a value defined in the CPU cores header files */
const char *cpu_dump_reg(int regnum);
/* Return a string describing the active CPUs current state */
const char *cpu_dump_state(void);
/***************************************************************************
* Get information for a specific CPU type
* cputype is a value from the CPU enum in driver.h
***************************************************************************/
/* Return address shift factor */
/* TMS320C10 -1: word addressing mode, TMS34010 3: bit addressing mode */
int cputype_address_shift(int cputype);
/* Return number of address bits */
unsigned cputype_address_bits(int cputype);
/* Return address mask */
unsigned cputype_address_mask(int cputype);
/* Return endianess of the emulated CPU (CPU_IS_LE or CPU_IS_BE) */
unsigned cputype_endianess(int cputype);
/* Return opcode align unit (1 byte, 2 word, 4 dword) */
unsigned cputype_align_unit(int cputype);
/* Return maximum instruction length */
unsigned cputype_max_inst_len(int cputype);
/* Return name of the CPU */
const char *cputype_name(int cputype);
/* Return family name of the CPU */
const char *cputype_core_family(int cputype);
/* Return core version number of the CPU */
const char *cputype_core_version(int cputype);
/* Return core filename of the CPU */
const char *cputype_core_file(int cputype);
/* Return credits for the CPU core */
const char *cputype_core_credits(int cputype);
/* Return register layout definition for the CPU core */
const char *cputype_reg_layout(int cputype);
/* Return (debugger) window layout definition for the CPU core */
const char *cputype_win_layout(int cputype);
/***************************************************************************
* Get (or set) information for a numbered CPU of the running machine
* cpunum is a value between 0 and cpu_gettotalcpu() - 1
***************************************************************************/
/* Return number of address bits */
unsigned cpunum_address_bits(int cputype);
/* Return address mask */
unsigned cpunum_address_mask(int cputype);
/* Return endianess of the emulated CPU (CPU_LSB_FIRST or CPU_MSB_FIRST) */
unsigned cpunum_endianess(int cputype);
/* Return opcode align unit (1 byte, 2 word, 4 dword) */
unsigned cpunum_align_unit(int cputype);
/* Return maximum instruction length */
unsigned cpunum_max_inst_len(int cputype);
/* Get a register value for the specified CPU number of the running machine */
unsigned cpunum_get_reg(int cpunum, int regnum);
/* Set a register value for the specified CPU number of the running machine */
void cpunum_set_reg(int cpunum, int regnum, unsigned val);
/* Return (debugger) register layout definition for the CPU core */
const char *cpunum_reg_layout(int cpunum);
/* Return (debugger) window layout definition for the CPU core */
const char *cpunum_win_layout(int cpunum);
unsigned cpunum_dasm(int cpunum,char *buffer,unsigned pc);
/* Return a string describing the currently set flag (status) bits of the CPU */
const char *cpunum_flags(int cpunum);
/* Return a string with a register name and value */
/* regnum is a value defined in the CPU cores header files */
const char *cpunum_dump_reg(int cpunum, int regnum);
/* Return a string describing the CPUs current state */
const char *cpunum_dump_state(int cpunum);
/* Return a name for the specified cpu number */
const char *cpunum_name(int cpunum);
/* Return a family name for the specified cpu number */
const char *cpunum_core_family(int cpunum);
/* Return a version for the specified cpu number */
const char *cpunum_core_version(int cpunum);
/* Return a the source filename for the specified cpu number */
const char *cpunum_core_file(int cpunum);
/* Return a the credits for the specified cpu number */
const char *cpunum_core_credits(int cpunum);
/* Dump all of the running machines CPUs state to stderr */
void cpu_dump_states(void);
/* daisy-chain link */
typedef struct {
void (*reset)(int); /* reset callback */
int (*interrupt_entry)(int); /* entry callback */
void (*interrupt_reti)(int); /* reti callback */
int irq_param; /* callback paramater */
} Z80_DaisyChain;
#define Z80_MAXDAISY 4 /* maximum of daisy chan device */
#define Z80_INT_REQ 0x01 /* interrupt request mask */
#define Z80_INT_IEO 0x02 /* interrupt disable mask(IEO) */
#define Z80_VECTOR(device,state) (((device)<<8)|(state))
#ifndef INLINE
#define INLINE inline
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define cpu_readmem16 memory_read
#define cpu_readport16 memory_readport
#define cpu_writeport16 memory_writeport
#define cpu_writemem16 memory_write
#define cpu_readop memory_readop
#define cpu_readop_arg memory_read
#define logerror(x, ...)
#define change_pc16(x)
#define CALL_MAME_DEBUG
#define ADDRESS_SPACES 3 /* maximum number of address spaces */
#define ADDRESS_SPACE_PROGRAM 0 /* program address space */
#define ADDRESS_SPACE_DATA 1 /* data address space */
#define ADDRESS_SPACE_IO 2 /* I/O address space */
enum
{
/* internal flags (not for use by drivers!) */
INTERNAL_CLEAR_LINE = 100 + CLEAR_LINE,
INTERNAL_ASSERT_LINE = 100 + ASSERT_LINE,
/* input lines */
MAX_INPUT_LINES = 32+3,
INPUT_LINE_IRQ0 = 0,
INPUT_LINE_IRQ1 = 1,
INPUT_LINE_IRQ2 = 2,
INPUT_LINE_IRQ3 = 3,
INPUT_LINE_IRQ4 = 4,
INPUT_LINE_IRQ5 = 5,
INPUT_LINE_IRQ6 = 6,
INPUT_LINE_IRQ7 = 7,
INPUT_LINE_IRQ8 = 8,
INPUT_LINE_IRQ9 = 9,
INPUT_LINE_NMI = MAX_INPUT_LINES - 3,
/* special input lines that are implemented in the core */
INPUT_LINE_RESET = MAX_INPUT_LINES - 2,
INPUT_LINE_HALT = MAX_INPUT_LINES - 1,
/* output lines */
MAX_OUTPUT_LINES = 32
};
enum
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
CPUINFO_INT_FIRST = 0x00000,
CPUINFO_INT_CONTEXT_SIZE = CPUINFO_INT_FIRST, /* R/O: size of CPU context in bytes */
CPUINFO_INT_INPUT_LINES, /* R/O: number of input lines */
CPUINFO_INT_OUTPUT_LINES, /* R/O: number of output lines */
CPUINFO_INT_DEFAULT_IRQ_VECTOR, /* R/O: default IRQ vector */
CPUINFO_INT_ENDIANNESS, /* R/O: either CPU_IS_BE or CPU_IS_LE */
CPUINFO_INT_CLOCK_DIVIDER, /* R/O: internal clock divider */
CPUINFO_INT_MIN_INSTRUCTION_BYTES, /* R/O: minimum bytes per instruction */
CPUINFO_INT_MAX_INSTRUCTION_BYTES, /* R/O: maximum bytes per instruction */
CPUINFO_INT_MIN_CYCLES, /* R/O: minimum cycles for a single instruction */
CPUINFO_INT_MAX_CYCLES, /* R/O: maximum cycles for a single instruction */
CPUINFO_INT_DATABUS_WIDTH, /* R/O: data bus size for each address space (8,16,32,64) */
CPUINFO_INT_DATABUS_WIDTH_LAST = CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACES - 1,
CPUINFO_INT_ADDRBUS_WIDTH, /* R/O: address bus size for each address space (12-32) */
CPUINFO_INT_ADDRBUS_WIDTH_LAST = CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACES - 1,
CPUINFO_INT_ADDRBUS_SHIFT, /* R/O: shift applied to addresses each address space (+3 means >>3, -1 means <<1) */
CPUINFO_INT_ADDRBUS_SHIFT_LAST = CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACES - 1,
CPUINFO_INT_SP, /* R/W: the current stack pointer value */
CPUINFO_INT_PC, /* R/W: the current PC value */
CPUINFO_INT_PREVIOUSPC, /* R/W: the previous PC value */
CPUINFO_INT_INPUT_STATE, /* R/W: states for each input line */
CPUINFO_INT_INPUT_STATE_LAST = CPUINFO_INT_INPUT_STATE + MAX_INPUT_LINES - 1,
CPUINFO_INT_OUTPUT_STATE, /* R/W: states for each output line */
CPUINFO_INT_OUTPUT_STATE_LAST = CPUINFO_INT_OUTPUT_STATE + MAX_OUTPUT_LINES - 1,
CPUINFO_INT_REGISTER, /* R/W: values of up to MAX_REGs registers */
CPUINFO_INT_REGISTER_LAST = CPUINFO_INT_REGISTER + MAX_REGS - 1,
CPUINFO_INT_CPU_SPECIFIC = 0x08000, /* R/W: CPU-specific values start here */
/* --- the following bits of info are returned as pointers to data or functions --- */
CPUINFO_PTR_FIRST = 0x10000,
CPUINFO_PTR_SET_INFO = CPUINFO_PTR_FIRST, /* R/O: void (*set_info)(UINT32 state, INT64 data, void *ptr) */
CPUINFO_PTR_GET_CONTEXT, /* R/O: void (*get_context)(void *buffer) */
CPUINFO_PTR_SET_CONTEXT, /* R/O: void (*set_context)(void *buffer) */
CPUINFO_PTR_INIT, /* R/O: void (*init)(void) */
CPUINFO_PTR_RESET, /* R/O: void (*reset)(void *param) */
CPUINFO_PTR_EXIT, /* R/O: void (*exit)(void) */
CPUINFO_PTR_EXECUTE, /* R/O: int (*execute)(int cycles) */
CPUINFO_PTR_BURN, /* R/O: void (*burn)(int cycles) */
CPUINFO_PTR_DISASSEMBLE, /* R/O: void (*disassemble)(char *buffer, offs_t pc) */
CPUINFO_PTR_IRQ_CALLBACK, /* R/W: int (*irqcallback)(int state) */
CPUINFO_PTR_INSTRUCTION_COUNTER, /* R/O: int *icount */
CPUINFO_PTR_REGISTER_LAYOUT, /* R/O: struct debug_register_layout *layout */
CPUINFO_PTR_WINDOW_LAYOUT, /* R/O: struct debug_window_layout *layout */
CPUINFO_PTR_INTERNAL_MEMORY_MAP, /* R/O: construct_map_t map */
CPUINFO_PTR_INTERNAL_MEMORY_MAP_LAST = CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACES - 1,
CPUINFO_PTR_DEBUG_REGISTER_LIST, /* R/O: int *list: list of registers for NEW_DEBUGGER */
CPUINFO_PTR_CPU_SPECIFIC = 0x18000, /* R/W: CPU-specific values start here */
/* --- the following bits of info are returned as NULL-terminated strings --- */
CPUINFO_STR_FIRST = 0x20000,
CPUINFO_STR_NAME = CPUINFO_STR_FIRST, /* R/O: name of the CPU */
CPUINFO_STR_CORE_FAMILY, /* R/O: family of the CPU */
CPUINFO_STR_CORE_VERSION, /* R/O: version of the CPU core */
CPUINFO_STR_CORE_FILE, /* R/O: file containing the CPU core */
CPUINFO_STR_CORE_CREDITS, /* R/O: credits for the CPU core */
CPUINFO_STR_FLAGS, /* R/O: string representation of the main flags value */
CPUINFO_STR_REGISTER, /* R/O: string representation of up to MAX_REGs registers */
CPUINFO_STR_REGISTER_LAST = CPUINFO_STR_REGISTER + MAX_REGS - 1,
CPUINFO_STR_CPU_SPECIFIC = 0x28000 /* R/W: CPU-specific values start here */
};
#endif /* CPUINTRF_H */

View file

@ -1,365 +0,0 @@
/*
Audio Overload SDK
Copyright (c) 2007, R. Belmont and Richard Bannister.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <windows.h>
#include <dsound.h>
#include "cpuintrf.h"
#include "oss.h"
#include "ao.h"
static INT16 samples[44100*4]; // make sure we reserve enough for worst-case scenario
void (*m1sdr_Callback)(unsigned long dwSamples, short *samples);
unsigned long cbUserData;
static int hw_present, playtime;
LPDIRECTSOUND lpDS; // DirectSound COM object
LPDIRECTSOUNDBUFFER lpPDSB; // Primary DirectSound buffer
LPDIRECTSOUNDBUFFER lpSecB; // Secondary DirectSound buffer
int nDSoundSamRate=44100; // sample rate
int nDSoundSegCount=16; // Segs in the pdsbLoop buffer
static int cbLoopLen=0; // Loop length (in bytes) calculated
int nDSoundFps=600; // Application fps * 10
int nDSoundSegLen=0; // Seg length in samples (calculated from Rate/Fps)
short *DSoundNextSound=NULL; // The next sound seg we will add to the sample loop
unsigned char bDSoundOkay=0; // True if DSound was initted okay
unsigned char bDSoundPlaying=0; // True if the Loop buffer is playing
#define WRAP_INC(x) { x++; if (x>=nDSoundSegCount) x=0; }
static int nDSoundNextSeg=0; // We have filled the sound in the loop up to the beginning of 'nNextSeg'
void m1sdr_SetSamplesPerTick(UINT32 spf)
{
if (spf != (nDSoundFps/10))
{
m1sdr_Exit();
nDSoundFps = spf * 10;
m1sdr_Init(nDSoundSamRate);
}
}
void m1sdr_TimeCheck(void)
{
int nPlaySeg=0, nFollowingSeg=0;
DWORD nPlay=0, nWrite=0;
int nRet=0;
if (!lpDS) return;
// We should do nothing until nPlay has left nDSoundNextSeg
IDirectSoundBuffer_GetCurrentPosition(lpSecB, &nPlay, &nWrite);
nPlaySeg=nPlay/(nDSoundSegLen<<2);
if (nPlaySeg>nDSoundSegCount-1) nPlaySeg=nDSoundSegCount-1;
if (nPlaySeg<0) nPlaySeg=0; // important to ensure nPlaySeg clipped for below
if (nDSoundNextSeg == nPlaySeg)
{
Sleep(200); // Don't need to do anything for a bit
goto End;
}
// work out which seg we will fill next
nFollowingSeg = nDSoundNextSeg;
WRAP_INC(nFollowingSeg)
while (nDSoundNextSeg != nPlaySeg)
{
void *pData=NULL,*pData2=NULL; DWORD cbLen=0,cbLen2=0;
// fill nNextSeg
// Lock the relevant seg of the loop buffer
nRet = IDirectSoundBuffer_Lock(lpSecB, nDSoundNextSeg*(nDSoundSegLen<<2), nDSoundSegLen<<2, &pData, &cbLen, &pData2, &cbLen2, 0);
if (nRet>=0 && pData!=NULL)
{
// Locked the seg okay - write the sound we calculated last time
memcpy(pData, samples, nDSoundSegLen<<2);
}
// Unlock (2nd 0 is because we wrote nothing to second part)
if (nRet>=0) IDirectSoundBuffer_Unlock(lpSecB, pData, cbLen, pData2, 0);
// generate more samples
if (m1sdr_Callback)
{
m1sdr_Callback(nDSoundSegLen, samples);
playtime++;
}
else
{
memset(samples, 0, nDSoundSegLen*4);
}
nDSoundNextSeg = nFollowingSeg;
WRAP_INC(nFollowingSeg)
}
End:
return;
}
INT16 m1sdr_Init(int sample_rate)
{
DSBUFFERDESC dsbuf;
WAVEFORMATEX format;
nDSoundSamRate = sample_rate;
lpDS = NULL;
lpPDSB = NULL;
lpSecB = NULL;
// Calculate the Seg Length and Loop length
// (round to nearest sample)
nDSoundSegLen=(nDSoundSamRate*10+(nDSoundFps>>1))/nDSoundFps;
cbLoopLen=(nDSoundSegLen*nDSoundSegCount)<<2;
// create an IDirectSound COM object
if (DS_OK != DirectSoundCreate(NULL, &lpDS, NULL))
{
printf("Unable to create DirectSound object!\n");
return(0);
}
// set cooperative level where we need it
if (DS_OK != IDirectSound_SetCooperativeLevel(lpDS, GetForegroundWindow(), DSSCL_PRIORITY))
{
printf("Unable to set cooperative level!\n");
return(0);
}
// now create a primary sound buffer
memset(&format, 0, sizeof(format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = 2;
format.wBitsPerSample = 16;
format.nSamplesPerSec = nDSoundSamRate;
format.nBlockAlign = 4; // stereo 16-bit
format.cbSize = 0;
format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
memset(&dsbuf, 0, sizeof(dsbuf));
dsbuf.dwSize = sizeof(DSBUFFERDESC);
dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER;
dsbuf.dwBufferBytes = 0;
dsbuf.lpwfxFormat = NULL;
if (DS_OK != IDirectSound_CreateSoundBuffer(lpDS, &dsbuf, &lpPDSB, NULL))
{
printf("Unable to create primary buffer!");
return(0);
}
// and set it's format how we want
if (DS_OK != IDirectSoundBuffer_SetFormat(lpPDSB, &format))
{
printf("Unable to set primary buffer format!\n");
return(0);
}
// start the primary buffer playing now so we get
// minimal lag when we trigger our secondary buffer
IDirectSoundBuffer_Play(lpPDSB, 0, 0, DSBPLAY_LOOPING);
// that's done, now let's create our secondary buffer
memset(&dsbuf, 0, sizeof(DSBUFFERDESC));
dsbuf.dwSize = sizeof(DSBUFFERDESC);
// we'll take default controls for this one
dsbuf.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;
dsbuf.dwBufferBytes = cbLoopLen;
dsbuf.lpwfxFormat = (LPWAVEFORMATEX)&format;
if (DS_OK != IDirectSound_CreateSoundBuffer(lpDS, &dsbuf, &lpSecB, NULL))
{
printf("Unable to create secondary buffer\n");
return(0);
}
// ok, cool, we're ready to go!
// blank out the entire sound buffer
{
LPVOID ptr; DWORD len;
IDirectSoundBuffer_Lock(lpSecB, 0, 0, &ptr, &len, NULL, NULL, DSBLOCK_ENTIREBUFFER);
ZeroMemory(ptr, len);
IDirectSoundBuffer_Unlock(lpSecB, ptr, len, 0, 0);
}
ZeroMemory(samples, nDSoundSegLen<<2);
bDSoundOkay=1; // This module was initted okay
return(1);
}
void m1sdr_Exit(void)
{
if (lpSecB)
{
IDirectSoundBuffer_Stop(lpSecB);
IDirectSoundBuffer_Release(lpSecB);
lpSecB = NULL;
}
if (lpPDSB)
{
IDirectSoundBuffer_Stop(lpPDSB);
IDirectSoundBuffer_Release(lpPDSB);
lpPDSB = NULL;
}
if (lpDS)
{
IDirectSound_Release(lpDS);
lpDS = NULL;
}
}
void m1sdr_PlayStart(void)
{
IDirectSound_SetCooperativeLevel(lpDS, GetForegroundWindow(), DSSCL_PRIORITY);
IDirectSoundBuffer_SetCurrentPosition(lpSecB, 0);
IDirectSoundBuffer_Play(lpSecB, 0, 0, DSBPLAY_LOOPING);
playtime = 0;
}
void m1sdr_PlayStop(void)
{
DSBUFFERDESC dsbuf;
WAVEFORMATEX format;
IDirectSoundBuffer_Stop(lpSecB);
// this is a bit cheezity-hacky
IDirectSoundBuffer_Release(lpSecB);
memset(&format, 0, sizeof(format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = 2;
format.wBitsPerSample = 16;
format.nSamplesPerSec = nDSoundSamRate;
format.nBlockAlign = 4; // stereo 16-bit
format.cbSize = 0;
format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
memset(&dsbuf, 0, sizeof(DSBUFFERDESC));
dsbuf.dwSize = sizeof(DSBUFFERDESC);
// we'll take default controls for this one
dsbuf.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;
dsbuf.dwBufferBytes = cbLoopLen;
dsbuf.lpwfxFormat = (LPWAVEFORMATEX)&format;
if (DS_OK != IDirectSound_CreateSoundBuffer(lpDS, &dsbuf, &lpSecB, NULL))
{
printf("Unable to create secondary buffer\n");
return;
}
// zero out the buffer
{
LPVOID ptr; DWORD len;
IDirectSoundBuffer_Lock(lpSecB, 0, 0, &ptr, &len, NULL, NULL, DSBLOCK_ENTIREBUFFER);
ZeroMemory(ptr, len);
IDirectSoundBuffer_Unlock(lpSecB, ptr, len, 0, 0);
}
}
INT32 m1sdr_HwPresent(void)
{
return hw_present;
}
INT16 m1sdr_IsThere(void)
{
if(DS_OK == DirectSoundCreate(NULL, &lpDS, NULL))
{
IDirectSound_Release(lpDS);
hw_present = 1;
return(1);
}
else
{
hw_present = 0;
return(0);
}
}
void m1sdr_SetCallback(void *fn)
{
if (fn == (void *)NULL)
{
printf("ERROR: NULL CALLBACK!\n");
}
m1sdr_Callback = (void (*)(unsigned long, signed short *))fn;
}
void m1sdr_FlushAudio(void)
{
memset(samples, 0, nDSoundSegLen * 4);
m1sdr_TimeCheck();
m1sdr_TimeCheck();
m1sdr_TimeCheck();
m1sdr_TimeCheck();
m1sdr_TimeCheck();
}
short *m1sdr_GetSamples(void)
{
return samples;
}
int m1sdr_GetPlayTime(void)
{
int rv;
int fps = nDSoundFps / 10;
rv = playtime / fps;
return rv; // total seconds
}
int m1sdr_GetPlayTimeTicks(void)
{
return playtime;
}

File diff suppressed because it is too large Load diff

View file

@ -1,44 +0,0 @@
/*
Sega/Yamaha AICA emulation
*/
#ifndef _AICA_H_
#define _AICA_H_
#define MAX_AICA (2)
#define COMBINE_DATA(varptr) (*(varptr) = (*(varptr) & mem_mask) | (data & ~mem_mask))
// convert AO types
typedef int8 data8_t;
typedef int16 data16_t;
typedef int32 data32_t;
typedef int offs_t;
struct AICAinterface
{
int num;
void *region[MAX_AICA];
int mixing_level[MAX_AICA]; /* volume */
void (*irq_callback[MAX_AICA])(int state); /* irq callback */
};
int AICA_sh_start(struct AICAinterface *intf);
void AICA_sh_stop(void);
void scsp_stop(void);
#define READ16_HANDLER(name) data16_t name(offs_t offset, data16_t mem_mask)
#define WRITE16_HANDLER(name) void name(offs_t offset, data16_t data, data16_t mem_mask)
// AICA register access
READ16_HANDLER( AICA_0_r );
WRITE16_HANDLER( AICA_0_w );
READ16_HANDLER( AICA_1_r );
WRITE16_HANDLER( AICA_1_w );
// MIDI I/O access (used for comms on Model 2/3)
WRITE16_HANDLER( AICA_MidiIn );
READ16_HANDLER( AICA_MidiOutR );
#endif

View file

@ -1,349 +0,0 @@
#include <assert.h>
#include <math.h>
#include "ao.h"
#include "cpuintrf.h"
#include "aica.h"
#include "aicadsp.h"
static UINT16 PACK(INT32 val)
{
UINT32 temp;
int sign,exponent,k;
sign = (val >> 23) & 0x1;
temp = (val ^ (val << 1)) & 0xFFFFFF;
exponent = 0;
for (k=0; k<12; k++)
{
if (temp & 0x800000)
break;
temp <<= 1;
exponent += 1;
}
if (exponent < 12)
val = (val << exponent) & 0x3FFFFF;
else
val <<= 11;
val >>= 11;
val |= sign << 15;
val |= exponent << 11;
return (UINT16)val;
}
static INT32 UNPACK(UINT16 val)
{
int sign,exponent,mantissa;
INT32 uval;
sign = (val >> 15) & 0x1;
exponent = (val >> 11) & 0xF;
mantissa = val & 0x7FF;
uval = mantissa << 11;
if (exponent > 11)
exponent = 11;
else
uval |= (sign ^ 1) << 22;
uval |= sign << 23;
uval <<= 8;
uval >>= 8;
uval >>= exponent;
return uval;
}
void AICADSP_Init(struct _AICADSP *DSP)
{
memset(DSP,0,sizeof(struct _AICADSP));
DSP->RBL=0x8000;
DSP->Stopped=1;
}
void AICADSP_Step(struct _AICADSP *DSP)
{
INT32 ACC=0; //26 bit
INT32 SHIFTED=0; //24 bit
INT32 X=0; //24 bit
INT32 Y=0; //13 bit
INT32 B=0; //26 bit
INT32 INPUTS=0; //24 bit
INT32 MEMVAL=0;
INT32 FRC_REG=0; //13 bit
INT32 Y_REG=0; //24 bit
UINT32 ADDR=0;
UINT32 ADRS_REG=0; //13 bit
int step;
if(DSP->Stopped)
return;
memset(DSP->EFREG,0,2*16);
#if 0
int dump=0;
FILE *f=NULL;
if(dump)
f=fopen("dsp.txt","wt");
#endif
for(step=0;step</*128*/DSP->LastStep;++step)
{
UINT16 *IPtr=DSP->MPRO+step*8;
// if(IPtr[0]==0 && IPtr[1]==0 && IPtr[2]==0 && IPtr[3]==0)
// break;
UINT32 TRA=(IPtr[0]>>9)&0x7F;
UINT32 TWT=(IPtr[0]>>8)&0x01;
UINT32 TWA=(IPtr[0]>>1)&0x7F;
UINT32 XSEL=(IPtr[2]>>15)&0x01;
UINT32 YSEL=(IPtr[2]>>13)&0x03;
UINT32 IRA=(IPtr[2]>>7)&0x3F;
UINT32 IWT=(IPtr[2]>>6)&0x01;
UINT32 IWA=(IPtr[2]>>1)&0x1F;
UINT32 TABLE=(IPtr[4]>>15)&0x01;
UINT32 MWT=(IPtr[4]>>14)&0x01;
UINT32 MRD=(IPtr[4]>>13)&0x01;
UINT32 EWT=(IPtr[4]>>12)&0x01;
UINT32 EWA=(IPtr[4]>>8)&0x0F;
UINT32 ADRL=(IPtr[4]>>7)&0x01;
UINT32 FRCL=(IPtr[4]>>6)&0x01;
UINT32 SHIFT=(IPtr[4]>>4)&0x03;
UINT32 YRL=(IPtr[4]>>3)&0x01;
UINT32 NEGB=(IPtr[4]>>2)&0x01;
UINT32 ZERO=(IPtr[4]>>1)&0x01;
UINT32 BSEL=(IPtr[4]>>0)&0x01;
UINT32 NOFL=(IPtr[6]>>15)&1; //????
UINT32 COEF=step;
UINT32 MASA=(IPtr[6]>>9)&0x3f; //???
UINT32 ADREB=(IPtr[6]>>8)&0x1;
UINT32 NXADR=(IPtr[6]>>7)&0x1;
INT64 v;
//operations are done at 24 bit precision
#if 0
if(MASA)
int a=1;
if(NOFL)
int a=1;
// int dump=0;
if(f)
{
#define DUMP(v) fprintf(f," " #v ": %04X",v);
fprintf(f,"%d: ",step);
DUMP(ACC);
DUMP(SHIFTED);
DUMP(X);
DUMP(Y);
DUMP(B);
DUMP(INPUTS);
DUMP(MEMVAL);
DUMP(FRC_REG);
DUMP(Y_REG);
DUMP(ADDR);
DUMP(ADRS_REG);
fprintf(f,"\n");
}
#endif
//INPUTS RW
assert(IRA<0x32);
if(IRA<=0x1f)
INPUTS=DSP->MEMS[IRA];
else if(IRA<=0x2F)
INPUTS=DSP->MIXS[IRA-0x20]<<4; //MIXS is 20 bit
else if(IRA<=0x31)
INPUTS=0;
INPUTS<<=8;
INPUTS>>=8;
//if(INPUTS&0x00800000)
// INPUTS|=0xFF000000;
if(IWT)
{
DSP->MEMS[IWA]=MEMVAL; //MEMVAL was selected in previous MRD
if(IRA==IWA)
INPUTS=MEMVAL;
}
//Operand sel
//B
if(!ZERO)
{
if(BSEL)
B=ACC;
else
{
B=DSP->TEMP[(TRA+DSP->DEC)&0x7F];
B<<=8;
B>>=8;
//if(B&0x00800000)
// B|=0xFF000000; //Sign extend
}
if(NEGB)
B=0-B;
}
else
B=0;
//X
if(XSEL)
X=INPUTS;
else
{
X=DSP->TEMP[(TRA+DSP->DEC)&0x7F];
X<<=8;
X>>=8;
//if(X&0x00800000)
// X|=0xFF000000;
}
//Y
if(YSEL==0)
Y=FRC_REG;
else if(YSEL==1)
Y=DSP->COEF[COEF<<1]>>3; //COEF is 16 bits
else if(YSEL==2)
Y=(Y_REG>>11)&0x1FFF;
else if(YSEL==3)
Y=(Y_REG>>4)&0x0FFF;
if(YRL)
Y_REG=INPUTS;
//Shifter
if(SHIFT==0)
{
SHIFTED=ACC;
if(SHIFTED>0x007FFFFF)
SHIFTED=0x007FFFFF;
if(SHIFTED<(-0x00800000))
SHIFTED=-0x00800000;
}
else if(SHIFT==1)
{
SHIFTED=ACC*2;
if(SHIFTED>0x007FFFFF)
SHIFTED=0x007FFFFF;
if(SHIFTED<(-0x00800000))
SHIFTED=-0x00800000;
}
else if(SHIFT==2)
{
SHIFTED=ACC*2;
SHIFTED<<=8;
SHIFTED>>=8;
//SHIFTED&=0x00FFFFFF;
//if(SHIFTED&0x00800000)
// SHIFTED|=0xFF000000;
}
else if(SHIFT==3)
{
SHIFTED=ACC;
SHIFTED<<=8;
SHIFTED>>=8;
//SHIFTED&=0x00FFFFFF;
//if(SHIFTED&0x00800000)
// SHIFTED|=0xFF000000;
}
//ACCUM
Y<<=19;
Y>>=19;
//if(Y&0x1000)
// Y|=0xFFFFF000;
v=(((INT64) X*(INT64) Y)>>12);
ACC=(int) v+B;
if(TWT)
DSP->TEMP[(TWA+DSP->DEC)&0x7F]=SHIFTED;
if(FRCL)
{
if(SHIFT==3)
FRC_REG=SHIFTED&0x0FFF;
else
FRC_REG=(SHIFTED>>11)&0x1FFF;
}
if(MRD || MWT)
//if(0)
{
ADDR=DSP->MADRS[MASA<<1];
if(!TABLE)
ADDR+=DSP->DEC;
if(ADREB)
ADDR+=ADRS_REG&0x0FFF;
if(NXADR)
ADDR++;
if(!TABLE)
ADDR&=DSP->RBL-1;
else
ADDR&=0xFFFF;
//ADDR<<=1;
//ADDR+=DSP->RBP<<13;
//MEMVAL=DSP->AICARAM[ADDR>>1];
ADDR+=DSP->RBP<<10;
if(MRD && (step&1)) //memory only allowed on odd? DoA inserts NOPs on even
{
if(NOFL)
MEMVAL=DSP->AICARAM[ADDR]<<8;
else
MEMVAL=UNPACK(DSP->AICARAM[ADDR]);
}
if(MWT && (step&1))
{
if(NOFL)
DSP->AICARAM[ADDR]=SHIFTED>>8;
else
DSP->AICARAM[ADDR]=PACK(SHIFTED);
}
}
if(ADRL)
{
if(SHIFT==3)
ADRS_REG=(SHIFTED>>12)&0xFFF;
else
ADRS_REG=(INPUTS>>16);
}
if(EWT)
DSP->EFREG[EWA]+=SHIFTED>>8;
}
--DSP->DEC;
memset(DSP->MIXS,0,4*16);
// if(f)
// fclose(f);
}
void AICADSP_SetSample(struct _AICADSP *DSP,INT32 sample,int SEL,int MXL)
{
//DSP->MIXS[SEL]+=sample<<(MXL+1)/*7*/;
DSP->MIXS[SEL]+=sample;
// if(MXL)
// int a=1;
}
void AICADSP_Start(struct _AICADSP *DSP)
{
int i;
DSP->Stopped=0;
for(i=127;i>=0;--i)
{
UINT16 *IPtr=DSP->MPRO+i*8;
if(IPtr[0]!=0 || IPtr[2]!=0 || IPtr[4]!=0 || IPtr[6]!=0)
break;
}
DSP->LastStep=i+1;
}

View file

@ -1,37 +0,0 @@
#ifndef AICADSP_H
#define AICADSP_H
//the DSP Context
struct _AICADSP
{
//Config
UINT16 *AICARAM;
UINT32 AICARAM_LENGTH;
UINT32 RBP; //Ring buf pointer
UINT32 RBL; //Delay ram (Ring buffer) size in words
//context
INT16 COEF[128*2]; //16 bit signed
UINT16 MADRS[64*2]; //offsets (in words), 16 bit
UINT16 MPRO[128*4*2*2]; //128 steps 64 bit
INT32 TEMP[128]; //TEMP regs,24 bit signed
INT32 MEMS[32]; //MEMS regs,24 bit signed
UINT32 DEC;
//input
INT32 MIXS[16]; //MIXS, 24 bit signed
INT16 EXTS[2]; //External inputs (CDDA) 16 bit signed
//output
INT16 EFREG[16]; //EFREG, 16 bit signed
int Stopped;
int LastStep;
};
void AICADSP_Init(struct _AICADSP *DSP);
void AICADSP_SetSample(struct _AICADSP *DSP, INT32 sample, INT32 SEL, INT32 MXL);
void AICADSP_Step(struct _AICADSP *DSP);
void AICADSP_Start(struct _AICADSP *DSP);
#endif

View file

@ -1,159 +0,0 @@
/*
AICA LFO handling
Part of the AICA emulator package.
(not compiled directly, #included from aica.c)
By ElSemi, kingshriek, and R. Belmont
*/
#define LFO_SHIFT 8
struct _LFO
{
unsigned short phase;
UINT32 phase_step;
int *table;
int *scale;
};
#define LFIX(v) ((unsigned int) ((float) (1<<LFO_SHIFT)*(v)))
//Convert DB to multiply amplitude
#define DB(v) LFIX(pow(10.0,v/20.0))
//Convert cents to step increment
#define CENTS(v) LFIX(pow(2.0,v/1200.0))
static int PLFO_TRI[256],PLFO_SQR[256],PLFO_SAW[256],PLFO_NOI[256];
static int ALFO_TRI[256],ALFO_SQR[256],ALFO_SAW[256],ALFO_NOI[256];
static float LFOFreq[32]={0.17,0.19,0.23,0.27,0.34,0.39,0.45,0.55,0.68,0.78,0.92,1.10,1.39,1.60,1.87,2.27,
2.87,3.31,3.92,4.79,6.15,7.18,8.60,10.8,14.4,17.2,21.5,28.7,43.1,57.4,86.1,172.3};
static float ASCALE[8]={0.0,0.4,0.8,1.5,3.0,6.0,12.0,24.0};
static float PSCALE[8]={0.0,7.0,13.5,27.0,55.0,112.0,230.0,494};
static int PSCALES[8][256];
static int ASCALES[8][256];
void AICALFO_Init(void)
{
int i,s;
for(i=0;i<256;++i)
{
int a,p;
// float TL;
//Saw
a=255-i;
if(i<128)
p=i;
else
p=i-256;
ALFO_SAW[i]=a;
PLFO_SAW[i]=p;
//Square
if(i<128)
{
a=255;
p=127;
}
else
{
a=0;
p=-128;
}
ALFO_SQR[i]=a;
PLFO_SQR[i]=p;
//Tri
if(i<128)
a=255-(i*2);
else
a=(i*2)-256;
if(i<64)
p=i*2;
else if(i<128)
p=255-i*2;
else if(i<192)
p=256-i*2;
else
p=i*2-511;
ALFO_TRI[i]=a;
PLFO_TRI[i]=p;
//noise
//a=lfo_noise[i];
a=rand()&0xff;
p=128-a;
ALFO_NOI[i]=a;
PLFO_NOI[i]=p;
}
for(s=0;s<8;++s)
{
float limit=PSCALE[s];
for(i=-128;i<128;++i)
{
PSCALES[s][i+128]=CENTS(((limit*(float) i)/128.0));
}
limit=-ASCALE[s];
for(i=0;i<256;++i)
{
ASCALES[s][i]=DB(((limit*(float) i)/256.0));
}
}
}
static signed int INLINE AICAPLFO_Step(struct _LFO *LFO)
{
int p;
LFO->phase+=LFO->phase_step;
#if LFO_SHIFT!=8
LFO->phase&=(1<<(LFO_SHIFT+8))-1;
#endif
p=LFO->table[LFO->phase>>LFO_SHIFT];
p=LFO->scale[p+128];
return p<<(SHIFT-LFO_SHIFT);
}
static signed int INLINE AICAALFO_Step(struct _LFO *LFO)
{
int p;
LFO->phase+=LFO->phase_step;
#if LFO_SHIFT!=8
LFO->phase&=(1<<(LFO_SHIFT+8))-1;
#endif
p=LFO->table[LFO->phase>>LFO_SHIFT];
p=LFO->scale[p];
return p<<(SHIFT-LFO_SHIFT);
}
void AICALFO_ComputeStep(struct _LFO *LFO,UINT32 LFOF,UINT32 LFOWS,UINT32 LFOS,int ALFO)
{
float step=(float) LFOFreq[LFOF]*256.0/(float)44100.0;
LFO->phase_step=(unsigned int) ((float) (1<<LFO_SHIFT)*step);
if(ALFO)
{
switch(LFOWS)
{
case 0: LFO->table=ALFO_SAW; break;
case 1: LFO->table=ALFO_SQR; break;
case 2: LFO->table=ALFO_TRI; break;
case 3: LFO->table=ALFO_NOI; break;
default: printf("Unknown ALFO %d\n", LFOWS);
}
LFO->scale=ASCALES[LFOS];
}
else
{
switch(LFOWS)
{
case 0: LFO->table=PLFO_SAW; break;
case 1: LFO->table=PLFO_SQR; break;
case 2: LFO->table=PLFO_TRI; break;
case 3: LFO->table=PLFO_NOI; break;
default: printf("Unknown PLFO %d\n", LFOWS);
}
LFO->scale=PSCALES[LFOS];
}
}

View file

@ -1,274 +0,0 @@
//
// ARM7 processor emulator
// version 1.6 / 2008-02-16
// (c) Radoslaw Balcewicz
//
#include "arm7.h"
#include "arm7i.h"
#ifdef ARM7_THUMB
#include "arm7thumb.h"
#endif
//--------------------------------------------------------------------------
// definitions and macros
/** Macro for accessing banked registers. */
#define RX_BANK(t,r) (ARM7.Rx_bank [t][r - 8])
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// private functions
/** CPU Reset. */
static void Reset (void);
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// public variables
/** ARM7 state. */
struct sARM7 ARM7;
// private variables
/** Table for decoding bit-coded mode to zero based index. */
static const int s_tabTryb [32] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, ARM7_MODE_usr, ARM7_MODE_fiq, ARM7_MODE_irq,
ARM7_MODE_svc, -1, -1, -1, ARM7_MODE_abt, -1, -1, -1, ARM7_MODE_und,
-1, -1, -1, ARM7_MODE_sys};
//--------------------------------------------------------------------------
// public functions
//--------------------------------------------------------------------------
/** ARM7 emulator init. */
void ARM7_Init ()
{
// sane startup values
ARM7.fiq = 0;
ARM7.irq = 0;
ARM7.carry = 0;
ARM7.overflow = 0;
ARM7.flagi = FALSE;
ARM7.cykle = 0;
// reset will do the rest
ARM7_HardReset ();
}
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
/** Power-ON reset. */
void ARM7_HardReset ()
{
// CPSR that makes sense
ARM7.Rx [ARM7_CPSR] = ARM7_CPSR_I | ARM7_CPSR_F | ARM7_CPSR_M_svc;
Reset ();
}
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
/** Hardware reset via /RESET line. */
void ARM7_SoftReset ()
{
Reset ();
}
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
/** CPSR update, possibly changing operating mode. */
void ARM7_SetCPSR (ARM7_REG sr)
{
int stary, nowy;
stary = s_tabTryb [ARM7_CPSR_M (ARM7.Rx [ARM7_CPSR])];
nowy = s_tabTryb [ARM7_CPSR_M (sr)];
// do we have to change modes?
if (nowy != stary)
{
// save this mode registers
RX_BANK (stary, ARM7_SP) = ARM7.Rx [ARM7_SP],
RX_BANK (stary, ARM7_LR) = ARM7.Rx [ARM7_LR],
RX_BANK (stary, ARM7_SPSR) = ARM7.Rx [ARM7_SPSR];
if (stary == ARM7_MODE_fiq)
{
// copy R8-R12
RX_BANK (ARM7_MODE_fiq, 8) = ARM7.Rx [8],
RX_BANK (ARM7_MODE_fiq, 9) = ARM7.Rx [9],
RX_BANK (ARM7_MODE_fiq, 10) = ARM7.Rx [10],
RX_BANK (ARM7_MODE_fiq, 11) = ARM7.Rx [11],
RX_BANK (ARM7_MODE_fiq, 12) = ARM7.Rx [12];
ARM7.Rx [8] = RX_BANK (ARM7_MODE_usr, 8),
ARM7.Rx [9] = RX_BANK (ARM7_MODE_usr, 9),
ARM7.Rx [10] = RX_BANK (ARM7_MODE_usr, 10),
ARM7.Rx [11] = RX_BANK (ARM7_MODE_usr, 11),
ARM7.Rx [12] = RX_BANK (ARM7_MODE_usr, 12);
}
// fetch new mode registers
ARM7.Rx [ARM7_SP] = RX_BANK (nowy, ARM7_SP),
ARM7.Rx [ARM7_LR] = RX_BANK (nowy, ARM7_LR),
ARM7.Rx [ARM7_SPSR] = RX_BANK (nowy, ARM7_SPSR);
if (nowy == ARM7_MODE_fiq)
{
// copy R8-R12
RX_BANK (ARM7_MODE_usr, 8) = ARM7.Rx [8],
RX_BANK (ARM7_MODE_usr, 9) = ARM7.Rx [9],
RX_BANK (ARM7_MODE_usr, 10) = ARM7.Rx [10],
RX_BANK (ARM7_MODE_usr, 11) = ARM7.Rx [11],
RX_BANK (ARM7_MODE_usr, 12) = ARM7.Rx [12];
ARM7.Rx [8] = RX_BANK (ARM7_MODE_fiq, 8),
ARM7.Rx [9] = RX_BANK (ARM7_MODE_fiq, 9),
ARM7.Rx [10] = RX_BANK (ARM7_MODE_fiq, 10),
ARM7.Rx [11] = RX_BANK (ARM7_MODE_fiq, 11),
ARM7.Rx [12] = RX_BANK (ARM7_MODE_fiq, 12);
}
}
// new CPSR value
ARM7.Rx [ARM7_CPSR] = sr;
// mode change could've enabled interrups, so we test for those and set
// appropriate flag for the instruction loop to catch
if (ARM7.fiq)
ARM7.flagi |= ARM7_FL_FIQ;
#ifndef ARM7_DREAMCAST
if (ARM7.irq)
ARM7.flagi |= ARM7_FL_IRQ;
#endif
}
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
/** Sets FIQ line state. */
void ARM7_SetFIQ (int stan)
{
stan = stan ? TRUE : FALSE;
// we catch changes only
if (stan ^ ARM7.fiq)
{
ARM7.fiq = stan;
if (ARM7.fiq)
ARM7.flagi |= ARM7_FL_FIQ;
}
}
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
/** Sets IRQ line state. */
void ARM7_SetIRQ (int stan)
{
stan = stan ? TRUE : FALSE;
// we catch changes only
if (stan ^ ARM7.irq)
{
ARM7.irq = stan;
if (ARM7.irq)
ARM7.flagi |= ARM7_FL_IRQ;
}
}
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
/** Tests for pending interrupts, switches to one if possible. */
void ARM7_CheckIRQ ()
{
UINT32 sr = ARM7.Rx [ARM7_CPSR];
// clear all interrupt flags
ARM7.flagi &= ~(ARM7_FL_FIQ | ARM7_FL_IRQ);
// check for pending interrupts we can switch to
// (FIQ can interrupt IRQ, but not the other way around)
if (ARM7.fiq)
{
if (!(sr & ARM7_CPSR_F))
{
// FIQ
ARM7_SetCPSR (ARM7_CPSR_MX (sr, ARM7_CPSR_M_fiq) | ARM7_CPSR_F | ARM7_CPSR_I);
ARM7.Rx [ARM7_SPSR] = sr;
// set new PC (return from interrupt will subtract 4)
ARM7.Rx [ARM7_LR] = ARM7.Rx [ARM7_PC] + 4;
ARM7.Rx [ARM7_PC] = 0x0000001c;
}
}
#ifndef ARM7_DREAMCAST
if (ARM7.irq)
{
if (!(sr & ARM7_CPSR_I))
{
// IRQ
ARM7_SetCPSR (ARM7_CPSR_MX (sr, ARM7_CPSR_M_irq) | ARM7_CPSR_I);
ARM7.Rx [ARM7_SPSR] = sr;
// set new PC (return from interrupt will subtract 4)
ARM7.Rx [ARM7_LR] = ARM7.Rx [ARM7_PC] + 4;
ARM7.Rx [ARM7_PC] = 0x00000018;
ARM7.irq = 0;
}
}
#endif
}
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
/** Single step. */
void ARM7_Step ()
{
// make a step
#ifdef ARM7_THUMB
if (ARM7.Rx[ARM7_CPSR] & ARM7_CPSR_T)
{
ARM7i_Thumb_Step();
}
else
#endif
{
ARM7i_Step ();
}
// and test interrupts
ARM7_CheckIRQ ();
}
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
/** Runs emulation for at least n cycles, returns actual amount of cycles
burned - normal interpreter. */
int ARM7_Execute (int n)
{
ARM7.cykle = 0;
while (ARM7.cykle < n)
{
ARM7_CheckIRQ ();
while (!ARM7.flagi && ARM7.cykle < n)
// make one step, sum up cycles
ARM7.cykle += ARM7i_Step ();
}
return ARM7.cykle;
}
//--------------------------------------------------------------------------
// private functions
//--------------------------------------------------------------------------
/** CPU Reset. */
void Reset (void)
{
// clear ALU flags
ARM7.carry = 0;
ARM7.overflow = 0;
// test CPSR mode and pick a valid one if necessary
if (s_tabTryb [ARM7_CPSR_M (ARM7.Rx [ARM7_CPSR])] < 0)
ARM7.Rx [ARM7_CPSR] = ARM7_CPSR_I | ARM7_CPSR_F | ARM7_CPSR_M_svc;
// set up registers according to manual
RX_BANK (ARM7_MODE_svc, ARM7_LR) = ARM7.Rx [ARM7_PC];
RX_BANK (ARM7_MODE_svc, ARM7_SPSR) = ARM7.Rx [ARM7_CPSR];
ARM7_SetCPSR (ARM7_CPSR_I | ARM7_CPSR_F | ARM7_CPSR_M_svc);
ARM7.Rx [ARM7_PC] = 0x00000000;
}
//--------------------------------------------------------------------------

View file

@ -1,165 +0,0 @@
//
// ARM7 processor emulator
// version 1.6 / 2008-02-16
// (c) Radoslaw Balcewicz
//
#ifndef _ARM7_h_
#define _ARM7_h_
#include "cpuintrf.h"
//--------------------------------------------------------------------------
// definitions and macros
/** If defined, will turn on specific behavior emulation, as well as some
optimizations that are valid only for Dreamcast AICA. */
#define ARM7_DREAMCAST
/** Define to enable Thumb support for ARM7. */
//#define ARM7_THUMB
// sanity tests
#ifdef ARM7_DREAMCAST
#ifdef ARM7_THUMB
#warning "Dreamcast ARM7 is a -DI type, it doesn't support Thumb mode."
#endif
#else
// #warning "Instructions cycle counts might not be correct."
#endif
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// CPU definitions
/** Status flags in CPSR register. */
#define ARM7_CPSR_N (1 << 31)
#define ARM7_CPSR_Z (1 << 30)
#define ARM7_CPSR_C (1 << 29)
#define ARM7_CPSR_V (1 << 28)
#define ARM7_CPSR_I (1 << 7)
#define ARM7_CPSR_F (1 << 6)
#define ARM7_CPSR_T (1 << 5)
/** CPSR bit mask for current operating mode. */
#define ARM7_CPSR_M(x) ((x) & 0x1f)
#define ARM7_CPSR_MX(sr,x) (((sr) & ~0x1f) | ((x) & 0x1f))
/** Bit combinations for each operating mode. */
#define ARM7_CPSR_M_usr 0x10
#define ARM7_CPSR_M_fiq 0x11
#define ARM7_CPSR_M_irq 0x12
#define ARM7_CPSR_M_svc 0x13
#define ARM7_CPSR_M_abt 0x17
#define ARM7_CPSR_M_und 0x11
#define ARM7_CPSR_M_sys 0x1f
/** Control flags for ARM7 core. */
#define ARM7_FL_FIQ (1 << 0)
#define ARM7_FL_IRQ (1 << 1)
/** Operating modes. */
#define ARM7_MODE_usr 0
#define ARM7_MODE_fiq 1
#define ARM7_MODE_irq 2
#define ARM7_MODE_svc 3
#define ARM7_MODE_abt 4
#define ARM7_MODE_und 5
#define ARM7_MODE_sys 0
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// register definitions
/** ARM7 register type (all are 32-bit). */
typedef INT32 ARM7_REG;
enum
{
ARM7_R0 = 0, ARM7_R1, ARM7_R2, ARM7_R3, ARM7_R4, ARM7_R5, ARM7_R6, ARM7_R7,
ARM7_R8, ARM7_R9, ARM7_R10, ARM7_R11, ARM7_R12, ARM7_R13, ARM7_R14, ARM7_R15
};
/** R13 is stack pointer. */
#define ARM7_SP 13
/** R14 is link/return address. */
#define ARM7_LR 14
/** R15 is program counter. */
#define ARM7_PC 15
/** CPSR control register. */
#define ARM7_CPSR 16
/** SPSR control register. */
#define ARM7_SPSR 17
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
/** ARM7 CPU state structure. */
struct sARM7
{
/** All-purpose and control registers (for current mode). */
ARM7_REG Rx [18];
/** Banked registers for all operating modes. */
ARM7_REG Rx_bank [6][10];
/** FIQ and IRQ interrupt requests. */
int fiq, irq;
/** Carry flag for barrel shifter and ALU operations. */
int carry;
/** Overflow flag for arithmetic instructions. */
int overflow;
/** Emulation control flags. */
int flagi;
/** Instruction code. */
UINT32 kod;
/** Cycle counter. */
int cykle;
};
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
/** ARM7 state. */
extern struct sARM7 ARM7;
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// public procedures
/** ARM7 emulator init. */
void ARM7_Init (void);
/** Power-ON reset. */
void ARM7_HardReset (void);
/** Hardware reset via /RESET line. */
void ARM7_SoftReset (void);
/** CPSR update, possibly changing operating mode. */
void ARM7_SetCPSR (ARM7_REG sr);
/** Sets FIQ line state. */
void ARM7_SetFIQ (int stan);
/** Sets IRQ line state. */
void ARM7_SetIRQ (int stan);
/** Tests for pending interrupts, switches to one if possible. */
void ARM7_CheckIRQ (void);
/** Single step. */
void ARM7_Step (void);
/** Runs emulation for at least n cycles, returns actual amount of cycles
burned - normal interpreter. */
int ARM7_Execute (int n);
//--------------------------------------------------------------------------
enum
{
ARM7_IRQ_LINE=0, ARM7_FIRQ_LINE,
ARM7_NUM_LINES
};
#ifdef ENABLE_DEBUGGER
extern UINT32 arm7_disasm( char *pBuf, UINT32 pc, UINT32 opcode );
extern UINT32 thumb_disasm( char *pBuf, UINT32 pc, UINT16 opcode );
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,19 +0,0 @@
//
// ARM7 processor emulator - interpreter core
// version 1.6 / 2008-02-16
// (c) Radoslaw Balcewicz
//
#ifndef _ARM7i_h_
#define _ARM7i_h_
#include "arm7.h"
//--------------------------------------------------------------------------
// public functions
/** Single step, returns number of burned cycles. */
int ARM7i_Step(void);
//--------------------------------------------------------------------------
#endif

View file

@ -1,56 +0,0 @@
// memory inline functions shared by ARM and THUMB modes
static INLINE void arm7_write_32(UINT32 addr, UINT32 data )
{
addr &= ~3;
dc_write32(addr,data);
}
static INLINE void arm7_write_16(UINT32 addr, UINT16 data)
{
addr &= ~1;
dc_write16(addr,data);
}
static INLINE void arm7_write_8(UINT32 addr, UINT8 data)
{
dc_write8(addr,data);
}
static INLINE UINT32 arm7_read_32(UINT32 addr)
{
UINT32 result;
int k = (addr & 3) << 3;
if (k)
{
result = dc_read32 (addr & ~3);
result = (result >> k) | (result << (32 - k));
}
else
{
result = dc_read32(addr);
}
return result;
}
static INLINE UINT16 arm7_read_16(UINT32 addr)
{
UINT16 result;
result = dc_read16(addr & ~1);
if (addr & 1)
{
result = ((result>>8) & 0xff) | ((result&0xff)<<8);
}
return result;
}
static INLINE UINT8 arm7_read_8(UINT32 addr)
{
return dc_read8(addr);
}

File diff suppressed because it is too large Load diff

View file

@ -1,117 +0,0 @@
#ifndef _ARM7_THUMB_
#define _ARM7_THUMB_
#define THUMB_INSN_TYPE ((UINT16) 0xf000)
#define THUMB_COND_TYPE ((UINT16) 0x0f00)
#define THUMB_GROUP4_TYPE ((UINT16) 0x0c00)
#define THUMB_GROUP5_TYPE ((UINT16) 0x0e00)
#define THUMB_GROUP5_RM ((UINT16) 0x01c0)
#define THUMB_GROUP5_RN ((UINT16) 0x0038)
#define THUMB_GROUP5_RD ((UINT16) 0x0007)
#define THUMB_ADDSUB_RNIMM ((UINT16) 0x01c0)
#define THUMB_ADDSUB_RS ((UINT16) 0x0038)
#define THUMB_ADDSUB_RD ((UINT16) 0x0007)
#define THUMB_INSN_ADDSUB ((UINT16) 0x0800)
#define THUMB_INSN_CMP ((UINT16) 0x0800)
#define THUMB_INSN_SUB ((UINT16) 0x0800)
#define THUMB_INSN_IMM_RD ((UINT16) 0x0700)
#define THUMB_INSN_IMM_S ((UINT16) 0x0080)
#define THUMB_INSN_IMM ((UINT16) 0x00ff)
#define THUMB_ADDSUB_TYPE ((UINT16) 0x0600)
#define THUMB_HIREG_OP ((UINT16) 0x0300)
#define THUMB_HIREG_H ((UINT16) 0x00c0)
#define THUMB_HIREG_RS ((UINT16) 0x0038)
#define THUMB_HIREG_RD ((UINT16) 0x0007)
#define THUMB_STACKOP_TYPE ((UINT16) 0x0f00)
#define THUMB_STACKOP_L ((UINT16) 0x0800)
#define THUMB_STACKOP_RD ((UINT16) 0x0700)
#define THUMB_ALUOP_TYPE ((UINT16) 0x03c0)
#define THUMB_BLOP_LO ((UINT16) 0x0800)
#define THUMB_BLOP_OFFS ((UINT16) 0x07ff)
#define THUMB_SHIFT_R ((UINT16) 0x0800)
#define THUMB_SHIFT_AMT ((UINT16) 0x07c0)
#define THUMB_HALFOP_L ((UINT16) 0x0800)
#define THUMB_HALFOP_OFFS ((UINT16) 0x07c0)
#define THUMB_BRANCH_OFFS ((UINT16) 0x07ff)
#define THUMB_LSOP_L ((UINT16) 0x0800)
#define THUMB_LSOP_OFFS ((UINT16) 0x07c0)
#define THUMB_MULTLS ((UINT16) 0x0800)
#define THUMB_MULTLS_BASE ((UINT16) 0x0700)
#define THUMB_RELADDR_SP ((UINT16) 0x0800)
#define THUMB_RELADDR_RD ((UINT16) 0x0700)
#define THUMB_INSN_TYPE_SHIFT 12
#define THUMB_COND_TYPE_SHIFT 8
#define THUMB_GROUP4_TYPE_SHIFT 10
#define THUMB_GROUP5_TYPE_SHIFT 9
#define THUMB_ADDSUB_TYPE_SHIFT 9
#define THUMB_INSN_IMM_RD_SHIFT 8
#define THUMB_STACKOP_TYPE_SHIFT 8
#define THUMB_HIREG_OP_SHIFT 8
#define THUMB_STACKOP_RD_SHIFT 8
#define THUMB_MULTLS_BASE_SHIFT 8
#define THUMB_RELADDR_RD_SHIFT 8
#define THUMB_HIREG_H_SHIFT 6
#define THUMB_HIREG_RS_SHIFT 3
#define THUMB_ALUOP_TYPE_SHIFT 6
#define THUMB_SHIFT_AMT_SHIFT 6
#define THUMB_HALFOP_OFFS_SHIFT 6
#define THUMB_LSOP_OFFS_SHIFT 6
#define THUMB_GROUP5_RM_SHIFT 6
#define THUMB_GROUP5_RN_SHIFT 3
#define THUMB_GROUP5_RD_SHIFT 0
#define THUMB_ADDSUB_RNIMM_SHIFT 6
#define THUMB_ADDSUB_RS_SHIFT 3
#define THUMB_ADDSUB_RD_SHIFT 0
#define THUMB_SIGN_BIT ((UINT32)(1<<31))
#define THUMB_SIGN_BITS_DIFFER(a,b) (((a)^(b)) >> 31)
#define N_IS_SET(pc) ((pc) & ARM7_CPSR_N)
#define Z_IS_SET(pc) ((pc) & ARM7_CPSR_Z)
#define C_IS_SET(pc) ((pc) & ARM7_CPSR_C)
#define V_IS_SET(pc) ((pc) & ARM7_CPSR_V)
#define I_IS_SET(pc) ((pc) & ARM7_CPSR_I)
#define F_IS_SET(pc) ((pc) & ARM7_CPSR_F)
#define T_IS_SET(pc) ((pc) & ARM7_CPSR_T)
#define N_IS_CLEAR(pc) (!N_IS_SET(pc))
#define Z_IS_CLEAR(pc) (!Z_IS_SET(pc))
#define C_IS_CLEAR(pc) (!C_IS_SET(pc))
#define V_IS_CLEAR(pc) (!V_IS_SET(pc))
#define I_IS_CLEAR(pc) (!I_IS_SET(pc))
#define F_IS_CLEAR(pc) (!F_IS_SET(pc))
#define T_IS_CLEAR(pc) (!T_IS_SET(pc))
enum
{
COND_EQ = 0, /* Z: equal */
COND_NE, /* ~Z: not equal */
COND_CS, COND_HS = 2, /* C: unsigned higher or same */
COND_CC, COND_LO = 3, /* ~C: unsigned lower */
COND_MI, /* N: negative */
COND_PL, /* ~N: positive or zero */
COND_VS, /* V: overflow */
COND_VC, /* ~V: no overflow */
COND_HI, /* C && ~Z: unsigned higher */
COND_LS, /* ~C || Z: unsigned lower or same */
COND_GE, /* N == V: greater or equal */
COND_LT, /* N != V: less than */
COND_GT, /* ~Z && (N == V): greater than */
COND_LE, /* Z || (N != V): less than or equal */
COND_AL, /* always */
COND_NV /* never */
};
#define GET_CPSR ARM7.Rx [ARM7_CPSR]
#define GET_REGISTER(r) ARM7.Rx[(r)]
#define SET_REGISTER(r, v) ARM7.Rx[(r)] = (v)
#define R15 ARM7.Rx[ARM7_PC]
// public function
int ARM7i_Thumb_Step(void);
#endif

View file

@ -1,175 +0,0 @@
// dc_hw.c - Hardware found on the ARM7/AICA side of the Dreamcast
#include "ao.h"
#include "dc_hw.h"
#include "aica.h"
#define DK_CORE (1)
#if DK_CORE
#include "arm7.h"
#else
#include "arm7core.h"
#endif
uint8 dc_ram[8*1024*1024];
static void aica_irq(int irq)
{
if (irq > 0)
{
#if DK_CORE
ARM7_SetFIQ(TRUE);
#else
set_irq_line(ARM7_FIRQ_LINE, 1);
#endif
}
else
{
#if DK_CORE
ARM7_SetFIQ(FALSE);
#else
set_irq_line(ARM7_FIRQ_LINE, 0);
#endif
}
}
#define MIXER_PAN_LEFT 1
#define MIXER_PAN_RIGHT 2
#define MIXER(level,pan) ((level & 0xff) | ((pan & 0x03) << 8))
#define YM3012_VOL(LVol,LPan,RVol,RPan) (MIXER(LVol,LPan)|(MIXER(RVol,RPan) << 16))
static struct AICAinterface aica_interface =
{
1,
{ dc_ram, },
{ YM3012_VOL(100, MIXER_PAN_LEFT, 100, MIXER_PAN_RIGHT) },
{ aica_irq, },
};
uint8 dc_read8(int addr)
{
if (addr < 0x800000)
{
return dc_ram[addr];
}
if ((addr >= 0x800000) && (addr <= 0x807fff))
{
int foo = AICA_0_r((addr-0x800000)/2, 0);
if (addr & 1)
{
return foo>>8;
}
else
{
return foo & 0xff;
}
}
printf("R8 @ %x\n", addr);
return -1;
}
uint16 dc_read16(int addr)
{
if (addr < 0x800000)
{
return dc_ram[addr] | (dc_ram[addr+1]<<8);
}
if ((addr >= 0x800000) && (addr <= 0x807fff))
{
return AICA_0_r((addr-0x800000)/2, 0);
}
printf("R16 @ %x\n", addr);
return -1;
}
uint32 dc_read32(int addr)
{
if (addr < 0x800000)
{
return dc_ram[addr] | (dc_ram[addr+1]<<8) | (dc_ram[addr+2]<<16) | (dc_ram[addr+3]<<24);
}
if ((addr >= 0x800000) && (addr <= 0x807fff))
{
addr &= 0x7fff;
return AICA_0_r(addr/2, 0) & 0xffff;
}
// printf("R32 @ %x\n", addr);
return 0;
}
void dc_write8(int addr, uint8 data)
{
if (addr < 0x800000)
{
dc_ram[addr] = data;
return;
}
if ((addr >= 0x800000) && (addr <= 0x807fff))
{
addr -= 0x800000;
if ((addr & 1))
AICA_0_w(addr>>1, data<<8, 0x00ff);
else
AICA_0_w(addr>>1, data, 0xff00);
return;
}
printf("W8 %x @ %x\n", data, addr);
}
void dc_write16(int addr, uint16 data)
{
if (addr < 0x800000)
{
dc_ram[addr] = data&0xff;
dc_ram[addr+1] = (data>>8) & 0xff;
return;
}
if ((addr >= 0x800000) && (addr <= 0x807fff))
{
AICA_0_w((addr-0x800000)/2, data, 0);
return;
}
printf("W16 %x @ %x\n", data, addr);
}
void dc_write32(int addr, uint32 data)
{
if (addr < 0x800000)
{
dc_ram[addr] = data&0xff;
dc_ram[addr+1] = (data>>8) & 0xff;
dc_ram[addr+2] = (data>>16) & 0xff;
dc_ram[addr+3] = (data>>24) & 0xff;
return;
}
if ((addr >= 0x800000) && (addr <= 0x807fff))
{
addr -= 0x800000;
AICA_0_w((addr>>1), data&0xffff, 0x0000);
AICA_0_w((addr>>1)+1, data>>16, 0x0000);
return;
}
printf("W32 %x @ %x\n", data, addr);
}
void dc_hw_init(void)
{
aica_interface.region[0] = dc_ram;
aica_start(&aica_interface);
}

View file

@ -1,9 +0,0 @@
#ifndef _DC_HW_H_
#define _DC_HW_H_
extern uint8 dc_ram[8*1024*1024];
void dc_hw_init(void);
#endif

View file

@ -1,261 +0,0 @@
//
// Audio Overload
// Emulated music player
//
// (C) 2000-2008 Richard F. Bannister
//
//
// eng_dsf.c
//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ao.h"
#include "eng_protos.h"
#include "corlett.h"
#include "dc_hw.h"
#include "aica.h"
#define DEBUG_LOADER (0)
#define DK_CORE (1)
#if DK_CORE
#include "arm7.h"
#else
#include "arm7core.h"
#endif
static corlett_t *c = NULL;
static char psfby[256];
static uint32 decaybegin, decayend, total_samples;
void *aica_start(const void *config);
void aica_stop(void);
void AICA_Update(void *param, INT16 **inputs, INT16 **buf, int samples);
int32 dsf_start(uint8 *buffer, uint32 length)
{
uint8 *file, *lib_decoded, *lib_raw_file;
uint32 offset, plength, lengthMS, fadeMS;
uint64 file_len, lib_len, lib_raw_length;
corlett_t *lib;
char *libfile;
int i;
// clear Dreamcast work RAM before we start scribbling in it
memset(dc_ram, 0, 8*1024*1024);
// Decode the current SSF
if (corlett_decode(buffer, length, &file, &file_len, &c) != AO_SUCCESS)
{
return AO_FAIL;
}
#if DEBUG_LOADER
printf("%d bytes decoded\n", file_len);
#endif
// Get the library file, if any
for (i=0; i<9; i++) {
libfile = i ? c->libaux[i-1] : c->lib;
if (libfile[0] != 0)
{
uint64 tmp_length;
#if DEBUG_LOADER
printf("Loading library: %s\n", c->lib);
#endif
if (ao_get_lib(libfile, &lib_raw_file, &tmp_length) != AO_SUCCESS)
{
return AO_FAIL;
}
lib_raw_length = tmp_length;
if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS)
{
free(lib_raw_file);
return AO_FAIL;
}
// Free up raw file
free(lib_raw_file);
// patch the file into ram
offset = lib_decoded[0] | lib_decoded[1]<<8 | lib_decoded[2]<<16 | lib_decoded[3]<<24;
memcpy(&dc_ram[offset], lib_decoded+4, lib_len-4);
// Dispose the corlett structure for the lib - we don't use it
free(lib);
free(lib_decoded);
}
}
// now patch the file into RAM over the libraries
offset = file[3]<<24 | file[2]<<16 | file[1]<<8 | file[0];
memcpy(&dc_ram[offset], file+4, file_len-4);
free(file);
// Finally, set psfby/ssfby tag
strcpy(psfby, "n/a");
if (c)
{
for (i = 0; i < MAX_UNKNOWN_TAGS; i++)
{
if ((!strcasecmp(c->tag_name[i], "psfby")) || (!strcasecmp(c->tag_name[i], "ssfby")))
strcpy(psfby, c->tag_data[i]);
}
}
#if DEBUG_LOADER && 1
{
FILE *f;
f = fopen("dcram.bin", "wb");
fwrite(dc_ram, 2*1024*1024, 1, f);
fclose(f);
}
#endif
#if DK_CORE
ARM7_Init();
#else
arm7_init(0, 45000000, NULL, NULL);
arm7_reset();
#endif
dc_hw_init();
// now figure out the time in samples for the length/fade
lengthMS = psfTimeToMS(c->inf_length);
fadeMS = psfTimeToMS(c->inf_fade);
total_samples = 0;
if (lengthMS == 0)
{
lengthMS = ~0;
}
if (lengthMS == ~0)
{
decaybegin = lengthMS;
}
else
{
lengthMS = (lengthMS * 441) / 10;
fadeMS = (fadeMS * 441) / 10;
decaybegin = lengthMS;
decayend = lengthMS + fadeMS;
}
return AO_SUCCESS;
}
int32 dsf_gen(int16 *buffer, uint32 samples)
{
int i;
int16 output[44100/30], output2[44100/30];
int16 *stereo[2];
int16 *outp = buffer;
int opos;
opos = 0;
for (i = 0; i < samples; i++)
{
#if DK_CORE
ARM7_Execute((33000000 / 60 / 4) / 735);
#else
arm7_execute((33000000 / 60 / 4) / 735);
#endif
stereo[0] = &output[opos];
stereo[1] = &output2[opos];
AICA_Update(NULL, NULL, stereo, 1);
opos++;
}
for (i = 0; i < samples; i++)
{
// process the fade tags
if (total_samples >= decaybegin)
{
if (total_samples >= decayend)
{
// song is done here, signal your player appropriately!
// ao_song_done = 1;
output[i] = 0;
output2[i] = 0;
}
else
{
int32 fader = 256 - (256*(total_samples - decaybegin)/(decayend-decaybegin));
output[i] = (output[i] * fader)>>8;
output2[i] = (output2[i] * fader)>>8;
total_samples++;
}
}
else
{
total_samples++;
}
*outp++ = output[i];
*outp++ = output2[i];
}
return AO_SUCCESS;
}
int32 dsf_stop(void)
{
aica_stop();
free(c);
return AO_SUCCESS;
}
int32 dsf_command(int32 command, int32 parameter)
{
switch (command)
{
case COMMAND_RESTART:
return AO_SUCCESS;
}
return AO_FAIL;
}
int32 dsf_fill_info(ao_display_info *info)
{
if (c == NULL)
return AO_FAIL;
strcpy(info->title[1], "Name: ");
sprintf(info->info[1], "%s", c->inf_title);
strcpy(info->title[2], "Game: ");
sprintf(info->info[2], "%s", c->inf_game);
strcpy(info->title[3], "Artist: ");
sprintf(info->info[3], "%s", c->inf_artist);
strcpy(info->title[4], "Copyright: ");
sprintf(info->info[4], "%s", c->inf_copy);
strcpy(info->title[5], "Year: ");
sprintf(info->info[5], "%s", c->inf_year);
strcpy(info->title[6], "Length: ");
sprintf(info->info[6], "%s", c->inf_length);
strcpy(info->title[7], "Fade: ");
sprintf(info->info[7], "%s", c->inf_fade);
strcpy(info->title[8], "Ripper: ");
sprintf(info->info[8], "%s", psfby);
return AO_SUCCESS;
}

View file

@ -1,53 +0,0 @@
//
// Audio Overload
// Emulated music player
//
// (C) 2000-2007 Richard F. Bannister
//
//
// eng_protos.h
//
int32 psf_start(uint8 *, uint32 length);
int32 psf_gen(int16 *, uint32);
int32 psf_stop(void);
int32 psf_command(int32, int32);
int32 psf_fill_info(ao_display_info *);
int32 psf2_start(uint8 *, uint32 length);
int32 psf2_gen(int16 *, uint32);
int32 psf2_stop(void);
int32 psf2_command(int32, int32);
int32 psf2_fill_info(ao_display_info *);
int32 qsf_start(uint8 *, uint32 length);
int32 qsf_gen(int16 *, uint32);
int32 qsf_stop(void);
int32 qsf_command(int32, int32);
int32 qsf_fill_info(ao_display_info *);
int32 ssf_start(uint8 *, uint32 length);
int32 ssf_gen(int16 *, uint32);
int32 ssf_stop(void);
int32 ssf_command(int32, int32);
int32 ssf_fill_info(ao_display_info *);
int32 spu_start(uint8 *, uint32 length);
int32 spu_gen(int16 *, uint32);
int32 spu_stop(void);
int32 spu_command(int32, int32);
int32 spu_fill_info(ao_display_info *);
uint8 qsf_memory_read(uint16 addr);
uint8 qsf_memory_readop(uint16 addr);
uint8 qsf_memory_readport(uint16 addr);
void qsf_memory_write(uint16 addr, uint8 byte);
void qsf_memory_writeport(uint16 addr, uint8 byte);
int32 dsf_start(uint8 *, uint32 length);
int32 dsf_gen(int16 *, uint32);
int32 dsf_stop(void);
int32 dsf_command(int32, int32);
int32 dsf_fill_info(ao_display_info *);

View file

@ -1,668 +0,0 @@
#ifndef CPUINTRF_H
#define CPUINTRF_H
#include "osd_cpu.h"
/* The old system is obsolete and no longer supported by the core */
#define NEW_INTERRUPT_SYSTEM 1
#define MAX_IRQ_LINES 8 /* maximum number of IRQ lines per CPU */
#define CLEAR_LINE 0 /* clear (a fired, held or pulsed) line */
#define ASSERT_LINE 1 /* assert an interrupt immediately */
#define HOLD_LINE 2 /* hold interrupt line until enable is true */
#define PULSE_LINE 3 /* pulse interrupt line for one instruction */
#define MAX_REGS 64 /* maximum number of register of any CPU */
#define IRQ_LINE_NMI 10
/* Values passed to the cpu_info function of a core to retrieve information */
enum {
CPU_INFO_REG,
CPU_INFO_FLAGS=MAX_REGS,
CPU_INFO_NAME,
CPU_INFO_FAMILY,
CPU_INFO_VERSION,
CPU_INFO_FILE,
CPU_INFO_CREDITS,
CPU_INFO_REG_LAYOUT,
CPU_INFO_WIN_LAYOUT
};
#define CPU_IS_LE 0 /* emulated CPU is little endian */
#define CPU_IS_BE 1 /* emulated CPU is big endian */
/*
* This value is passed to cpu_get_reg to retrieve the previous
* program counter value, ie. before a CPU emulation started
* to fetch opcodes and arguments for the current instrution.
*/
#define REG_PREVIOUSPC -1
/*
* This value is passed to cpu_get_reg/cpu_set_reg, instead of one of
* the names from the enum a CPU core defines for it's registers,
* to get or set the contents of the memory pointed to by a stack pointer.
* You can specify the n'th element on the stack by (REG_SP_CONTENTS-n),
* ie. lower negative values. The actual element size (UINT16 or UINT32)
* depends on the CPU core.
* This is also used to replace the cpu_geturnpc() function.
*/
#define REG_SP_CONTENTS -2
/*
* These flags can be defined in the makefile (or project) to
* exclude (zero) or include (non zero) specific CPU cores
*/
#ifndef HAS_GENSYNC
#define HAS_GENSYNC 0
#endif
#ifndef HAS_Z80
#define HAS_Z80 0
#endif
#ifndef HAS_Z80_VM
#define HAS_Z80_VM 0
#endif
#ifndef HAS_8080
#define HAS_8080 0
#endif
#ifndef HAS_8085A
#define HAS_8085A 0
#endif
#ifndef HAS_M6502
#define HAS_M6502 0
#endif
#ifndef HAS_M65C02
#define HAS_M65C02 0
#endif
#ifndef HAS_M65SC02
#define HAS_M65SC02 0
#endif
#ifndef HAS_M65CE02
#define HAS_M65CE02 0
#endif
#ifndef HAS_M6509
#define HAS_M6509 0
#endif
#ifndef HAS_M6510
#define HAS_M6510 0
#endif
#ifndef HAS_N2A03
#define HAS_N2A03 0
#endif
#ifndef HAS_H6280
#define HAS_H6280 0
#endif
#ifndef HAS_I86
#define HAS_I86 0
#endif
#ifndef HAS_V20
#define HAS_V20 0
#endif
#ifndef HAS_V30
#define HAS_V30 0
#endif
#ifndef HAS_V33
#define HAS_V33 0
#endif
#ifndef HAS_I8035
#define HAS_I8035 0
#endif
#ifndef HAS_I8039
#define HAS_I8039 0
#endif
#ifndef HAS_I8048
#define HAS_I8048 0
#endif
#ifndef HAS_N7751
#define HAS_N7751 0
#endif
#ifndef HAS_M6800
#define HAS_M6800 0
#endif
#ifndef HAS_M6801
#define HAS_M6801 0
#endif
#ifndef HAS_M6802
#define HAS_M6802 0
#endif
#ifndef HAS_M6803
#define HAS_M6803 0
#endif
#ifndef HAS_M6808
#define HAS_M6808 0
#endif
#ifndef HAS_HD63701
#define HAS_HD63701 0
#endif
#ifndef HAS_M6805
#define HAS_M6805 0
#endif
#ifndef HAS_M68705
#define HAS_M68705 0
#endif
#ifndef HAS_HD63705
#define HAS_HD63705 0
#endif
#ifndef HAS_HD6309
#define HAS_HD6309 0
#endif
#ifndef HAS_M6809
#define HAS_M6809 0
#endif
#ifndef HAS_KONAMI
#define HAS_KONAMI 0
#endif
#ifndef HAS_M68000
#define HAS_M68000 0
#endif
#ifndef HAS_M68010
#define HAS_M68010 0
#endif
#ifndef HAS_M68020
#define HAS_M68020 0
#endif
#ifndef HAS_T11
#define HAS_T11 0
#endif
#ifndef HAS_S2650
#define HAS_S2650 0
#endif
#ifndef HAS_TMS34010
#define HAS_TMS34010 0
#endif
#ifndef HAS_TMS9900
#define HAS_TMS9900 0
#endif
#ifndef HAS_TMS9940
#define HAS_TMS9940 0
#endif
#ifndef HAS_TMS9980
#define HAS_TMS9980 0
#endif
#ifndef HAS_TMS9985
#define HAS_TMS9985 0
#endif
#ifndef HAS_TMS9989
#define HAS_TMS9989 0
#endif
#ifndef HAS_TMS9995
#define HAS_TMS9995 0
#endif
#ifndef HAS_TMS99105A
#define HAS_TMS99105A 0
#endif
#ifndef HAS_TMS99110A
#define HAS_TMS99110A 0
#endif
#ifndef HAS_Z8000
#define HAS_Z8000 0
#endif
#ifndef HAS_TMS320C10
#define HAS_TMS320C10 0
#endif
#ifndef HAS_CCPU
#define HAS_CCPU 0
#endif
#ifndef HAS_PDP1
#define HAS_PDP1 0
#endif
#ifndef HAS_ADSP2100
#define HAS_ADSP2100 0
#endif
/* ASG 971222 -- added this generic structure */
struct cpu_interface
{
unsigned cpu_num;
void (*reset)(void *param);
void (*exit)(void);
int (*execute)(int cycles);
void (*burn)(int cycles);
unsigned (*get_context)(void *reg);
void (*set_context)(void *reg);
unsigned (*get_pc)(void);
void (*set_pc)(unsigned val);
unsigned (*get_sp)(void);
void (*set_sp)(unsigned val);
unsigned (*get_reg)(int regnum);
void (*set_reg)(int regnum, unsigned val);
void (*set_nmi_line)(int linestate);
void (*set_irq_line)(int irqline, int linestate);
void (*set_irq_callback)(int(*callback)(int irqline));
void (*internal_interrupt)(int type);
void (*cpu_state_save)(void *file);
void (*cpu_state_load)(void *file);
const char* (*cpu_info)(void *context,int regnum);
unsigned (*cpu_dasm)(char *buffer,unsigned pc);
unsigned num_irqs;
int default_vector;
int *icount;
double overclock;
int no_int, irq_int, nmi_int;
int (*memory_read)(int offset);
void (*memory_write)(int offset, int data);
void (*set_op_base)(int pc);
int address_shift;
unsigned address_bits, endianess, align_unit, max_inst_len;
unsigned abits1, abits2, abitsmin;
};
extern struct cpu_interface cpuintf[];
void cpu_init(void);
void cpu_run(void);
/* optional watchdog */
void watchdog_reset_w(int offset,int data);
int watchdog_reset_r(int offset);
/* Use this function to reset the machine */
void machine_reset(void);
/* Use this function to reset a single CPU */
void cpu_set_reset_line(int cpu,int state);
/* Use this function to halt a single CPU */
void cpu_set_halt_line(int cpu,int state);
/* This function returns CPUNUM current status (running or halted) */
int cpu_getstatus(int cpunum);
int cpu_gettotalcpu(void);
int cpu_getactivecpu(void);
void cpu_setactivecpu(int cpunum);
/* Returns the current program counter */
unsigned cpu_get_pc(void);
/* Set the current program counter */
void cpu_set_pc(unsigned val);
/* Returns the current stack pointer */
unsigned cpu_get_sp(void);
/* Set the current stack pointer */
void cpu_set_sp(unsigned val);
/* Get the active CPUs context and return it's size */
unsigned cpu_get_context(void *context);
/* Set the active CPUs context */
void cpu_set_context(void *context);
/* Returns a specific register value (mamedbg) */
unsigned cpu_get_reg(int regnum);
/* Sets a specific register value (mamedbg) */
void cpu_set_reg(int regnum, unsigned val);
/* Returns previous pc (start of opcode causing read/write) */
/* int cpu_getpreviouspc(void); */
#define cpu_getpreviouspc() cpu_get_reg(REG_PREVIOUSPC)
/* Returns the return address from the top of the stack (Z80 only) */
/* int cpu_getreturnpc(void); */
/* This can now be handled with a generic function */
#define cpu_geturnpc() cpu_get_reg(REG_SP_CONTENTS)
int cycles_currently_ran(void);
int cycles_left_to_run(void);
/* Returns the number of CPU cycles which take place in one video frame */
int cpu_gettotalcycles(void);
/* Returns the number of CPU cycles before the next interrupt handler call */
int cpu_geticount(void);
/* Returns the number of CPU cycles before the end of the current video frame */
int cpu_getfcount(void);
/* Returns the number of CPU cycles in one video frame */
int cpu_getfperiod(void);
/* Scales a given value by the ratio of fcount / fperiod */
int cpu_scalebyfcount(int value);
/* Returns the current scanline number */
int cpu_getscanline(void);
/* Returns the amount of time until a given scanline */
double cpu_getscanlinetime(int scanline);
/* Returns the duration of a single scanline */
double cpu_getscanlineperiod(void);
/* Returns the duration of a single scanline in cycles */
int cpu_getscanlinecycles(void);
/* Returns the number of cycles since the beginning of this frame */
int cpu_getcurrentcycles(void);
/* Returns the current horizontal beam position in pixels */
int cpu_gethorzbeampos(void);
/*
Returns the number of times the interrupt handler will be called before
the end of the current video frame. This is can be useful to interrupt
handlers to synchronize their operation. If you call this from outside
an interrupt handler, add 1 to the result, i.e. if it returns 0, it means
that the interrupt handler will be called once.
*/
int cpu_getiloops(void);
/* Returns the current VBLANK state */
int cpu_getvblank(void);
/* Returns the number of the video frame we are currently playing */
int cpu_getcurrentframe(void);
/* generate a trigger after a specific period of time */
void cpu_triggertime (double duration, int trigger);
/* generate a trigger now */
void cpu_trigger (int trigger);
/* burn CPU cycles until a timer trigger */
void cpu_spinuntil_trigger (int trigger);
/* burn CPU cycles until the next interrupt */
void cpu_spinuntil_int (void);
/* burn CPU cycles until our timeslice is up */
void cpu_spin (void);
/* burn CPU cycles for a specific period of time */
void cpu_spinuntil_time (double duration);
/* yield our timeslice for a specific period of time */
void cpu_yielduntil_trigger (int trigger);
/* yield our timeslice until the next interrupt */
void cpu_yielduntil_int (void);
/* yield our current timeslice */
void cpu_yield (void);
/* yield our timeslice for a specific period of time */
void cpu_yielduntil_time (double duration);
/* set the NMI line state for a CPU, normally use PULSE_LINE */
void cpu_set_nmi_line(int cpunum, int state);
/* set the IRQ line state for a specific irq line of a CPU */
/* normally use state HOLD_LINE, irqline 0 for first IRQ type of a cpu */
void cpu_set_irq_line(int cpunum, int irqline, int state);
/* this is to be called by CPU cores only! */
void cpu_generate_internal_interrupt(int cpunum, int type);
/* set the vector to be returned during a CPU's interrupt acknowledge cycle */
void cpu_irq_line_vector_w(int cpunum, int irqline, int vector);
/* use these in your write memory/port handles to set an IRQ vector */
/* offset corresponds to the irq line number here */
void cpu_0_irq_line_vector_w(int offset, int data);
void cpu_1_irq_line_vector_w(int offset, int data);
void cpu_2_irq_line_vector_w(int offset, int data);
void cpu_3_irq_line_vector_w(int offset, int data);
void cpu_4_irq_line_vector_w(int offset, int data);
void cpu_5_irq_line_vector_w(int offset, int data);
void cpu_6_irq_line_vector_w(int offset, int data);
void cpu_7_irq_line_vector_w(int offset, int data);
/* Obsolete functions: avoid to use them in new drivers if possible. */
/* cause an interrupt on a CPU */
void cpu_cause_interrupt(int cpu,int type);
void cpu_clear_pending_interrupts(int cpu);
void interrupt_enable_w(int offset,int data);
void interrupt_vector_w(int offset,int data);
int interrupt(void);
int nmi_interrupt(void);
int m68_level1_irq(void);
int m68_level2_irq(void);
int m68_level3_irq(void);
int m68_level4_irq(void);
int m68_level5_irq(void);
int m68_level6_irq(void);
int m68_level7_irq(void);
int ignore_interrupt(void);
/* CPU context access */
void* cpu_getcontext (int _activecpu);
int cpu_is_saving_context(int _activecpu);
/***************************************************************************
* Get information for the currently active CPU
* cputype is a value from the CPU enum in driver.h
***************************************************************************/
/* Return number of address bits */
unsigned cpu_address_bits(void);
/* Return address mask */
unsigned cpu_address_mask(void);
/* Return address shift factor (TMS34010 bit addressing mode) */
int cpu_address_shift(void);
/* Return endianess of the emulated CPU (CPU_IS_LE or CPU_IS_BE) */
unsigned cpu_endianess(void);
/* Return opcode align unit (1 byte, 2 word, 4 dword) */
unsigned cpu_align_unit(void);
/* Return maximum instruction length */
unsigned cpu_max_inst_len(void);
/* Return name of the active CPU */
const char *cpu_name(void);
/* Return family name of the active CPU */
const char *cpu_core_family(void);
/* Return core version of the active CPU */
const char *cpu_core_version(void);
/* Return core filename of the active CPU */
const char *cpu_core_file(void);
/* Return credits info for of the active CPU */
const char *cpu_core_credits(void);
/* Return register layout definition for the active CPU */
const char *cpu_reg_layout(void);
/* Return (debugger) window layout definition for the active CPU */
const char *cpu_win_layout(void);
/* Disassemble an instruction at PC into the given buffer */
unsigned cpu_dasm(char *buffer, unsigned pc);
/* Return a string describing the currently set flag (status) bits of the active CPU */
const char *cpu_flags(void);
/* Return a string with a register name and hex value for the active CPU */
/* regnum is a value defined in the CPU cores header files */
const char *cpu_dump_reg(int regnum);
/* Return a string describing the active CPUs current state */
const char *cpu_dump_state(void);
/***************************************************************************
* Get information for a specific CPU type
* cputype is a value from the CPU enum in driver.h
***************************************************************************/
/* Return address shift factor */
/* TMS320C10 -1: word addressing mode, TMS34010 3: bit addressing mode */
int cputype_address_shift(int cputype);
/* Return number of address bits */
unsigned cputype_address_bits(int cputype);
/* Return address mask */
unsigned cputype_address_mask(int cputype);
/* Return endianess of the emulated CPU (CPU_IS_LE or CPU_IS_BE) */
unsigned cputype_endianess(int cputype);
/* Return opcode align unit (1 byte, 2 word, 4 dword) */
unsigned cputype_align_unit(int cputype);
/* Return maximum instruction length */
unsigned cputype_max_inst_len(int cputype);
/* Return name of the CPU */
const char *cputype_name(int cputype);
/* Return family name of the CPU */
const char *cputype_core_family(int cputype);
/* Return core version number of the CPU */
const char *cputype_core_version(int cputype);
/* Return core filename of the CPU */
const char *cputype_core_file(int cputype);
/* Return credits for the CPU core */
const char *cputype_core_credits(int cputype);
/* Return register layout definition for the CPU core */
const char *cputype_reg_layout(int cputype);
/* Return (debugger) window layout definition for the CPU core */
const char *cputype_win_layout(int cputype);
/***************************************************************************
* Get (or set) information for a numbered CPU of the running machine
* cpunum is a value between 0 and cpu_gettotalcpu() - 1
***************************************************************************/
/* Return number of address bits */
unsigned cpunum_address_bits(int cputype);
/* Return address mask */
unsigned cpunum_address_mask(int cputype);
/* Return endianess of the emulated CPU (CPU_LSB_FIRST or CPU_MSB_FIRST) */
unsigned cpunum_endianess(int cputype);
/* Return opcode align unit (1 byte, 2 word, 4 dword) */
unsigned cpunum_align_unit(int cputype);
/* Return maximum instruction length */
unsigned cpunum_max_inst_len(int cputype);
/* Get a register value for the specified CPU number of the running machine */
unsigned cpunum_get_reg(int cpunum, int regnum);
/* Set a register value for the specified CPU number of the running machine */
void cpunum_set_reg(int cpunum, int regnum, unsigned val);
/* Return (debugger) register layout definition for the CPU core */
const char *cpunum_reg_layout(int cpunum);
/* Return (debugger) window layout definition for the CPU core */
const char *cpunum_win_layout(int cpunum);
unsigned cpunum_dasm(int cpunum,char *buffer,unsigned pc);
/* Return a string describing the currently set flag (status) bits of the CPU */
const char *cpunum_flags(int cpunum);
/* Return a string with a register name and value */
/* regnum is a value defined in the CPU cores header files */
const char *cpunum_dump_reg(int cpunum, int regnum);
/* Return a string describing the CPUs current state */
const char *cpunum_dump_state(int cpunum);
/* Return a name for the specified cpu number */
const char *cpunum_name(int cpunum);
/* Return a family name for the specified cpu number */
const char *cpunum_core_family(int cpunum);
/* Return a version for the specified cpu number */
const char *cpunum_core_version(int cpunum);
/* Return a the source filename for the specified cpu number */
const char *cpunum_core_file(int cpunum);
/* Return a the credits for the specified cpu number */
const char *cpunum_core_credits(int cpunum);
/* Dump all of the running machines CPUs state to stderr */
void cpu_dump_states(void);
/* daisy-chain link */
typedef struct {
void (*reset)(int); /* reset callback */
int (*interrupt_entry)(int); /* entry callback */
void (*interrupt_reti)(int); /* reti callback */
int irq_param; /* callback paramater */
} Z80_DaisyChain;
#define Z80_MAXDAISY 4 /* maximum of daisy chan device */
#define Z80_INT_REQ 0x01 /* interrupt request mask */
#define Z80_INT_IEO 0x02 /* interrupt disable mask(IEO) */
#define Z80_VECTOR(device,state) (((device)<<8)|(state))
#ifndef INLINE
#define INLINE inline
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define cpu_readmem16 memory_read
#define cpu_readport16 memory_readport
#define cpu_writeport16 memory_writeport
#define cpu_writemem16 memory_write
#define cpu_readop memory_readop
#define cpu_readop_arg memory_read
#define logerror(x, ...)
#define change_pc16(x)
#define CALL_MAME_DEBUG
#define ADDRESS_SPACES 3 /* maximum number of address spaces */
#define ADDRESS_SPACE_PROGRAM 0 /* program address space */
#define ADDRESS_SPACE_DATA 1 /* data address space */
#define ADDRESS_SPACE_IO 2 /* I/O address space */
enum
{
/* internal flags (not for use by drivers!) */
INTERNAL_CLEAR_LINE = 100 + CLEAR_LINE,
INTERNAL_ASSERT_LINE = 100 + ASSERT_LINE,
/* input lines */
MAX_INPUT_LINES = 32+3,
INPUT_LINE_IRQ0 = 0,
INPUT_LINE_IRQ1 = 1,
INPUT_LINE_IRQ2 = 2,
INPUT_LINE_IRQ3 = 3,
INPUT_LINE_IRQ4 = 4,
INPUT_LINE_IRQ5 = 5,
INPUT_LINE_IRQ6 = 6,
INPUT_LINE_IRQ7 = 7,
INPUT_LINE_IRQ8 = 8,
INPUT_LINE_IRQ9 = 9,
INPUT_LINE_NMI = MAX_INPUT_LINES - 3,
/* special input lines that are implemented in the core */
INPUT_LINE_RESET = MAX_INPUT_LINES - 2,
INPUT_LINE_HALT = MAX_INPUT_LINES - 1,
/* output lines */
MAX_OUTPUT_LINES = 32
};
enum
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
CPUINFO_INT_FIRST = 0x00000,
CPUINFO_INT_CONTEXT_SIZE = CPUINFO_INT_FIRST, /* R/O: size of CPU context in bytes */
CPUINFO_INT_INPUT_LINES, /* R/O: number of input lines */
CPUINFO_INT_OUTPUT_LINES, /* R/O: number of output lines */
CPUINFO_INT_DEFAULT_IRQ_VECTOR, /* R/O: default IRQ vector */
CPUINFO_INT_ENDIANNESS, /* R/O: either CPU_IS_BE or CPU_IS_LE */
CPUINFO_INT_CLOCK_DIVIDER, /* R/O: internal clock divider */
CPUINFO_INT_MIN_INSTRUCTION_BYTES, /* R/O: minimum bytes per instruction */
CPUINFO_INT_MAX_INSTRUCTION_BYTES, /* R/O: maximum bytes per instruction */
CPUINFO_INT_MIN_CYCLES, /* R/O: minimum cycles for a single instruction */
CPUINFO_INT_MAX_CYCLES, /* R/O: maximum cycles for a single instruction */
CPUINFO_INT_DATABUS_WIDTH, /* R/O: data bus size for each address space (8,16,32,64) */
CPUINFO_INT_DATABUS_WIDTH_LAST = CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACES - 1,
CPUINFO_INT_ADDRBUS_WIDTH, /* R/O: address bus size for each address space (12-32) */
CPUINFO_INT_ADDRBUS_WIDTH_LAST = CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACES - 1,
CPUINFO_INT_ADDRBUS_SHIFT, /* R/O: shift applied to addresses each address space (+3 means >>3, -1 means <<1) */
CPUINFO_INT_ADDRBUS_SHIFT_LAST = CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACES - 1,
CPUINFO_INT_SP, /* R/W: the current stack pointer value */
CPUINFO_INT_PC, /* R/W: the current PC value */
CPUINFO_INT_PREVIOUSPC, /* R/W: the previous PC value */
CPUINFO_INT_INPUT_STATE, /* R/W: states for each input line */
CPUINFO_INT_INPUT_STATE_LAST = CPUINFO_INT_INPUT_STATE + MAX_INPUT_LINES - 1,
CPUINFO_INT_OUTPUT_STATE, /* R/W: states for each output line */
CPUINFO_INT_OUTPUT_STATE_LAST = CPUINFO_INT_OUTPUT_STATE + MAX_OUTPUT_LINES - 1,
CPUINFO_INT_REGISTER, /* R/W: values of up to MAX_REGs registers */
CPUINFO_INT_REGISTER_LAST = CPUINFO_INT_REGISTER + MAX_REGS - 1,
CPUINFO_INT_CPU_SPECIFIC = 0x08000, /* R/W: CPU-specific values start here */
/* --- the following bits of info are returned as pointers to data or functions --- */
CPUINFO_PTR_FIRST = 0x10000,
CPUINFO_PTR_SET_INFO = CPUINFO_PTR_FIRST, /* R/O: void (*set_info)(UINT32 state, INT64 data, void *ptr) */
CPUINFO_PTR_GET_CONTEXT, /* R/O: void (*get_context)(void *buffer) */
CPUINFO_PTR_SET_CONTEXT, /* R/O: void (*set_context)(void *buffer) */
CPUINFO_PTR_INIT, /* R/O: void (*init)(void) */
CPUINFO_PTR_RESET, /* R/O: void (*reset)(void *param) */
CPUINFO_PTR_EXIT, /* R/O: void (*exit)(void) */
CPUINFO_PTR_EXECUTE, /* R/O: int (*execute)(int cycles) */
CPUINFO_PTR_BURN, /* R/O: void (*burn)(int cycles) */
CPUINFO_PTR_DISASSEMBLE, /* R/O: void (*disassemble)(char *buffer, offs_t pc) */
CPUINFO_PTR_IRQ_CALLBACK, /* R/W: int (*irqcallback)(int state) */
CPUINFO_PTR_INSTRUCTION_COUNTER, /* R/O: int *icount */
CPUINFO_PTR_REGISTER_LAYOUT, /* R/O: struct debug_register_layout *layout */
CPUINFO_PTR_WINDOW_LAYOUT, /* R/O: struct debug_window_layout *layout */
CPUINFO_PTR_INTERNAL_MEMORY_MAP, /* R/O: construct_map_t map */
CPUINFO_PTR_INTERNAL_MEMORY_MAP_LAST = CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACES - 1,
CPUINFO_PTR_DEBUG_REGISTER_LIST, /* R/O: int *list: list of registers for NEW_DEBUGGER */
CPUINFO_PTR_CPU_SPECIFIC = 0x18000, /* R/W: CPU-specific values start here */
/* --- the following bits of info are returned as NULL-terminated strings --- */
CPUINFO_STR_FIRST = 0x20000,
CPUINFO_STR_NAME = CPUINFO_STR_FIRST, /* R/O: name of the CPU */
CPUINFO_STR_CORE_FAMILY, /* R/O: family of the CPU */
CPUINFO_STR_CORE_VERSION, /* R/O: version of the CPU core */
CPUINFO_STR_CORE_FILE, /* R/O: file containing the CPU core */
CPUINFO_STR_CORE_CREDITS, /* R/O: credits for the CPU core */
CPUINFO_STR_FLAGS, /* R/O: string representation of the main flags value */
CPUINFO_STR_REGISTER, /* R/O: string representation of up to MAX_REGs registers */
CPUINFO_STR_REGISTER_LAST = CPUINFO_STR_REGISTER + MAX_REGS - 1,
CPUINFO_STR_CPU_SPECIFIC = 0x28000 /* R/W: CPU-specific values start here */
};
#endif /* CPUINTRF_H */

View file

@ -1,463 +0,0 @@
/*
Audio Overload SDK - PSF file format engine
Copyright (c) 2007 R. Belmont and Richard Bannister.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ao.h"
#include "eng_protos.h"
#include "cpuintrf.h"
#include "psx.h"
#include "peops/stdafx.h"
#include "peops/externals.h"
#include "peops/regs.h"
#include "peops/registers.h"
#include "peops/spu.h"
#include "corlett.h"
#define DEBUG_LOADER (0)
static corlett_t *c = NULL;
static char psfby[256];
char *spu_pOutput;
int psf_refresh = -1;
// main RAM
extern uint32 psx_ram[((2*1024*1024)/4)+4];
extern uint32 psx_scratch[0x400];
extern uint32 initial_ram[((2*1024*1024)/4)+4];
extern uint32 initial_scratch[0x400];
static uint32 initialPC, initialGP, initialSP;
extern void mips_init( void );
extern void mips_reset( void *param );
extern int mips_execute( int cycles );
extern void mips_set_info(UINT32 state, union cpuinfo *info);
extern void psx_hw_init(void);
extern void psx_hw_slice(void);
extern void psx_hw_frame(void);
extern void setlength(int32 stop, int32 fade);
int32 psf_start(uint8 *buffer, uint32 length)
{
uint8 *file, *lib_decoded, *lib_raw_file, *alib_decoded;
uint32 offset, plength, PC, SP, GP, lengthMS, fadeMS;
uint64 file_len, lib_len, lib_raw_length, alib_len;
corlett_t *lib;
int i;
union cpuinfo mipsinfo;
// clear PSX work RAM before we start scribbling in it
memset(psx_ram, 0, 2*1024*1024);
// printf("Length = %d\n", length);
// Decode the current GSF
if (corlett_decode(buffer, length, &file, &file_len, &c) != AO_SUCCESS)
{
return AO_FAIL;
}
// printf("file_len %d reserve %d\n", file_len, c->res_size);
// check for PSX EXE signature
if (strncmp((char *)file, "PS-X EXE", 8))
{
return AO_FAIL;
}
#if DEBUG_LOADER
offset = file[0x18] | file[0x19]<<8 | file[0x1a]<<16 | file[0x1b]<<24;
printf("Text section start: %x\n", offset);
offset = file[0x1c] | file[0x1d]<<8 | file[0x1e]<<16 | file[0x1f]<<24;
printf("Text section size: %x\n", offset);
printf("Region: [%s]\n", &file[0x4c]);
printf("refresh: [%s]\n", c->inf_refresh);
#endif
if (c->inf_refresh[0] == '5')
{
psf_refresh = 50;
}
if (c->inf_refresh[0] == '6')
{
psf_refresh = 60;
}
PC = file[0x10] | file[0x11]<<8 | file[0x12]<<16 | file[0x13]<<24;
GP = file[0x14] | file[0x15]<<8 | file[0x16]<<16 | file[0x17]<<24;
SP = file[0x30] | file[0x31]<<8 | file[0x32]<<16 | file[0x33]<<24;
#if DEBUG_LOADER
printf("Top level: PC %x GP %x SP %x\n", PC, GP, SP);
#endif
// Get the library file, if any
if (c->lib[0] != 0)
{
uint64 tmp_length;
#if DEBUG_LOADER
printf("Loading library: %s\n", c->lib);
#endif
if (ao_get_lib(c->lib, &lib_raw_file, &tmp_length) != AO_SUCCESS)
{
return AO_FAIL;
}
lib_raw_length = tmp_length;
if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS)
{
free(lib_raw_file);
return AO_FAIL;
}
// Free up raw file
free(lib_raw_file);
if (strncmp((char *)lib_decoded, "PS-X EXE", 8))
{
printf("Major error! PSF was OK, but referenced library is not!\n");
free(lib);
return AO_FAIL;
}
#if DEBUG_LOADER
offset = lib_decoded[0x18] | lib_decoded[0x19]<<8 | lib_decoded[0x1a]<<16 | lib_decoded[0x1b]<<24;
printf("Text section start: %x\n", offset);
offset = lib_decoded[0x1c] | lib_decoded[0x1d]<<8 | lib_decoded[0x1e]<<16 | lib_decoded[0x1f]<<24;
printf("Text section size: %x\n", offset);
printf("Region: [%s]\n", &lib_decoded[0x4c]);
printf("refresh: [%s]\n", lib->inf_refresh);
#endif
// if the original file had no refresh tag, give the lib a shot
if (psf_refresh == -1)
{
if (lib->inf_refresh[0] == '5')
{
psf_refresh = 50;
}
if (lib->inf_refresh[0] == '6')
{
psf_refresh = 60;
}
}
PC = lib_decoded[0x10] | lib_decoded[0x11]<<8 | lib_decoded[0x12]<<16 | lib_decoded[0x13]<<24;
GP = lib_decoded[0x14] | lib_decoded[0x15]<<8 | lib_decoded[0x16]<<16 | lib_decoded[0x17]<<24;
SP = lib_decoded[0x30] | lib_decoded[0x31]<<8 | lib_decoded[0x32]<<16 | lib_decoded[0x33]<<24;
#if DEBUG_LOADER
printf("Library: PC %x GP %x SP %x\n", PC, GP, SP);
#endif
// now patch the file into RAM
offset = lib_decoded[0x18] | lib_decoded[0x19]<<8 | lib_decoded[0x1a]<<16 | lib_decoded[0x1b]<<24;
offset &= 0x3fffffff; // kill any MIPS cache segment indicators
plength = lib_decoded[0x1c] | lib_decoded[0x1d]<<8 | lib_decoded[0x1e]<<16 | lib_decoded[0x1f]<<24;
#if DEBUG_LOADER
printf("library offset: %x plength: %d\n", offset, plength);
#endif
memcpy(&psx_ram[offset/4], lib_decoded+2048, plength);
// Dispose the corlett structure for the lib - we don't use it
free(lib);
free(lib_decoded);
}
// now patch the main file into RAM OVER the libraries (but not the aux lib)
offset = file[0x18] | file[0x19]<<8 | file[0x1a]<<16 | file[0x1b]<<24;
offset &= 0x3fffffff; // kill any MIPS cache segment indicators
plength = file[0x1c] | file[0x1d]<<8 | file[0x1e]<<16 | file[0x1f]<<24;
// Philosoma has an illegal "plength". *sigh*
if (plength > (file_len-2048))
{
plength = file_len-2048;
}
memcpy(&psx_ram[offset/4], file+2048, plength);
// load any auxiliary libraries now
for (i = 0; i < 8; i++)
{
if (c->libaux[i][0] != 0)
{
uint64 tmp_length;
#if DEBUG_LOADER
printf("Loading aux library: %s\n", c->libaux[i]);
#endif
if (ao_get_lib(c->libaux[i], &lib_raw_file, &tmp_length) != AO_SUCCESS)
{
return AO_FAIL;
}
lib_raw_length = tmp_length;
if (corlett_decode(lib_raw_file, lib_raw_length, &alib_decoded, &alib_len, &lib) != AO_SUCCESS)
{
free(lib_raw_file);
return AO_FAIL;
}
// Free up raw file
free(lib_raw_file);
if (strncmp((char *)alib_decoded, "PS-X EXE", 8))
{
printf("Major error! PSF was OK, but referenced library is not!\n");
free(lib);
return AO_FAIL;
}
#if DEBUG_LOADER
offset = alib_decoded[0x18] | alib_decoded[0x19]<<8 | alib_decoded[0x1a]<<16 | alib_decoded[0x1b]<<24;
printf("Text section start: %x\n", offset);
offset = alib_decoded[0x1c] | alib_decoded[0x1d]<<8 | alib_decoded[0x1e]<<16 | alib_decoded[0x1f]<<24;
printf("Text section size: %x\n", offset);
printf("Region: [%s]\n", &alib_decoded[0x4c]);
#endif
// now patch the file into RAM
offset = alib_decoded[0x18] | alib_decoded[0x19]<<8 | alib_decoded[0x1a]<<16 | alib_decoded[0x1b]<<24;
offset &= 0x3fffffff; // kill any MIPS cache segment indicators
plength = alib_decoded[0x1c] | alib_decoded[0x1d]<<8 | alib_decoded[0x1e]<<16 | alib_decoded[0x1f]<<24;
memcpy(&psx_ram[offset/4], alib_decoded+2048, plength);
// Dispose the corlett structure for the lib - we don't use it
free(lib);
free(alib_decoded);
}
}
free(file);
// Finally, set psfby tag
strcpy(psfby, "n/a");
if (c)
{
int i;
for (i = 0; i < MAX_UNKNOWN_TAGS; i++)
{
if (!strcasecmp(c->tag_name[i], "psfby"))
strcpy(psfby, c->tag_data[i]);
}
}
mips_init();
mips_reset(NULL);
// set the initial PC, SP, GP
#if DEBUG_LOADER
printf("Initial PC %x, GP %x, SP %x\n", PC, GP, SP);
printf("Refresh = %d\n", psf_refresh);
#endif
mipsinfo.i = PC;
mips_set_info(CPUINFO_INT_PC, &mipsinfo);
// set some reasonable default for the stack
if (SP == 0)
{
SP = 0x801fff00;
}
mipsinfo.i = SP;
mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);
mipsinfo.i = GP;
mips_set_info(CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo);
#if DEBUG_LOADER && 1
{
FILE *f;
f = fopen("psxram.bin", "wb");
fwrite(psx_ram, 2*1024*1024, 1, f);
fclose(f);
}
#endif
psx_hw_init();
SPUinit();
SPUopen();
lengthMS = psfTimeToMS(c->inf_length);
fadeMS = psfTimeToMS(c->inf_fade);
#if DEBUG_LOADER
printf("length %d fade %d\n", lengthMS, fadeMS);
#endif
if (lengthMS == 0)
{
lengthMS = ~0;
}
setlength(lengthMS, fadeMS);
// patch illegal Chocobo Dungeon 2 code - CaitSith2 put a jump in the delay slot from a BNE
// and rely on Highly Experimental's buggy-ass CPU to rescue them. Verified on real hardware
// that the initial code is wrong.
if (c->inf_game)
{
if (!strcmp(c->inf_game, "Chocobo Dungeon 2"))
{
if (psx_ram[0xbc090/4] == LE32(0x0802f040))
{
psx_ram[0xbc090/4] = LE32(0);
psx_ram[0xbc094/4] = LE32(0x0802f040);
psx_ram[0xbc098/4] = LE32(0);
}
}
}
// psx_ram[0x118b8/4] = LE32(0); // crash 2 hack
// backup the initial state for restart
memcpy(initial_ram, psx_ram, 2*1024*1024);
memcpy(initial_scratch, psx_scratch, 0x400);
initialPC = PC;
initialGP = GP;
initialSP = SP;
mips_execute(5000);
return AO_SUCCESS;
}
void spu_update(unsigned char* pSound,long lBytes)
{
memcpy(spu_pOutput, pSound, lBytes);
}
int32 psf_gen(int16 *buffer, uint32 samples)
{
int i;
for (i = 0; i < samples; i++)
{
psx_hw_slice();
SPUasync(384);
}
spu_pOutput = (char *)buffer;
SPU_flushboot();
psx_hw_frame();
return AO_SUCCESS;
}
int32 psf_stop(void)
{
SPUclose();
free(c);
return AO_SUCCESS;
}
int32 psf_command(int32 command, int32 parameter)
{
union cpuinfo mipsinfo;
uint32 lengthMS, fadeMS;
switch (command)
{
case COMMAND_RESTART:
SPUclose();
memcpy(psx_ram, initial_ram, 2*1024*1024);
memcpy(psx_scratch, initial_scratch, 0x400);
mips_init();
mips_reset(NULL);
psx_hw_init();
SPUinit();
SPUopen();
lengthMS = psfTimeToMS(c->inf_length);
fadeMS = psfTimeToMS(c->inf_fade);
if (lengthMS == 0)
{
lengthMS = ~0;
}
setlength(lengthMS, fadeMS);
mipsinfo.i = initialPC;
mips_set_info(CPUINFO_INT_PC, &mipsinfo);
mipsinfo.i = initialSP;
mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);
mipsinfo.i = initialGP;
mips_set_info(CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo);
mips_execute(5000);
return AO_SUCCESS;
}
return AO_FAIL;
}
int32 psf_fill_info(ao_display_info *info)
{
if (c == NULL)
return AO_FAIL;
strcpy(info->title[1], "Name: ");
sprintf(info->info[1], "%s", c->inf_title);
strcpy(info->title[2], "Game: ");
sprintf(info->info[2], "%s", c->inf_game);
strcpy(info->title[3], "Artist: ");
sprintf(info->info[3], "%s", c->inf_artist);
strcpy(info->title[4], "Copyright: ");
sprintf(info->info[4], "%s", c->inf_copy);
strcpy(info->title[5], "Year: ");
sprintf(info->info[5], "%s", c->inf_year);
strcpy(info->title[6], "Length: ");
sprintf(info->info[6], "%s", c->inf_length);
strcpy(info->title[7], "Fade: ");
sprintf(info->info[7], "%s", c->inf_fade);
strcpy(info->title[8], "Ripper: ");
sprintf(info->info[8], "%s", psfby);
return AO_SUCCESS;
}

View file

@ -1,717 +0,0 @@
/*
Audio Overload SDK - PSF2 file format engine
Copyright (c) 2007-2008 R. Belmont and Richard Bannister.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//
// Audio Overload
// Emulated music player
//
// (C) 2000-2008 Richard F. Bannister
//
//
// eng_psf2.c
//
// References:
// psf_format.txt v1.6 by Neill Corlett (filesystem and decompression info)
// Intel ELF format specs ELF.PS (general ELF parsing info)
// http://ps2dev.org/kb.x?T=457 (IRX relocation and inter-module call info)
// http://ps2dev.org/ (the whole site - lots of IOP info)
// spu2regs.txt (comes with SexyPSF source: IOP hardware info)
// 64-bit ELF Object File Specification: http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf (MIPS ELF relocation types)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <zlib.h>
#include "ao.h"
#include "eng_protos.h"
#include "cpuintrf.h"
#include "psx.h"
#include "peops2/stdafx.h"
#include "peops2/externals.h"
#include "peops2/regs.h"
#include "peops2/registers.h"
#include "peops2/spu.h"
#include "corlett.h"
#define DEBUG_LOADER (0)
#define MAX_FS (32) // maximum # of filesystems (libs and subdirectories)
// ELF relocation helpers
#define ELF32_R_SYM(val) ((val) >> 8)
#define ELF32_R_TYPE(val) ((val) & 0xff)
static corlett_t *c = NULL;
static char psfby[256];
static char *spu_pOutput;
// main RAM
extern uint32 psx_ram[(2*1024*1024)/4];
extern uint32 initial_ram[(2*1024*1024)/4];
static uint32 initialPC, initialSP;
static uint32 loadAddr, lengthMS, fadeMS;
static uint8 *filesys[MAX_FS];
static uint8 *lib_raw_file;
static uint32 fssize[MAX_FS];
static int num_fs;
extern void mips_init( void );
extern void mips_reset( void *param );
extern int mips_execute( int cycles );
extern void mips_set_info(UINT32 state, union cpuinfo *info);
extern void psx_hw_init(void);
extern void ps2_hw_slice(void);
extern void ps2_hw_frame(void);
extern void setlength2(int32 stop, int32 fade);
static uint32 secname(uint8 *start, uint32 strndx, uint32 shoff, uint32 shentsize, uint32 name)
{
uint32 offset, shent;
// get string table section
shent = shoff + (shentsize * strndx);
// find the offset to the section
offset = start[shent+16] | start[shent+17]<<8 | start[shent+18]<<16 | start[shent+19]<<24;
offset += name;
return offset;
}
static void do_iopmod(uint8 *start, uint32 offset)
{
uint32 nameoffs, saddr, heap, tsize, dsize, bsize, vers2;
nameoffs = start[offset] | start[offset+1]<<8 | start[offset+2]<<16 | start[offset+3]<<24;
saddr = start[offset+4] | start[offset+5]<<8 | start[offset+6]<<16 | start[offset+7]<<24;
heap = start[offset+8] | start[offset+9]<<8 | start[offset+10]<<16 | start[offset+11]<<24;
tsize = start[offset+12] | start[offset+13]<<8 | start[offset+14]<<16 | start[offset+15]<<24;
dsize = start[offset+16] | start[offset+17]<<8 | start[offset+18]<<16 | start[offset+19]<<24;
bsize = start[offset+20] | start[offset+21]<<8 | start[offset+22]<<16 | start[offset+23]<<24;
vers2 = start[offset+24] | start[offset+25]<<8;
// printf("nameoffs %08x saddr %08x heap %08x tsize %08x dsize %08x bsize %08x\n", nameoffs, saddr, heap, tsize, dsize, bsize);
#if DEBUG_LOADER
printf("vers: %04x name [%s]\n", vers2, &start[offset+26]);
#endif
}
uint32 psf2_load_elf(uint8 *start, uint32 len)
{
uint32 entry, phoff, shoff, phentsize, shentsize, phnum, shnum, shstrndx;
uint32 name, type, flags, addr, offset, size, shent;
uint32 totallen;
int i, rec;
// FILE *f;
if (loadAddr & 3)
{
loadAddr &= ~3;
loadAddr += 4;
}
#if DEBUG_LOADER
printf("psf2_load_elf: starting at %08x\n", loadAddr | 0x80000000);
#endif
if ((start[0] != 0x7f) || (start[1] != 'E') || (start[2] != 'L') || (start[3] != 'F'))
{
printf("Not an ELF file\n");
return 0xffffffff;
}
entry = start[24] | start[25]<<8 | start[26]<<16 | start[27]<<24; // 0x18
phoff = start[28] | start[29]<<8 | start[30]<<16 | start[31]<<24; // 0x1c
shoff = start[32] | start[33]<<8 | start[34]<<16 | start[35]<<24; // 0x20
// printf("Entry: %08x phoff %08x shoff %08x\n", entry, phoff, shoff);
phentsize = start[42] | start[43]<<8; // 0x2a
phnum = start[44] | start[45]<<8; // 0x2c
shentsize = start[46] | start[47]<<8; // 0x2e
shnum = start[48] | start[49]<<8; // 0x30
shstrndx = start[50] | start[51]<<8; // 0x32
// printf("phentsize %08x phnum %d shentsize %08x shnum %d shstrndx %d\n", phentsize, phnum, shentsize, shnum, shstrndx);
// process ELF sections
shent = shoff;
totallen = 0;
for (i = 0; i < shnum; i++)
{
name = start[shent] | start[shent+1]<<8 | start[shent+2]<<16 | start[shent+3]<<24;
type = start[shent+4] | start[shent+5]<<8 | start[shent+6]<<16 | start[shent+7]<<24;
flags = start[shent+8] | start[shent+9]<<8 | start[shent+10]<<16 | start[shent+11]<<24;
addr = start[shent+12] | start[shent+13]<<8 | start[shent+14]<<16 | start[shent+15]<<24;
offset = start[shent+16] | start[shent+17]<<8 | start[shent+18]<<16 | start[shent+19]<<24;
size = start[shent+20] | start[shent+21]<<8 | start[shent+22]<<16 | start[shent+23]<<24;
// printf("Section %02d: name %08x [%s] type %08x flags %08x addr %08x offset %08x size %08x\n", i, name, &start[secname(start, shstrndx, shoff, shentsize, name)], type, flags, addr, offset, size);
switch (type)
{
case 0: // section table header - do nothing
break;
case 1: // PROGBITS: copy data to destination
memcpy(&psx_ram[(loadAddr + addr)/4], &start[offset], size);
totallen += size;
break;
case 2: // SYMTAB: ignore
break;
case 3: // STRTAB: ignore
break;
case 8: // NOBITS: BSS region, zero out destination
memset(&psx_ram[(loadAddr + addr)/4], 0, size);
totallen += size;
break;
case 9: // REL: short relocation data
for (rec = 0; rec < (size/8); rec++)
{
uint32 offs, info, target, temp, val, vallo;
static uint32 hi16offs = 0, hi16target = 0;
offs = start[offset+(rec*8)] | start[offset+1+(rec*8)]<<8 | start[offset+2+(rec*8)]<<16 | start[offset+3+(rec*8)]<<24;
info = start[offset+4+(rec*8)] | start[offset+5+(rec*8)]<<8 | start[offset+6+(rec*8)]<<16 | start[offset+7+(rec*8)]<<24;
target = LE32(psx_ram[(loadAddr+offs)/4]);
// printf("[%04d] offs %08x type %02x info %08x => %08x\n", rec, offs, ELF32_R_TYPE(info), ELF32_R_SYM(info), target);
switch (ELF32_R_TYPE(info))
{
case 2: // R_MIPS_32
target += loadAddr;
// target |= 0x80000000;
break;
case 4: // R_MIPS_26
temp = (target & 0x03ffffff);
target &= 0xfc000000;
temp += (loadAddr>>2);
target |= temp;
break;
case 5: // R_MIPS_HI16
hi16offs = offs;
hi16target = target;
break;
case 6: // R_MIPS_LO16
vallo = ((target & 0xffff) ^ 0x8000) - 0x8000;
val = ((hi16target & 0xffff) << 16) + vallo;
val += loadAddr;
// val |= 0x80000000;
/* Account for the sign extension that will happen in the low bits. */
val = ((val >> 16) + ((val & 0x8000) != 0)) & 0xffff;
hi16target = (hi16target & ~0xffff) | val;
/* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
val = loadAddr + vallo;
target = (target & ~0xffff) | (val & 0xffff);
psx_ram[(loadAddr+hi16offs)/4] = LE32(hi16target);
break;
default:
printf("FATAL: Unknown MIPS ELF relocation!\n");
return 0xffffffff;
break;
}
psx_ram[(loadAddr+offs)/4] = LE32(target);
}
break;
case 0x70000080: // .iopmod
do_iopmod(start, offset);
break;
default:
#if DEBUG_LOADER
printf("Unhandled ELF section type %d\n", type);
#endif
break;
}
shent += shentsize;
}
entry += loadAddr;
entry |= 0x80000000;
loadAddr += totallen;
#if DEBUG_LOADER
printf("psf2_load_elf: entry PC %08x\n", entry);
#endif
return entry;
}
static uint32 load_file_ex(uint8 *top, uint8 *start, uint32 len, char *file, uint8 *buf, uint32 buflen)
{
int32 numfiles, i, j;
uint8 *cptr;
uint32 offs, uncomp, bsize, cofs, uofs;
uint32 X;
uLongf dlength;
int uerr;
char matchname[512], *remainder;
// strip out to only the directory name
i = 0;
while ((file[i] != '/') && (file[i] != '\\') && (file[i] != '\0'))
{
matchname[i] = file[i];
i++;
}
matchname[i] = '\0';
remainder = &file[i+1];
cptr = start + 4;
numfiles = start[0] | start[1]<<8 | start[2]<<16 | start[3]<<24;
for (i = 0; i < numfiles; i++)
{
offs = cptr[36] | cptr[37]<<8 | cptr[38]<<16 | cptr[39]<<24;
uncomp = cptr[40] | cptr[41]<<8 | cptr[42]<<16 | cptr[43]<<24;
bsize = cptr[44] | cptr[45]<<8 | cptr[46]<<16 | cptr[47]<<24;
#if DEBUG_LOADER
printf("[%s vs %s]: ofs %08x uncomp %08x bsize %08x\n", cptr, matchname, offs, uncomp, bsize);
#endif
if (!strcasecmp((char *)cptr, matchname))
{
if ((uncomp == 0) && (bsize == 0))
{
#if DEBUG_LOADER
printf("Drilling into subdirectory [%s] with [%s] at offset %x\n", matchname, remainder, offs);
#endif
return load_file_ex(top, &top[offs], len-offs, remainder, buf, buflen);
}
X = (uncomp + bsize - 1) / bsize;
cofs = offs + (X*4);
uofs = 0;
for (j = 0; j < X; j++)
{
uint32 usize;
usize = top[offs+(j*4)] | top[offs+1+(j*4)]<<8 | top[offs+2+(j*4)]<<16 | top[offs+3+(j*4)]<<24;
dlength = buflen - uofs;
uerr = uncompress(&buf[uofs], &dlength, &top[cofs], usize);
if (uerr != Z_OK)
{
printf("Decompress fail: %x %d!\n", dlength, uerr);
return 0xffffffff;
}
cofs += usize;
uofs += dlength;
}
return uncomp;
}
else
{
cptr += 48;
}
}
return 0xffffffff;
}
static uint32 load_file(int fs, char *file, uint8 *buf, uint32 buflen)
{
return load_file_ex(filesys[fs], filesys[fs], fssize[fs], file, buf, buflen);
}
#if 0
static dump_files(int fs, uint8 *buf, uint32 buflen)
{
int32 numfiles, i, j;
uint8 *cptr;
uint32 offs, uncomp, bsize, cofs, uofs;
uint32 X;
uLongf dlength;
int uerr;
uint8 *start;
uint32 len;
FILE *f;
char tfn[128];
printf("Dumping FS %d\n", fs);
start = filesys[fs];
len = fssize[fs];
cptr = start + 4;
numfiles = start[0] | start[1]<<8 | start[2]<<16 | start[3]<<24;
for (i = 0; i < numfiles; i++)
{
offs = cptr[36] | cptr[37]<<8 | cptr[38]<<16 | cptr[39]<<24;
uncomp = cptr[40] | cptr[41]<<8 | cptr[42]<<16 | cptr[43]<<24;
bsize = cptr[44] | cptr[45]<<8 | cptr[46]<<16 | cptr[47]<<24;
if (bsize > 0)
{
X = (uncomp + bsize - 1) / bsize;
printf("[dump %s]: ofs %08x uncomp %08x bsize %08x\n", cptr, offs, uncomp, bsize);
cofs = offs + (X*4);
uofs = 0;
for (j = 0; j < X; j++)
{
uint32 usize;
usize = start[offs+(j*4)] | start[offs+1+(j*4)]<<8 | start[offs+2+(j*4)]<<16 | start[offs+3+(j*4)]<<24;
dlength = buflen - uofs;
uerr = uncompress(&buf[uofs], &dlength, &start[cofs], usize);
if (uerr != Z_OK)
{
printf("Decompress fail: %x %d!\n", dlength, uerr);
return 0xffffffff;
}
cofs += usize;
uofs += dlength;
}
sprintf(tfn, "iopfiles/%s", cptr);
f = fopen(tfn, "wb");
fwrite(buf, uncomp, 1, f);
fclose(f);
}
else
{
printf("[subdir %s]: ofs %08x uncomp %08x bsize %08x\n", cptr, offs, uncomp, bsize);
}
cptr += 48;
}
return 0xffffffff;
}
#endif
// find a file on our filesystems
uint32 psf2_load_file(char *file, uint8 *buf, uint32 buflen)
{
int i;
uint32 flen;
for (i = 0; i < num_fs; i++)
{
flen = load_file(i, file, buf, buflen);
if (flen != 0xffffffff)
{
return flen;
}
}
return 0xffffffff;
}
int32 psf2_start(uint8 *buffer, uint32 length)
{
uint8 *file, *lib_decoded;
uint32 irx_len;
uint64 file_len, lib_raw_length, lib_len;
uint8 *buf;
union cpuinfo mipsinfo;
corlett_t *lib;
loadAddr = 0x23f00; // this value makes allocations work out similarly to how they would
// in Highly Experimental (as per Shadow Hearts' hard-coded assumptions)
// clear IOP work RAM before we start scribbling in it
memset(psx_ram, 0, 2*1024*1024);
// Decode the current PSF2
if (corlett_decode(buffer, length, &file, &file_len, &c) != AO_SUCCESS)
{
return AO_FAIL;
}
if (file_len > 0) printf("ERROR: PSF2 can't have a program section! ps %08x\n", file_len);
#if DEBUG_LOADER
printf("FS section: size %x\n", c->res_size);
#endif
num_fs = 1;
filesys[0] = (uint8 *)c->res_section;
fssize[0] = c->res_size;
// Get the library file, if any
if (c->lib[0] != 0)
{
uint64 tmp_length;
#if DEBUG_LOADER
printf("Loading library: %s\n", c->lib);
#endif
if (ao_get_lib(c->lib, &lib_raw_file, &tmp_length) != AO_SUCCESS)
{
return AO_FAIL;
}
lib_raw_length = tmp_length;
if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS)
{
free(lib_raw_file);
return AO_FAIL;
}
free(lib_raw_file);
#if DEBUG_LOADER
printf("Lib FS section: size %x bytes\n", lib->res_size);
#endif
num_fs++;
filesys[1] = (uint8 *)lib->res_section;
fssize[1] = lib->res_size;
}
// dump all files
#if 0
buf = (uint8 *)malloc(16*1024*1024);
dump_files(0, buf, 16*1024*1024);
if (c->lib[0] != 0)
dump_files(1, buf, 16*1024*1024);
free(buf);
#endif
// load psf2.irx, which kicks everything off
buf = (uint8 *)malloc(512*1024);
irx_len = psf2_load_file("psf2.irx", buf, 512*1024);
if (irx_len != 0xffffffff)
{
initialPC = psf2_load_elf(buf, irx_len);
initialSP = 0x801ffff0;
}
free(buf);
if (initialPC == 0xffffffff)
{
return AO_FAIL;
}
lengthMS = psfTimeToMS(c->inf_length);
fadeMS = psfTimeToMS(c->inf_fade);
if (lengthMS == 0)
{
lengthMS = ~0;
}
setlength2(lengthMS, fadeMS);
mips_init();
mips_reset(NULL);
mipsinfo.i = initialPC;
mips_set_info(CPUINFO_INT_PC, &mipsinfo);
mipsinfo.i = initialSP;
mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);
// set RA
mipsinfo.i = 0x80000000;
mips_set_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
// set A0 & A1 to point to "aofile:/"
mipsinfo.i = 2; // argc
mips_set_info(CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo);
mipsinfo.i = 0x80000004; // argv
mips_set_info(CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo);
psx_ram[1] = LE32(0x80000008);
buf = (uint8 *)&psx_ram[2];
strcpy((char *)buf, "aofile:/");
psx_ram[0] = LE32(FUNCT_HLECALL);
// back up initial RAM image to quickly restart songs
memcpy(initial_ram, psx_ram, 2*1024*1024);
psx_hw_init();
SPU2init();
SPU2open(NULL);
return AO_SUCCESS;
}
void ps2_update(unsigned char *pSound, long lBytes)
{
memcpy(spu_pOutput, pSound, lBytes); // (for direct 44.1kHz output)
}
int32 psf2_gen(int16 *buffer, uint32 samples)
{
int i;
spu_pOutput = (char *)buffer;
for (i = 0; i < samples; i++)
{
SPU2async(1);
ps2_hw_slice();
}
ps2_hw_frame();
return AO_SUCCESS;
}
int32 psf2_stop(void)
{
SPU2close();
if (c->lib[0] != 0)
{
free(lib_raw_file);
}
free(c);
return AO_SUCCESS;
}
int32 psf2_command(int32 command, int32 parameter)
{
union cpuinfo mipsinfo;
uint32 lengthMS, fadeMS;
switch (command)
{
case COMMAND_RESTART:
SPU2close();
memcpy(psx_ram, initial_ram, 2*1024*1024);
mips_init();
mips_reset(NULL);
psx_hw_init();
SPU2init();
SPU2open(NULL);
mipsinfo.i = initialPC;
mips_set_info(CPUINFO_INT_PC, &mipsinfo);
mipsinfo.i = initialSP;
mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);
// set RA
mipsinfo.i = 0x80000000;
mips_set_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
// set A0 & A1 to point to "aofile:/"
mipsinfo.i = 2; // argc
mips_set_info(CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo);
mipsinfo.i = 0x80000004; // argv
mips_set_info(CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo);
psx_hw_init();
lengthMS = psfTimeToMS(c->inf_length);
fadeMS = psfTimeToMS(c->inf_fade);
if (lengthMS == 0)
{
lengthMS = ~0;
}
setlength2(lengthMS, fadeMS);
return AO_SUCCESS;
}
return AO_FAIL;
}
int32 psf2_fill_info(ao_display_info *info)
{
if (c == NULL)
return AO_FAIL;
strcpy(info->title[1], "Name: ");
sprintf(info->info[1], "%s", c->inf_title);
strcpy(info->title[2], "Game: ");
sprintf(info->info[2], "%s", c->inf_game);
strcpy(info->title[3], "Artist: ");
sprintf(info->info[3], "%s", c->inf_artist);
strcpy(info->title[4], "Copyright: ");
sprintf(info->info[4], "%s", c->inf_copy);
strcpy(info->title[5], "Year: ");
sprintf(info->info[5], "%s", c->inf_year);
strcpy(info->title[6], "Length: ");
sprintf(info->info[6], "%s", c->inf_length);
strcpy(info->title[7], "Fade: ");
sprintf(info->info[7], "%s", c->inf_fade);
strcpy(info->title[8], "Ripper: ");
sprintf(info->info[8], "%s", psfby);
return AO_SUCCESS;
}
uint32 psf2_get_loadaddr(void)
{
return loadAddr;
}
void psf2_set_loadaddr(uint32 new)
{
loadAddr = new;
}

View file

@ -1,319 +0,0 @@
/*
Audio Overload SDK - SPU file format engine
Copyright (c) 2007 R. Belmont and Richard Bannister.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//
// eng_spu.c
//
// Note: support for old-format files is not tested and may not work. All the rips I could find
// are in the newer format. Also, CDDA and XA commands do not work - I've not found a rip using them.
//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ao.h"
#include "eng_protos.h"
#include "cpuintrf.h"
#include "psx.h"
extern int SPUinit(void);
extern int SPUopen(void);
extern int SPUclose(void);
extern void SPUinjectRAMImage(unsigned short *source);
static uint8 *start_of_file, *song_ptr;
static uint32 cur_tick, cur_event, num_events, next_tick, end_tick;
static int old_fmt;
static char name[128], song[128], company[128];
int32 spu_start(uint8 *buffer, uint32 length)
{
int i;
uint16 reg;
if (strncmp((char *)buffer, "SPU", 3))
{
return AO_FAIL;
}
start_of_file = buffer;
SPUinit();
SPUopen();
setlength(~0, 0);
// upload the SPU RAM image
SPUinjectRAMImage((unsigned short *)&buffer[0]);
// apply the register image
for (i = 0; i < 512; i += 2)
{
reg = buffer[0x80000+i] | buffer[0x80000+i+1]<<8;
SPUwriteRegister((i/2)+0x1f801c00, reg);
}
old_fmt = 1;
if ((buffer[0x80200] != 0x44) || (buffer[0x80201] != 0xac) || (buffer[0x80202] != 0x00) || (buffer[0x80203] != 0x00))
{
old_fmt = 0;
}
if (old_fmt)
{
num_events = buffer[0x80204] | buffer[0x80205]<<8 | buffer[0x80206]<<16 | buffer[0x80207]<<24;
if (((num_events * 12) + 0x80208) > length)
{
old_fmt = 0;
}
else
{
cur_tick = 0;
}
}
if (!old_fmt)
{
end_tick = buffer[0x80200] | buffer[0x80201]<<8 | buffer[0x80202]<<16 | buffer[0x80203]<<24;
cur_tick = buffer[0x80204] | buffer[0x80205]<<8 | buffer[0x80206]<<16 | buffer[0x80207]<<24;
next_tick = cur_tick;
}
song_ptr = &buffer[0x80208];
cur_event = 0;
strncpy((char *)&buffer[4], name, 128);
strncpy((char *)&buffer[0x44], song, 128);
strncpy((char *)&buffer[0x84], company, 128);
return AO_SUCCESS;
}
extern int SPUasync(uint32 cycles);
extern void SPU_flushboot(void);
extern char *spu_pOutput; // this is a bit lame, but we'll deal
static void spu_tick(void)
{
uint32 time, reg, size;
uint16 rdata;
uint8 opcode;
if (old_fmt)
{
time = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
while ((time == cur_tick) && (cur_event < num_events))
{
reg = song_ptr[4] | song_ptr[5]<<8 | song_ptr[6]<<16 | song_ptr[7]<<24;
rdata = song_ptr[8] | song_ptr[9]<<8;
SPUwriteRegister(reg, rdata);
cur_event++;
song_ptr += 12;
time = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
}
}
else
{
if (cur_tick < end_tick)
{
while (cur_tick == next_tick)
{
opcode = song_ptr[0];
song_ptr++;
switch (opcode)
{
case 0: // write register
reg = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
rdata = song_ptr[4] | song_ptr[5]<<8;
SPUwriteRegister(reg, rdata);
next_tick = song_ptr[6] | song_ptr[7]<<8 | song_ptr[8]<<16 | song_ptr[9]<<24;
song_ptr += 10;
break;
case 1: // read register
reg = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
SPUreadRegister(reg);
next_tick = song_ptr[4] | song_ptr[5]<<8 | song_ptr[6]<<16 | song_ptr[7]<<24;
song_ptr += 8;
break;
case 2: // dma write
size = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
song_ptr += (4 + size);
next_tick = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
song_ptr += 4;
break;
case 3: // dma read
next_tick = song_ptr[4] | song_ptr[5]<<8 | song_ptr[6]<<16 | song_ptr[7]<<24;
song_ptr += 8;
break;
case 4: // xa play
song_ptr += (32 + 16384);
next_tick = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
song_ptr += 4;
break;
case 5: // cdda play
size = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
song_ptr += (4 + size);
next_tick = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
song_ptr += 4;
break;
default:
printf("Unknown opcode %d\n", opcode);
exit(-1);
break;
}
}
}
else
{
// ao_song_done = 1;
}
}
cur_tick++;
}
int32 spu_gen(int16 *buffer, uint32 samples)
{
int i, run = 1;
if (old_fmt)
{
if (cur_event >= num_events)
{
run = 0;
}
}
else
{
if (cur_tick >= end_tick)
{
run = 0;
}
}
if (run)
{
for (i = 0; i < samples; i++)
{
spu_tick();
SPUasync(384);
}
spu_pOutput = (char *)buffer;
SPU_flushboot();
}
else
{
memset(buffer, 0, samples*2*sizeof(int16));
}
return AO_SUCCESS;
}
int32 spu_stop(void)
{
return AO_SUCCESS;
}
int32 spu_command(int32 command, int32 parameter)
{
switch (command)
{
case COMMAND_GET_MIN:
case COMMAND_GET_MAX:
{
return 0;
}
break;
case COMMAND_HAS_PREV:
case COMMAND_HAS_NEXT:
case COMMAND_PREV:
case COMMAND_NEXT:
case COMMAND_JUMP:
{
return AO_FAIL;
}
break;
case COMMAND_RESTART:
{
song_ptr = &start_of_file[0x80200];
if (old_fmt)
{
num_events = song_ptr[4] | song_ptr[5]<<8 | song_ptr[6]<<16 | song_ptr[7]<<24;
}
else
{
end_tick = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
cur_tick = song_ptr[4] | song_ptr[5]<<8 | song_ptr[6]<<16 | song_ptr[7]<<24;
}
song_ptr += 8;
cur_event = 0;
return AO_SUCCESS;
}
break;
#if VERBOSE
default:
printf("Unknown command executed!\n");
break;
#endif
}
return AO_FAIL;
}
int32 spu_fill_info(ao_display_info *info)
{
strcpy(info->title[1], "Game: ");
sprintf(info->info[1], "%.128s", name);
strcpy(info->title[2], "Song: ");
sprintf(info->info[2], "%.128s", song);
strcpy(info->title[3], "Company: ");
sprintf(info->info[3], "%.128s", company);
return AO_SUCCESS;
}

View file

@ -1,662 +0,0 @@
#ifndef _MEMORY_H
#define _MEMORY_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __GNU__
#define UNUSEDARG __attribute__((__unused__))
#else
#define UNUSEDARG
#endif
#define MAX_BANKS 20
/* obsolete, to be removed */
#define READ_WORD(a) (*(UINT16 *)(a))
#define WRITE_WORD(a,d) (*(UINT16 *)(a) = (d))
#define COMBINE_WORD(w,d) (((w) & ((d) >> 16)) | ((d) & 0xffff))
#define COMBINE_WORD_MEM(a,d) (WRITE_WORD((a), (READ_WORD(a) & ((d) >> 16)) | (d)))
#define ASSERT_LINE (1)
#define CLEAR_LINE (0)
#define TIME_NEVER (0)
#define TIME_IN_HZ(hz) (1.0 / (double)(hz))
#define TIME_IN_MSEC(ms) ((double)(ms) * (1.0 / 1000.0))
#define TIME_IN_USEC(us) ((double)(us) * (1.0 / 1000000.0))
/***************************************************************************
Note that the memory hooks are not passed the actual memory address where
the operation takes place, but the offset from the beginning of the block
they are assigned to. This makes handling of mirror addresses easier, and
makes the handlers a bit more "object oriented". If you handler needs to
read/write the main memory area, provide a "base" pointer: it will be
initialized by the main engine to point to the beginning of the memory block
assigned to the handler. You may also provided a pointer to "size": it
will be set to the length of the memory area processed by the handler.
***************************************************************************/
#define MEMORY_WIDTH_MASK 0x00000003
#define MEMORY_WIDTH_8 0x00000001
#define MEMORY_WIDTH_16 0x00000002
#define MEMORY_WIDTH_32 0x00000003
#define MEMORY_TYPE_MASK 0x30000000
#define MEMORY_TYPE_MEM 0x10000000
#define MEMORY_TYPE_IO 0x20000000
#define MEMORY_DIRECTION_MASK 0xc0000000
#define MEMORY_DIRECTION_READ 0x40000000
#define MEMORY_DIRECTION_WRITE 0x80000000
typedef unsigned int offs_t;
typedef offs_t (*opbase_handler)(UNUSEDARG offs_t address);
/***************************************************************************
8-BIT Core memory read/write/opbase handler types
***************************************************************************/
typedef unsigned char data8_t;
typedef unsigned short data16_t;
typedef data8_t (*mem_read_handler)(UNUSEDARG offs_t offset);
typedef void (*mem_write_handler)(UNUSEDARG offs_t offset, UNUSEDARG data8_t data);
#define READ_HANDLER(name) data8_t name(UNUSEDARG offs_t offset)
#define WRITE_HANDLER(name) void name(UNUSEDARG offs_t offset, UNUSEDARG data8_t data)
#define OPBASE_HANDLER(name) offs_t name(UNUSEDARG offs_t address)
#define READ16_HANDLER(name) data16_t name(UNUSEDARG offs_t offset, UNUSEDARG UINT32 mem_mask)
#define WRITE16_HANDLER(name) void name(UNUSEDARG offs_t offset, UNUSEDARG data16_t data, UNUSEDARG UINT32 mem_mask)
#define OPBASE16_HANDLER(name) offs_t name(UNUSEDARG offs_t address)
#define MRA_NOP 0 /* don't care, return 0 */
#define MWA_NOP 0 /* do nothing */
#define MRA_RAM ((mem_read_handler)-1) /* plain RAM location (return its contents) */
#define MWA_RAM ((mem_write_handler)-1) /* plain RAM location (store the value) */
#define MRA_ROM ((mem_read_handler)-2) /* plain ROM location (return its contents) */
#define MWA_ROM ((mem_write_handler)-2) /* plain ROM location (do nothing) */
/**************************************************************************
* If the CPU opcodes are encrypted, they are fetched from a different
* memory space. In such a case, if the program dynamically creates code
* in RAM and executes it, it won't work unless you use MWA_RAMROM
* to affect both memory spaces.
**************************************************************************/
#define MWA_RAMROM ((mem_write_handler)-3)
/* bank memory */
#define MRA_BANK1 ((mem_read_handler)-10)
#define MWA_BANK1 ((mem_write_handler)-10)
#define MRA_BANK2 ((mem_read_handler)-11)
#define MWA_BANK2 ((mem_write_handler)-11)
#define MRA_BANK3 ((mem_read_handler)-12)
#define MWA_BANK3 ((mem_write_handler)-12)
#define MRA_BANK4 ((mem_read_handler)-13)
#define MWA_BANK4 ((mem_write_handler)-13)
#define MRA_BANK5 ((mem_read_handler)-14)
#define MWA_BANK5 ((mem_write_handler)-14)
#define MRA_BANK6 ((mem_read_handler)-15)
#define MWA_BANK6 ((mem_write_handler)-15)
#define MRA_BANK7 ((mem_read_handler)-16)
#define MWA_BANK7 ((mem_write_handler)-16)
#define MRA_BANK8 ((mem_read_handler)-17)
#define MWA_BANK8 ((mem_write_handler)-17)
#define MRA_BANK9 ((mem_read_handler)-18)
#define MWA_BANK9 ((mem_write_handler)-18)
#define MRA_BANK10 ((mem_read_handler)-19)
#define MWA_BANK10 ((mem_write_handler)-19)
#define MRA_BANK11 ((mem_read_handler)-20)
#define MWA_BANK11 ((mem_write_handler)-20)
#define MRA_BANK12 ((mem_read_handler)-21)
#define MWA_BANK12 ((mem_write_handler)-21)
#define MRA_BANK13 ((mem_read_handler)-22)
#define MWA_BANK13 ((mem_write_handler)-22)
#define MRA_BANK14 ((mem_read_handler)-23)
#define MWA_BANK14 ((mem_write_handler)-23)
#define MRA_BANK15 ((mem_read_handler)-24)
#define MWA_BANK15 ((mem_write_handler)-24)
#define MRA_BANK16 ((mem_read_handler)-25)
#define MWA_BANK16 ((mem_write_handler)-25)
#define MRA_BANK17 ((mem_read_handler)-26)
#define MWA_BANK17 ((mem_write_handler)-26)
#define MRA_BANK18 ((mem_read_handler)-27)
#define MWA_BANK18 ((mem_write_handler)-27)
#define MRA_BANK19 ((mem_read_handler)-28)
#define MWA_BANK19 ((mem_write_handler)-28)
#define MRA_BANK20 ((mem_read_handler)-29)
#define MWA_BANK20 ((mem_write_handler)-29)
struct Memory_ReadAddress
{
offs_t start, end;
mem_read_handler handler; /* see special values above */
};
struct Memory_WriteAddress
{
offs_t start, end;
mem_write_handler handler; /* see special values above */
data8_t **base; /* optional (see explanation above) */
size_t *size; /* optional (see explanation above) */
};
#define MEMORY_MARKER ((offs_t)~0)
#define MEMORY_END { MEMORY_MARKER, 0 } };
#define IS_MEMORY_MARKER( ma ) ((ma)->start == MEMORY_MARKER && (ma)->end < MEMORY_MARKER)
#define IS_MEMORY_END( ma ) ((ma)->start == MEMORY_MARKER && (ma)->end == 0)
#define MEMORY_READ_START(name) const struct Memory_ReadAddress name[] = { \
{ MEMORY_MARKER, MEMORY_DIRECTION_READ | MEMORY_TYPE_MEM | MEMORY_WIDTH_8 },
#define MEMORY_WRITE_START(name) const struct Memory_WriteAddress name[] = { \
{ MEMORY_MARKER, MEMORY_DIRECTION_WRITE | MEMORY_TYPE_MEM | MEMORY_WIDTH_8 },
/***************************************************************************
16-BIT Core memory read/write/opbase handler types
***************************************************************************/
typedef data16_t (*mem_read16_handler)(UNUSEDARG offs_t offset);
typedef void (*mem_write16_handler)(UNUSEDARG offs_t offset, UNUSEDARG data16_t data, UNUSEDARG UINT32 mem_mask);
#define READ16_HANDLER(name) data16_t name(UNUSEDARG offs_t offset, UNUSEDARG UINT32 mem_mask)
#define WRITE16_HANDLER(name) void name(UNUSEDARG offs_t offset, UNUSEDARG data16_t data, UNUSEDARG UINT32 mem_mask)
#define OPBASE16_HANDLER(name) offs_t name(UNUSEDARG offs_t address)
#define MRA16_NOP 0 /* don't care, return 0 */
#define MWA16_NOP 0 /* do nothing */
#define MRA16_RAM ((mem_read16_handler)-1) /* plain RAM location (return its contents) */
#define MWA16_RAM ((mem_write16_handler)-1) /* plqain RAM location (store the value) */
#define MRA16_ROM ((mem_read16_handler)-2) /* plain ROM location (return its contents) */
#define MWA16_ROM ((mem_write16_handler)-2) /* plain ROM location (do nothing) */
/**************************************************************************
* If the CPU opcodes are encrypted, they are fetched from a different
* memory space. In such a case, if the program dynamically creates code
* in RAM and executes it, it won't work unless you use MWA_RAMROM
* to affect both memory spaces.
**************************************************************************/
#define MWA16_RAMROM ((mem_write16_handler)-3)
/* bank memory */
#define MRA16_BANK1 ((mem_read16_handler)-10)
#define MWA16_BANK1 ((mem_write16_handler)-10)
#define MRA16_BANK2 ((mem_read16_handler)-11)
#define MWA16_BANK2 ((mem_write16_handler)-11)
#define MRA16_BANK3 ((mem_read16_handler)-12)
#define MWA16_BANK3 ((mem_write16_handler)-12)
#define MRA16_BANK4 ((mem_read16_handler)-13)
#define MWA16_BANK4 ((mem_write16_handler)-13)
#define MRA16_BANK5 ((mem_read16_handler)-14)
#define MWA16_BANK5 ((mem_write16_handler)-14)
#define MRA16_BANK6 ((mem_read16_handler)-15)
#define MWA16_BANK6 ((mem_write16_handler)-15)
#define MRA16_BANK7 ((mem_read16_handler)-16)
#define MWA16_BANK7 ((mem_write16_handler)-16)
#define MRA16_BANK8 ((mem_read16_handler)-17)
#define MWA16_BANK8 ((mem_write16_handler)-17)
#define MRA16_BANK9 ((mem_read16_handler)-18)
#define MWA16_BANK9 ((mem_write16_handler)-18)
#define MRA16_BANK10 ((mem_read16_handler)-19)
#define MWA16_BANK10 ((mem_write16_handler)-19)
#define MRA16_BANK11 ((mem_read16_handler)-20)
#define MWA16_BANK11 ((mem_write16_handler)-20)
#define MRA16_BANK12 ((mem_read16_handler)-21)
#define MWA16_BANK12 ((mem_write16_handler)-21)
#define MRA16_BANK13 ((mem_read16_handler)-22)
#define MWA16_BANK13 ((mem_write16_handler)-22)
#define MRA16_BANK14 ((mem_read16_handler)-23)
#define MWA16_BANK14 ((mem_write16_handler)-23)
#define MRA16_BANK15 ((mem_read16_handler)-24)
#define MWA16_BANK15 ((mem_write16_handler)-24)
#define MRA16_BANK16 ((mem_read16_handler)-25)
#define MWA16_BANK16 ((mem_write16_handler)-25)
#define MRA16_BANK17 ((mem_read16_handler)-26)
#define MWA16_BANK17 ((mem_write16_handler)-26)
#define MRA16_BANK18 ((mem_read16_handler)-27)
#define MWA16_BANK18 ((mem_write16_handler)-27)
#define MRA16_BANK19 ((mem_read16_handler)-28)
#define MWA16_BANK19 ((mem_write16_handler)-28)
#define MRA16_BANK20 ((mem_read16_handler)-29)
#define MWA16_BANK20 ((mem_write16_handler)-29)
struct Memory_ReadAddress16
{
offs_t start, end;
mem_read16_handler handler; /* see special values above */
};
struct Memory_WriteAddress16
{
offs_t start, end;
mem_write16_handler handler; /* see special values above */
data16_t **base; /* optional (see explanation above) */
size_t *size; /* optional (see explanation above) */
};
#define MEMORY_READ16_START(name) const struct Memory_ReadAddress16 name[] = { \
{ MEMORY_MARKER, MEMORY_DIRECTION_READ | MEMORY_TYPE_MEM | MEMORY_WIDTH_16 },
#define MEMORY_WRITE16_START(name) const struct Memory_WriteAddress16 name[] = { \
{ MEMORY_MARKER, MEMORY_DIRECTION_WRITE | MEMORY_TYPE_MEM | MEMORY_WIDTH_16 },
/***************************************************************************
32-BIT Core memory read/write/opbase handler types
***************************************************************************/
typedef UINT32 data32_t;
typedef data32_t (*mem_read32_handler)(UNUSEDARG offs_t offset);
typedef void (*mem_write32_handler)(UNUSEDARG offs_t offset, UNUSEDARG data32_t data, UNUSEDARG UINT32 mem_mask);
#define READ32_HANDLER(name) data32_t name(UNUSEDARG offs_t offset, UNUSEDARG UINT32 mem_mask)
#define WRITE32_HANDLER(name) void name(UNUSEDARG offs_t offset, UNUSEDARG data32_t data, UNUSEDARG UINT32 mem_mask)
#define OPBASE32_HANDLER(name) offs_t name(UNUSEDARG offs_t address)
#define MRA32_NOP 0 /* don't care, return 0 */
#define MWA32_NOP 0 /* do nothing */
#define MRA32_RAM ((mem_read32_handler)-1) /* plain RAM location (return its contents) */
#define MWA32_RAM ((mem_write32_handler)-1) /* plain RAM location (store the value) */
#define MRA32_ROM ((mem_read32_handler)-2) /* plain ROM location (return its contents) */
#define MWA32_ROM ((mem_write32_handler)-2) /* plain ROM location (do nothing) */
/**************************************************************************
* If the CPU opcodes are encrypted, they are fetched from a different
* memory space. In such a case, if the program dynamically creates code
* in RAM and executes it, it won't work unless you use MWA_RAMROM
* to affect both memory spaces.
**************************************************************************/
#define MWA32_RAMROM ((mem_write32_handler)-3)
/* bank memory */
#define MRA32_BANK1 ((mem_read32_handler)-10)
#define MWA32_BANK1 ((mem_write32_handler)-10)
#define MRA32_BANK2 ((mem_read32_handler)-11)
#define MWA32_BANK2 ((mem_write32_handler)-11)
#define MRA32_BANK3 ((mem_read32_handler)-12)
#define MWA32_BANK3 ((mem_write32_handler)-12)
#define MRA32_BANK4 ((mem_read32_handler)-13)
#define MWA32_BANK4 ((mem_write32_handler)-13)
#define MRA32_BANK5 ((mem_read32_handler)-14)
#define MWA32_BANK5 ((mem_write32_handler)-14)
#define MRA32_BANK6 ((mem_read32_handler)-15)
#define MWA32_BANK6 ((mem_write32_handler)-15)
#define MRA32_BANK7 ((mem_read32_handler)-16)
#define MWA32_BANK7 ((mem_write32_handler)-16)
#define MRA32_BANK8 ((mem_read32_handler)-17)
#define MWA32_BANK8 ((mem_write32_handler)-17)
#define MRA32_BANK9 ((mem_read32_handler)-18)
#define MWA32_BANK9 ((mem_write32_handler)-18)
#define MRA32_BANK10 ((mem_read32_handler)-19)
#define MWA32_BANK10 ((mem_write32_handler)-19)
#define MRA32_BANK11 ((mem_read32_handler)-20)
#define MWA32_BANK11 ((mem_write32_handler)-20)
#define MRA32_BANK12 ((mem_read32_handler)-21)
#define MWA32_BANK12 ((mem_write32_handler)-21)
#define MRA32_BANK13 ((mem_read32_handler)-22)
#define MWA32_BANK13 ((mem_write32_handler)-22)
#define MRA32_BANK14 ((mem_read32_handler)-23)
#define MWA32_BANK14 ((mem_write32_handler)-23)
#define MRA32_BANK15 ((mem_read32_handler)-24)
#define MWA32_BANK15 ((mem_write32_handler)-24)
#define MRA32_BANK32 ((mem_read32_handler)-25)
#define MWA32_BANK32 ((mem_write32_handler)-25)
#define MRA32_BANK17 ((mem_read32_handler)-26)
#define MWA32_BANK17 ((mem_write32_handler)-26)
#define MRA32_BANK18 ((mem_read32_handler)-27)
#define MWA32_BANK18 ((mem_write32_handler)-27)
#define MRA32_BANK19 ((mem_read32_handler)-28)
#define MWA32_BANK19 ((mem_write32_handler)-28)
#define MRA32_BANK20 ((mem_read32_handler)-29)
#define MWA32_BANK20 ((mem_write32_handler)-29)
struct Memory_ReadAddress32
{
offs_t start, end;
mem_read32_handler handler; /* see special values above */
};
struct Memory_WriteAddress32
{
offs_t start, end;
mem_write32_handler handler; /* see special values above */
data32_t **base; /* optional (see explanation above) */
size_t *size; /* optional (see explanation above) */
};
#define MEMORY_READ32_START(name) const struct Memory_ReadAddress32 name[] = { \
{ MEMORY_MARKER, MEMORY_DIRECTION_READ | MEMORY_TYPE_MEM | MEMORY_WIDTH_32 },
#define MEMORY_WRITE32_START(name) const struct Memory_WriteAddress32 name[] = { \
{ MEMORY_MARKER, MEMORY_DIRECTION_WRITE | MEMORY_TYPE_MEM | MEMORY_WIDTH_32 },
/***************************************************************************
IN and OUT ports are handled like memory accesses, the hook template is the
same so you can interchange them. Of course there is no 'base' pointer for
IO ports.
***************************************************************************/
struct IO_ReadPort
{
offs_t start,end;
mem_read_handler handler; /* see special values below */
};
#define IORP_NOP 0 /* don't care, return 0 */
struct IO_WritePort
{
offs_t start,end;
mem_write_handler handler; /* see special values below */
};
#define IOWP_NOP 0 /* do nothing */
#define PORT_READ_START(name) const struct IO_ReadPort name[] = { \
{ MEMORY_MARKER, MEMORY_DIRECTION_READ | MEMORY_TYPE_IO | MEMORY_WIDTH_8 },
#define PORT_WRITE_START(name) const struct IO_WritePort name[] = { \
{ MEMORY_MARKER, MEMORY_DIRECTION_WRITE | MEMORY_TYPE_IO | MEMORY_WIDTH_8 },
#define PORT_END MEMORY_END
/***************************************************************************
If a memory region contains areas that are outside of the ROM region for
an address space, the memory system will allocate an array of structures
to track the external areas.
***************************************************************************/
#define MAX_EXT_MEMORY 64
struct ExtMemory
{
offs_t start,end,region;
UINT8 *data;
};
extern struct ExtMemory ext_memory[MAX_EXT_MEMORY];
/***************************************************************************
For a given number of address bits, we need to determine how many elements
there are in the first and second-order lookup tables. We also need to know
how many low-order bits to ignore. The ABITS* values represent these
constants for each address space type we support.
***************************************************************************/
/* memory element block size */
#define MH_SBITS 8 /* sub element bank size */
#define MH_PBITS 8 /* port current element size */
#define MH_ELEMAX 64 /* sub elements limit */
#define MH_HARDMAX 64 /* hardware functions limit */
/* 16 bits address */
#define ABITS1_16 12
#define ABITS2_16 4
#define ABITS_MIN_16 0 /* minimum memory block is 1 byte */
/* 16 bits address (word access) */
#define ABITS1_16W 12
#define ABITS2_16W 3
#define ABITS_MIN_16W 1 /* minimum memory block is 2 bytes */
/* 20 bits address */
#define ABITS1_20 12
#define ABITS2_20 8
#define ABITS_MIN_20 0 /* minimum memory block is 1 byte */
/* 21 bits address */
#define ABITS1_21 13
#define ABITS2_21 8
#define ABITS_MIN_21 0 /* minimum memory block is 1 byte */
/* 24 bits address */
#define ABITS1_24 16
#define ABITS2_24 8
#define ABITS_MIN_24 0 /* minimum memory block is 1 byte */
/* 24 bits address (word access) */
#define ABITS1_24W 15
#define ABITS2_24W 8
#define ABITS_MIN_24W 1 /* minimum memory block is 2 bytes */
/* 24 bits address (dword access) */
#define ABITS1_24DW 14
#define ABITS2_24DW 8
#define ABITS_MIN_24DW 2 /* minimum memory block is 4 bytes */
/* 26 bits address (dword access) */
#define ABITS1_26DW 16
#define ABITS2_26DW 8
#define ABITS_MIN_26DW 2 /* minimum memory block is 4 bytes */
/* 29 bits address (word access) */
#define ABITS1_29W 20
#define ABITS2_29W 8
#define ABITS_MIN_29W 1 /* minimum memory block is 2 bytes */
/* 32 bits address (word access) */
#define ABITS1_32W 23
#define ABITS2_32W 8
#define ABITS_MIN_32W 1 /* minimum memory block is 2 bytes */
/* 32 bits address (dword access) */
#define ABITS1_32DW 22
#define ABITS2_32DW 8
#define ABITS_MIN_32DW 2 /* minimum memory block is 4 bytes */
/* mask bits */
#define MHMASK(abits) (0xffffffff >> (32 - abits))
/***************************************************************************
Global variables
***************************************************************************/
typedef unsigned char MHELE;
extern MHELE ophw; /* opcode handler */
extern MHELE *cur_mrhard; /* current set of read handlers */
extern MHELE *cur_mwhard; /* current set of write handlers */
extern UINT8 *OP_RAM; /* opcode RAM base */
extern UINT8 *OP_ROM; /* opcode ROM base */
extern UINT8 *cpu_bankbase[]; /* array of bank bases */
/* global memory access width and mask (16-bit and 32-bit under-size accesses) */
//extern UINT32 mem_width;
//extern UINT32 mem_mask;
//extern UINT32 mem_offs;
/***************************************************************************
Macros
***************************************************************************/
/* ----- 16-bit memory accessing ----- */
#define COMBINE_DATA(varptr) (*(varptr) = (*(varptr) & mem_mask) | (data & ~mem_mask))
#define ACCESSING_LSB ((mem_mask & 0x00ff) == 0)
#define ACCESSING_MSB ((mem_mask & 0xff00) == 0)
//extern unsigned char prgrom[128*1024];
/* ----- opcode reading ----- */
#define cpu_readop cpu_readmem16
//#define cpu_readop16(A) READ_WORD(&prgrom[A&0x3fff])
//#define cpu_readop32(A) READ_DWORD(&prgrom[A&0x3fff])
/* ----- opcode argument reading ----- */
#define cpu_readop_arg cpu_readmem16
//#define cpu_readop_arg16(A) READ_WORD(&prgrom[A&0x3fff])
//#define cpu_readop_arg32(A) READ_DWORD(&prgrom[A&0x3fff])
/* ----- bank switching for CPU cores ----- */
#define change_pc_generic(pc,abits2,abitsmin,shift,setop) \
{ \
if (cur_mrhard[(pc)>>(abits2+abitsmin+shift)] != ophw) \
setop(pc); \
}
#define change_pc16(pc)
//change_pc_generic(pc, ABITS2_16, ABITS_MIN_16, 0, cpu_setOPbase16)
#define change_pc20(pc) change_pc_generic(pc, ABITS2_20, ABITS_MIN_20, 0, cpu_setOPbase20)
#define change_pc21(pc) change_pc_generic(pc, ABITS2_21, ABITS_MIN_21, 0, cpu_setOPbase21)
#define change_pc24(pc) change_pc_generic(pc, ABITS2_24, ABITS_MIN_24, 0, cpu_setOPbase24)
#define change_pc16bew(pc) change_pc_generic(pc, ABITS2_16W, ABITS_MIN_16W, 0, cpu_setOPbase16bew)
#define change_pc16lew(pc) change_pc_generic(pc, ABITS2_16W, ABITS_MIN_16W, 0, cpu_setOPbase16lew)
#define change_pc24bew(pc) change_pc_generic(pc, ABITS2_24W, ABITS_MIN_24W, 0, cpu_setOPbase24bew)
#define change_pc29lew(pc) change_pc_generic(pc, ABITS2_29W, ABITS_MIN_29W, 3, cpu_setOPbase29lew)
#define change_pc32bew(pc) change_pc_generic(pc, ABITS2_32W, ABITS_MIN_32W, 0, cpu_setOPbase32bew)
#define change_pc32lew(pc) change_pc_generic(pc, ABITS2_32W, ABITS_MIN_32W, 0, cpu_setOPbase32lew)
#define change_pc24bedw(pc) change_pc_generic(pc, ABITS2_24DW, ABITS_MIN_24DW, 0, cpu_setOPbase24bedw)
#define change_pc26ledw(pc) change_pc_generic(pc, ABITS2_26DW, ABITS_MIN_26DW, 0, cpu_setOPbase26ledw)
#define change_pc32bedw(pc) change_pc_generic(pc, ABITS2_32DW, ABITS_MIN_32DW, 0, cpu_setOPbase32bedw)
/* backward compatibility */
#define change_pc(pc)
// change_pc16(pc)
/* ----- for use OPbaseOverride driver, request override callback to next cpu_setOPbase ----- */
#define catch_nextBranch() (ophw = 0xff)
/* ----- bank switching macro ----- */
#define cpu_setbank(bank, base) \
{ \
if (bank >= 1 && bank <= MAX_BANKS) \
{ \
cpu_bankbase[bank] = (UINT8 *)(base); \
if (ophw == bank) \
{ \
ophw = 0xff; \
cpu_set_op_base(cpu_get_pc()); \
} \
} \
}
/***************************************************************************
Function prototypes
***************************************************************************/
/* ----- memory setup function ----- */
/* ----- memory read functions ----- */
data8_t cpu_readmem16(offs_t address);
data8_t cpu_readmem20(offs_t address);
data8_t cpu_readmem21(offs_t address);
data8_t cpu_readmem24(offs_t address);
data16_t cpu_readmem16bew(offs_t address);
data16_t cpu_readmem16bew_word(offs_t address);
data16_t cpu_readmem16lew(offs_t address);
data16_t cpu_readmem16lew_word(offs_t address);
data16_t cpu_readmem24bew(offs_t address);
data16_t cpu_readmem24bew_word(offs_t address);
data16_t cpu_readmem29lew(offs_t address);
data16_t cpu_readmem29lew_word(offs_t address);
data16_t cpu_readmem32bew(offs_t address);
data16_t cpu_readmem32bew_word(offs_t address);
data16_t cpu_readmem32lew(offs_t address);
data16_t cpu_readmem32lew_word(offs_t address);
data32_t cpu_readmem24bedw(offs_t address);
data32_t cpu_readmem24bedw_word(offs_t address);
data32_t cpu_readmem24bedw_dword(offs_t address);
data32_t cpu_readmem26ledw(offs_t address);
data32_t cpu_readmem26ledw_word(offs_t address);
data32_t cpu_readmem26ledw_dword(offs_t address);
data32_t cpu_readmem27bedw(offs_t address);
data32_t cpu_readmem27bedw_word(offs_t address);
data32_t cpu_readmem27bedw_dword(offs_t address);
data32_t cpu_readmem32bedw(offs_t address);
data32_t cpu_readmem32bedw_word(offs_t address);
data32_t cpu_readmem32bedw_dword(offs_t address);
/* ----- memory write functions ----- */
void cpu_writemem16(offs_t address,data8_t data);
void cpu_writemem20(offs_t address,data8_t data);
void cpu_writemem21(offs_t address,data8_t data);
void cpu_writemem24(offs_t address,data8_t data);
void cpu_writemem16bew(offs_t address,data16_t data);
void cpu_writemem16bew_word(offs_t address,data16_t data);
void cpu_writemem16lew(offs_t address,data16_t data);
void cpu_writemem16lew_word(offs_t address,data16_t data);
void cpu_writemem24bew(offs_t address,data16_t data);
void cpu_writemem24bew_word(offs_t address,data16_t data);
void cpu_writemem29lew(offs_t address,data16_t data);
void cpu_writemem29lew_word(offs_t address,data16_t data);
void cpu_writemem32bew(offs_t address,data16_t data);
void cpu_writemem32bew_word(offs_t address,data16_t data);
void cpu_writemem32lew(offs_t address,data16_t data);
void cpu_writemem32lew_word(offs_t address,data16_t data);
void cpu_writemem24bedw(offs_t address,data32_t data);
void cpu_writemem24bedw_word(offs_t address,data32_t data);
void cpu_writemem24bedw_dword(offs_t address,data32_t data);
void cpu_writemem26ledw(offs_t address,data32_t data);
void cpu_writemem26ledw_word(offs_t address,data32_t data);
void cpu_writemem26ledw_dword(offs_t address,data32_t data);
void cpu_writemem27bedw(offs_t address,data32_t data);
void cpu_writemem27bedw_word(offs_t address,data32_t data);
void cpu_writemem27bedw_dword(offs_t address,data32_t data);
void cpu_writemem32bedw(offs_t address,data32_t data);
void cpu_writemem32bedw_word(offs_t address,data32_t data);
void cpu_writemem32bedw_dword(offs_t address,data32_t data);
/* ----- port I/O functions ----- */
int cpu_readport(int port);
void cpu_writeport(int port, int value);
/* ----- dynamic memory/port mapping ----- */
void *install_mem_read_handler(int cpu, int start, int end, mem_read_handler handler);
void *install_mem_read16_handler(int cpu, int start, int end, mem_read16_handler handler);
void *install_mem_read32_handler(int cpu, int start, int end, mem_read32_handler handler);
void *install_mem_write_handler(int cpu, int start, int end, mem_write_handler handler);
void *install_mem_write16_handler(int cpu, int start, int end, mem_write16_handler handler);
void *install_mem_write32_handler(int cpu, int start, int end, mem_write32_handler handler);
void *install_port_read_handler(int cpu, int start, int end, mem_read_handler handler);
void *install_port_write_handler(int cpu, int start, int end, mem_write_handler handler);
/* ----- dynamic bank handlers ----- */
void cpu_setbankhandler_r(int bank, mem_read_handler handler);
void cpu_setbankhandler_w(int bank, mem_write_handler handler);
/* ----- opcode base control ---- */
void cpu_setOPbase16(offs_t pc);
void cpu_setOPbase20(offs_t pc);
void cpu_setOPbase21(offs_t pc);
void cpu_setOPbase24(offs_t pc);
void cpu_setOPbase16bew(offs_t pc);
void cpu_setOPbase16lew(offs_t pc);
void cpu_setOPbase24bew(offs_t pc);
void cpu_setOPbase24bedw(offs_t pc);
void cpu_setOPbase26ledw(offs_t pc);
void cpu_setOPbase29lew(offs_t pc);
void cpu_setOPbase32bew(offs_t pc);
void cpu_setOPbase32lew(offs_t pc);
void cpu_setOPbaseoverride(int cpu, opbase_handler function);
/* ----- harder-to-explain functions ---- */
/* use this to set the a different opcode base address when using a CPU with
opcodes and data encrypted separately */
void memory_set_opcode_base(int cpu, void *base);
/* look up a chunk of memory and get its start/end addresses, and its base.
Pass in the cpu number and the offset. It will find the chunk containing
that offset and return the start and end addresses, along with a pointer to
the base of the memory.
This can be used (carefully!) by drivers that wish to access memory directly
without going through the readmem/writemem accessors (e.g., blitters). */
void *findmemorychunk(int cpu, int offset, int *chunkstart, int *chunkend);
#ifdef __cplusplus
}
#endif
#endif /* !_MEMORY_H */

View file

@ -1,282 +0,0 @@
#########################################################################
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS

View file

@ -1,618 +0,0 @@
/***************************************************************************
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:
//
// 2003/01/06 - Pete
// - added Neill's ADSR timings
//
// 2002/05/15 - Pete
// - generic cleanup for the Peops release
//
//*************************************************************************//
#define _IN_ADSR
// will be included from spu.c
#ifdef _IN_SPU
////////////////////////////////////////////////////////////////////////
// ADSR func
////////////////////////////////////////////////////////////////////////
static u32 RateTable[160];
static void InitADSR(void) // INIT ADSR
{
u32 r,rs,rd;int i;
memset(RateTable,0,sizeof(u32)*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;
}
}
////////////////////////////////////////////////////////////////////////
static INLINE void StartADSR(int ch) // MIX ADSR
{
s_chan[ch].ADSRX.lVolume=1; // and init some adsr vars
s_chan[ch].ADSRX.State=0;
s_chan[ch].ADSRX.EnvelopeVol=0;
}
////////////////////////////////////////////////////////////////////////
static INLINE int MixADSR(int ch) // MIX ADSR
{
static const int sexytable[8]=
{0,4,6,8,9,10,11,12};
if(s_chan[ch].bStop) // should be stopped:
{ // do release
if(s_chan[ch].ADSRX.ReleaseModeExp)
{
s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18+32+sexytable[(s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7]];
}
else
{
s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x0C + 32];
}
if(s_chan[ch].ADSRX.EnvelopeVol<0)
{
s_chan[ch].ADSRX.EnvelopeVol=0;
s_chan[ch].bOn=0;
s_chan[ch].bNoise=0;
}
s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
return s_chan[ch].ADSRX.lVolume;
}
else // not stopped yet?
{
if(s_chan[ch].ADSRX.State==0) // -> attack
{
if(s_chan[ch].ADSRX.AttackModeExp)
{
if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
else
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x18 + 32];
}
else
{
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
}
if(s_chan[ch].ADSRX.EnvelopeVol<0)
{
s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
s_chan[ch].ADSRX.State=1;
}
s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
return s_chan[ch].ADSRX.lVolume;
}
//--------------------------------------------------//
if(s_chan[ch].ADSRX.State==1) // -> decay
{
s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+32+sexytable[(s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7]];
if(s_chan[ch].ADSRX.EnvelopeVol<0) s_chan[ch].ADSRX.EnvelopeVol=0;
if(((s_chan[ch].ADSRX.EnvelopeVol>>27)&0xF) <= s_chan[ch].ADSRX.SustainLevel)
{
s_chan[ch].ADSRX.State=2;
}
s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
return s_chan[ch].ADSRX.lVolume;
}
//--------------------------------------------------//
if(s_chan[ch].ADSRX.State==2) // -> sustain
{
if(s_chan[ch].ADSRX.SustainIncrease)
{
if(s_chan[ch].ADSRX.SustainModeExp)
{
if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
else
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x18 + 32];
}
else
{
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
}
if(s_chan[ch].ADSRX.EnvelopeVol<0)
{
s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
}
}
else
{
if(s_chan[ch].ADSRX.SustainModeExp)
s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B+32+sexytable[(s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7]];
else
s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x0F + 32];
if(s_chan[ch].ADSRX.EnvelopeVol<0)
{
s_chan[ch].ADSRX.EnvelopeVol=0;
}
}
s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
return s_chan[ch].ADSRX.lVolume;
}
}
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<<value)*292)/10000
------------------------------------
3. Sustain rate value (linear mode)
Sustain rate range: 0 -> 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<<value)*446)/10000
------------------------------------
Other notes:
Log stuff not figured out. You may get some clues from the "Decay rate"
stuff above. For emu purposes it may not be important - use linear
approx.
To get timings in millisecs, multiply frames by 20.
- James Higgs 17/6/2000
james7780@yahoo.com
//---------------------------------------------------------------
OLD adsr mixing according to james' rules... has to be called
every one millisecond
i32 v,v2,lT,l1,l2,l3;
if(s_chan[ch].bStop) // psx wants to stop? -> 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<l1) // -> 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(lT<l1) // attack
{ // no exp mode used (yet)
// if(s_chan[ch].ADSR.AttackModeExp)
// {
// v=(v*lT)/l1;
// }
// else
{
v=(v*lT)/l1;
}
if(v==0) v=1;
}
else // decay
{ // should be exp, but who cares? ;)
l2=s_chan[ch].ADSR.DecayTime;
v2=s_chan[ch].ADSR.SustainLevel;
lT-=l1;
if(lT<l2)
{
v-=(((v-v2)*lT)/l2);
}
else // sustain
{ // no exp mode used (yet)
l3=s_chan[ch].ADSR.SustainTime;
lT-=l2;
if(s_chan[ch].ADSR.SustainModeDec>0)
{
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]
-----------------------------------------------------------------------------
*/

View file

@ -1,28 +0,0 @@
/***************************************************************************
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
//
//*************************************************************************//
static INLINE void StartADSR(int ch);
static INLINE int MixADSR(int ch);

View file

@ -1,80 +0,0 @@
/***************************************************************************
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 "../peops/stdafx.h"
#define _IN_DMA
extern uint32 psx_ram[(2*1024*1024)/4];
//#include "externals.h"
////////////////////////////////////////////////////////////////////////
// READ DMA (many values)
////////////////////////////////////////////////////////////////////////
void SPUreadDMAMem(u32 usPSXMem,int iSize)
{
int i;
u16 *ram16 = (u16 *)&psx_ram[0];
for(i=0;i<iSize;i++)
{
ram16[usPSXMem>>1]=spuMem[spuAddr>>1]; // spu addr got by writeregister
usPSXMem+=2;
spuAddr+=2; // inc spu addr
if(spuAddr>0x7ffff) spuAddr=0; // wrap
}
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// 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 (many values)
////////////////////////////////////////////////////////////////////////
void SPUwriteDMAMem(u32 usPSXMem,int iSize)
{
int i;
u16 *ram16 = (u16 *)&psx_ram[0];
for(i=0;i<iSize;i++)
{
// printf("main RAM %x => SPU %x\n", usPSXMem, spuAddr);
spuMem[spuAddr>>1] = ram16[usPSXMem>>1];
usPSXMem+=2; // spu addr got by writeregister
spuAddr+=2; // inc spu addr
if(spuAddr>0x7ffff) spuAddr=0; // wrap
}
}
////////////////////////////////////////////////////////////////////////

View file

@ -1,31 +0,0 @@
/***************************************************************************
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
//
//*************************************************************************//
u16 CALLBACK SPUreadDMA(void);
void CALLBACK SPUreadDMAMem(u16 * pusPSXMem,int iSize);
void CALLBACK SPUwriteDMA(u16 val);
void CALLBACK SPUwriteDMAMem(u16 * pusPSXMem,int iSize);

View file

@ -1,203 +0,0 @@
/***************************************************************************
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. *
* *
***************************************************************************/
#include "ao.h"
#ifndef PEOPS_EXTERNALS
#define PEOPS_EXTERNALS
typedef int8 s8;
typedef int16 s16;
typedef int32 s32;
typedef int64 s64;
typedef uint8 u8;
typedef uint16 u16;
typedef uint32 u32;
typedef uint64 u64;
#if LSB_FIRST
static INLINE u16 BFLIP16(u16 x)
{
return x;
}
#else
static INLINE u16 BFLIP16(u16 x)
{
return( ((x>>8)&0xFF)| ((x&0xFF)<<8) );
}
#endif
//*************************************************************************//
// History of changes:
//
// 2002/05/15 - Pete
// - generic cleanup for the Peops release
//
//*************************************************************************//
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
////////////////////////////////////////////////////////////////////////
// spu defines
////////////////////////////////////////////////////////////////////////
// num of channels
#define MAXCHAN 24
///////////////////////////////////////////////////////////
// struct defines
///////////////////////////////////////////////////////////
// ADSR INFOS PER CHANNEL
typedef struct
{
int AttackModeExp;
s32 AttackTime;
s32 DecayTime;
s32 SustainLevel;
int SustainModeExp;
s32 SustainModeDec;
s32 SustainTime;
int ReleaseModeExp;
u32 ReleaseVal;
s32 ReleaseTime;
s32 ReleaseStartTime;
s32 ReleaseVol;
s32 lTime;
s32 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;
s32 lVolume;
s32 lDummy1;
s32 lDummy2;
} ADSRInfoEx;
///////////////////////////////////////////////////////////
// Tmp Flags
// used for debug channel muting
#define FLAG_MUTE 1
///////////////////////////////////////////////////////////
// MAIN CHANNEL STRUCT
typedef struct
{
int bNew; // start flag
int iSBPos; // mixing stuff
int spos;
int sinc;
int SB[32+1];
int sval;
u8 * pStart; // start ptr into sound mem
u8 * pCurr; // current pos in sound mem
u8 * 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 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 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 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 Enabled;
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;
#endif // PEOPS_EXTERNALS

View file

@ -1,163 +0,0 @@
/***************************************************************************
gauss_i.h - description
-----------------------
begin : Sun Feb 08 2003
copyright : (C) 2003 by Chris Moeller, eh, whatever
email : chris@kode54.tk
***************************************************************************/
/***************************************************************************
* *
* 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/08 - kode54
// - generated by interleaving table from gauss.h from the libopenspc
// project; a gaussian bell curve table logged from the SPC-700,
// though Neill says he logged the same curve from a PSX SPU. Also
// says that interleaving the coefficients together runs faster. Meh.
//
//*************************************************************************//
#ifndef GAUSS_H
#define GAUSS_H
// 1024 entries
const int gauss[]={
0x172, 0x519, 0x176, 0x000, 0x16E, 0x519, 0x17A, 0x000,
0x16A, 0x518, 0x17D, 0x000, 0x166, 0x518, 0x181, 0x000,
0x162, 0x518, 0x185, 0x000, 0x15F, 0x518, 0x189, 0x000,
0x15B, 0x518, 0x18D, 0x000, 0x157, 0x517, 0x191, 0x000,
0x153, 0x517, 0x195, 0x000, 0x150, 0x517, 0x19A, 0x000,
0x14C, 0x516, 0x19E, 0x000, 0x148, 0x516, 0x1A2, 0x000,
0x145, 0x515, 0x1A6, 0x000, 0x141, 0x514, 0x1AA, 0x000,
0x13E, 0x514, 0x1AE, 0x000, 0x13A, 0x513, 0x1B2, 0x000,
0x137, 0x512, 0x1B7, 0x001, 0x133, 0x511, 0x1BB, 0x001,
0x130, 0x511, 0x1BF, 0x001, 0x12C, 0x510, 0x1C3, 0x001,
0x129, 0x50F, 0x1C8, 0x001, 0x125, 0x50E, 0x1CC, 0x001,
0x122, 0x50D, 0x1D0, 0x001, 0x11E, 0x50C, 0x1D5, 0x001,
0x11B, 0x50B, 0x1D9, 0x001, 0x118, 0x50A, 0x1DD, 0x001,
0x114, 0x508, 0x1E2, 0x001, 0x111, 0x507, 0x1E6, 0x002,
0x10E, 0x506, 0x1EB, 0x002, 0x10B, 0x504, 0x1EF, 0x002,
0x107, 0x503, 0x1F3, 0x002, 0x104, 0x502, 0x1F8, 0x002,
0x101, 0x500, 0x1FC, 0x002, 0x0FE, 0x4FF, 0x201, 0x002,
0x0FB, 0x4FD, 0x205, 0x003, 0x0F8, 0x4FB, 0x20A, 0x003,
0x0F5, 0x4FA, 0x20F, 0x003, 0x0F2, 0x4F8, 0x213, 0x003,
0x0EF, 0x4F6, 0x218, 0x003, 0x0EC, 0x4F5, 0x21C, 0x004,
0x0E9, 0x4F3, 0x221, 0x004, 0x0E6, 0x4F1, 0x226, 0x004,
0x0E3, 0x4EF, 0x22A, 0x004, 0x0E0, 0x4ED, 0x22F, 0x004,
0x0DD, 0x4EB, 0x233, 0x005, 0x0DA, 0x4E9, 0x238, 0x005,
0x0D7, 0x4E7, 0x23D, 0x005, 0x0D4, 0x4E5, 0x241, 0x005,
0x0D2, 0x4E3, 0x246, 0x006, 0x0CF, 0x4E0, 0x24B, 0x006,
0x0CC, 0x4DE, 0x250, 0x006, 0x0C9, 0x4DC, 0x254, 0x006,
0x0C7, 0x4D9, 0x259, 0x007, 0x0C4, 0x4D7, 0x25E, 0x007,
0x0C1, 0x4D5, 0x263, 0x007, 0x0BF, 0x4D2, 0x267, 0x008,
0x0BC, 0x4D0, 0x26C, 0x008, 0x0BA, 0x4CD, 0x271, 0x008,
0x0B7, 0x4CB, 0x276, 0x009, 0x0B4, 0x4C8, 0x27B, 0x009,
0x0B2, 0x4C5, 0x280, 0x009, 0x0AF, 0x4C3, 0x284, 0x00A,
0x0AD, 0x4C0, 0x289, 0x00A, 0x0AB, 0x4BD, 0x28E, 0x00A,
0x0A8, 0x4BA, 0x293, 0x00B, 0x0A6, 0x4B7, 0x298, 0x00B,
0x0A3, 0x4B5, 0x29D, 0x00B, 0x0A1, 0x4B2, 0x2A2, 0x00C,
0x09F, 0x4AF, 0x2A6, 0x00C, 0x09C, 0x4AC, 0x2AB, 0x00D,
0x09A, 0x4A9, 0x2B0, 0x00D, 0x098, 0x4A6, 0x2B5, 0x00E,
0x096, 0x4A2, 0x2BA, 0x00E, 0x093, 0x49F, 0x2BF, 0x00F,
0x091, 0x49C, 0x2C4, 0x00F, 0x08F, 0x499, 0x2C9, 0x00F,
0x08D, 0x496, 0x2CE, 0x010, 0x08B, 0x492, 0x2D3, 0x010,
0x089, 0x48F, 0x2D8, 0x011, 0x086, 0x48C, 0x2DC, 0x011,
0x084, 0x488, 0x2E1, 0x012, 0x082, 0x485, 0x2E6, 0x013,
0x080, 0x481, 0x2EB, 0x013, 0x07E, 0x47E, 0x2F0, 0x014,
0x07C, 0x47A, 0x2F5, 0x014, 0x07A, 0x477, 0x2FA, 0x015,
0x078, 0x473, 0x2FF, 0x015, 0x076, 0x470, 0x304, 0x016,
0x075, 0x46C, 0x309, 0x017, 0x073, 0x468, 0x30E, 0x017,
0x071, 0x465, 0x313, 0x018, 0x06F, 0x461, 0x318, 0x018,
0x06D, 0x45D, 0x31D, 0x019, 0x06B, 0x459, 0x322, 0x01A,
0x06A, 0x455, 0x326, 0x01B, 0x068, 0x452, 0x32B, 0x01B,
0x066, 0x44E, 0x330, 0x01C, 0x064, 0x44A, 0x335, 0x01D,
0x063, 0x446, 0x33A, 0x01D, 0x061, 0x442, 0x33F, 0x01E,
0x05F, 0x43E, 0x344, 0x01F, 0x05E, 0x43A, 0x349, 0x020,
0x05C, 0x436, 0x34E, 0x020, 0x05A, 0x432, 0x353, 0x021,
0x059, 0x42E, 0x357, 0x022, 0x057, 0x42A, 0x35C, 0x023,
0x056, 0x425, 0x361, 0x024, 0x054, 0x421, 0x366, 0x024,
0x053, 0x41D, 0x36B, 0x025, 0x051, 0x419, 0x370, 0x026,
0x050, 0x415, 0x374, 0x027, 0x04E, 0x410, 0x379, 0x028,
0x04D, 0x40C, 0x37E, 0x029, 0x04C, 0x408, 0x383, 0x02A,
0x04A, 0x403, 0x388, 0x02B, 0x049, 0x3FF, 0x38C, 0x02C,
0x047, 0x3FB, 0x391, 0x02D, 0x046, 0x3F6, 0x396, 0x02E,
0x045, 0x3F2, 0x39B, 0x02F, 0x043, 0x3ED, 0x39F, 0x030,
0x042, 0x3E9, 0x3A4, 0x031, 0x041, 0x3E5, 0x3A9, 0x032,
0x040, 0x3E0, 0x3AD, 0x033, 0x03E, 0x3DC, 0x3B2, 0x034,
0x03D, 0x3D7, 0x3B7, 0x035, 0x03C, 0x3D2, 0x3BB, 0x036,
0x03B, 0x3CE, 0x3C0, 0x037, 0x03A, 0x3C9, 0x3C5, 0x038,
0x038, 0x3C5, 0x3C9, 0x03A, 0x037, 0x3C0, 0x3CE, 0x03B,
0x036, 0x3BB, 0x3D2, 0x03C, 0x035, 0x3B7, 0x3D7, 0x03D,
0x034, 0x3B2, 0x3DC, 0x03E, 0x033, 0x3AD, 0x3E0, 0x040,
0x032, 0x3A9, 0x3E5, 0x041, 0x031, 0x3A4, 0x3E9, 0x042,
0x030, 0x39F, 0x3ED, 0x043, 0x02F, 0x39B, 0x3F2, 0x045,
0x02E, 0x396, 0x3F6, 0x046, 0x02D, 0x391, 0x3FB, 0x047,
0x02C, 0x38C, 0x3FF, 0x049, 0x02B, 0x388, 0x403, 0x04A,
0x02A, 0x383, 0x408, 0x04C, 0x029, 0x37E, 0x40C, 0x04D,
0x028, 0x379, 0x410, 0x04E, 0x027, 0x374, 0x415, 0x050,
0x026, 0x370, 0x419, 0x051, 0x025, 0x36B, 0x41D, 0x053,
0x024, 0x366, 0x421, 0x054, 0x024, 0x361, 0x425, 0x056,
0x023, 0x35C, 0x42A, 0x057, 0x022, 0x357, 0x42E, 0x059,
0x021, 0x353, 0x432, 0x05A, 0x020, 0x34E, 0x436, 0x05C,
0x020, 0x349, 0x43A, 0x05E, 0x01F, 0x344, 0x43E, 0x05F,
0x01E, 0x33F, 0x442, 0x061, 0x01D, 0x33A, 0x446, 0x063,
0x01D, 0x335, 0x44A, 0x064, 0x01C, 0x330, 0x44E, 0x066,
0x01B, 0x32B, 0x452, 0x068, 0x01B, 0x326, 0x455, 0x06A,
0x01A, 0x322, 0x459, 0x06B, 0x019, 0x31D, 0x45D, 0x06D,
0x018, 0x318, 0x461, 0x06F, 0x018, 0x313, 0x465, 0x071,
0x017, 0x30E, 0x468, 0x073, 0x017, 0x309, 0x46C, 0x075,
0x016, 0x304, 0x470, 0x076, 0x015, 0x2FF, 0x473, 0x078,
0x015, 0x2FA, 0x477, 0x07A, 0x014, 0x2F5, 0x47A, 0x07C,
0x014, 0x2F0, 0x47E, 0x07E, 0x013, 0x2EB, 0x481, 0x080,
0x013, 0x2E6, 0x485, 0x082, 0x012, 0x2E1, 0x488, 0x084,
0x011, 0x2DC, 0x48C, 0x086, 0x011, 0x2D8, 0x48F, 0x089,
0x010, 0x2D3, 0x492, 0x08B, 0x010, 0x2CE, 0x496, 0x08D,
0x00F, 0x2C9, 0x499, 0x08F, 0x00F, 0x2C4, 0x49C, 0x091,
0x00F, 0x2BF, 0x49F, 0x093, 0x00E, 0x2BA, 0x4A2, 0x096,
0x00E, 0x2B5, 0x4A6, 0x098, 0x00D, 0x2B0, 0x4A9, 0x09A,
0x00D, 0x2AB, 0x4AC, 0x09C, 0x00C, 0x2A6, 0x4AF, 0x09F,
0x00C, 0x2A2, 0x4B2, 0x0A1, 0x00B, 0x29D, 0x4B5, 0x0A3,
0x00B, 0x298, 0x4B7, 0x0A6, 0x00B, 0x293, 0x4BA, 0x0A8,
0x00A, 0x28E, 0x4BD, 0x0AB, 0x00A, 0x289, 0x4C0, 0x0AD,
0x00A, 0x284, 0x4C3, 0x0AF, 0x009, 0x280, 0x4C5, 0x0B2,
0x009, 0x27B, 0x4C8, 0x0B4, 0x009, 0x276, 0x4CB, 0x0B7,
0x008, 0x271, 0x4CD, 0x0BA, 0x008, 0x26C, 0x4D0, 0x0BC,
0x008, 0x267, 0x4D2, 0x0BF, 0x007, 0x263, 0x4D5, 0x0C1,
0x007, 0x25E, 0x4D7, 0x0C4, 0x007, 0x259, 0x4D9, 0x0C7,
0x006, 0x254, 0x4DC, 0x0C9, 0x006, 0x250, 0x4DE, 0x0CC,
0x006, 0x24B, 0x4E0, 0x0CF, 0x006, 0x246, 0x4E3, 0x0D2,
0x005, 0x241, 0x4E5, 0x0D4, 0x005, 0x23D, 0x4E7, 0x0D7,
0x005, 0x238, 0x4E9, 0x0DA, 0x005, 0x233, 0x4EB, 0x0DD,
0x004, 0x22F, 0x4ED, 0x0E0, 0x004, 0x22A, 0x4EF, 0x0E3,
0x004, 0x226, 0x4F1, 0x0E6, 0x004, 0x221, 0x4F3, 0x0E9,
0x004, 0x21C, 0x4F5, 0x0EC, 0x003, 0x218, 0x4F6, 0x0EF,
0x003, 0x213, 0x4F8, 0x0F2, 0x003, 0x20F, 0x4FA, 0x0F5,
0x003, 0x20A, 0x4FB, 0x0F8, 0x003, 0x205, 0x4FD, 0x0FB,
0x002, 0x201, 0x4FF, 0x0FE, 0x002, 0x1FC, 0x500, 0x101,
0x002, 0x1F8, 0x502, 0x104, 0x002, 0x1F3, 0x503, 0x107,
0x002, 0x1EF, 0x504, 0x10B, 0x002, 0x1EB, 0x506, 0x10E,
0x002, 0x1E6, 0x507, 0x111, 0x001, 0x1E2, 0x508, 0x114,
0x001, 0x1DD, 0x50A, 0x118, 0x001, 0x1D9, 0x50B, 0x11B,
0x001, 0x1D5, 0x50C, 0x11E, 0x001, 0x1D0, 0x50D, 0x122,
0x001, 0x1CC, 0x50E, 0x125, 0x001, 0x1C8, 0x50F, 0x129,
0x001, 0x1C3, 0x510, 0x12C, 0x001, 0x1BF, 0x511, 0x130,
0x001, 0x1BB, 0x511, 0x133, 0x001, 0x1B7, 0x512, 0x137,
0x000, 0x1B2, 0x513, 0x13A, 0x000, 0x1AE, 0x514, 0x13E,
0x000, 0x1AA, 0x514, 0x141, 0x000, 0x1A6, 0x515, 0x145,
0x000, 0x1A2, 0x516, 0x148, 0x000, 0x19E, 0x516, 0x14C,
0x000, 0x19A, 0x517, 0x150, 0x000, 0x195, 0x517, 0x153,
0x000, 0x191, 0x517, 0x157, 0x000, 0x18D, 0x518, 0x15B,
0x000, 0x189, 0x518, 0x15F, 0x000, 0x185, 0x518, 0x162,
0x000, 0x181, 0x518, 0x166, 0x000, 0x17D, 0x518, 0x16A,
0x000, 0x17A, 0x519, 0x16E, 0x000, 0x176, 0x519, 0x172};
#endif

View file

@ -1,492 +0,0 @@
/***************************************************************************
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. *
* *
***************************************************************************/
/* ChangeLog
February 8, 2004 - xodnizel
- Fixed setting of reverb volume. Just typecast val("u16") to s16.
Also adjusted the normal channel volume to be one less than what it was before when the
"phase invert" bit is set. I'm assuming it's just in two's complement.
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 "../peops/externals.h"
#include "../peops/registers.h"
#include "../peops/regs.h"
////////////////////////////////////////////////////////////////////////
// WRITE REGISTERS: called by main emu
////////////////////////////////////////////////////////////////////////
void SPUwriteRegister(u32 reg, u16 val)
{
const u32 r=reg&0xfff;
regArea[(r-0xc00)>>1] = val;
// printf("SPUwrite: r %x val %x\n", r, val);
if(r>=0x0c00 && r<0x0d80) // some channel info?
{
int ch=(r>>4)-0xc0; // calc channel
//if(ch==20) printf("%08x: %04x\n",reg,val);
switch(r&0x0f)
{
//------------------------------------------------// r volume
case 0:
SetVolumeLR(0,(u8)ch,val);
break;
//------------------------------------------------// l volume
case 2:
SetVolumeLR(1,(u8)ch,val);
break;
//------------------------------------------------// pitch
case 4:
SetPitch(ch,val);
break;
//------------------------------------------------// start
case 6:
s_chan[ch].pStart=spuMemC+((u32) val<<3);
break;
//------------------------------------------------// level with pre-calcs
case 8:
{
const u32 lval=val; // DEBUG CHECK
//---------------------------------------------//
s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0;
s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f;
s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f;
s_chan[ch].ADSRX.SustainLevel=lval & 0x000f;
//---------------------------------------------//
}
break;
//------------------------------------------------// adsr times with pre-calcs
case 10:
{
const u32 lval=val; // DEBUG CHECK
//----------------------------------------------//
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;
s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0;
s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f;
//----------------------------------------------//
}
break;
//------------------------------------------------// adsr volume... mmm have to investigate this
//case 0xC:
// break;
//------------------------------------------------//
case 0xE: // loop?
s_chan[ch].pLoop=spuMemC+((u32) val<<3);
s_chan[ch].bIgnoreLoop=1;
break;
//------------------------------------------------//
}
return;
}
switch(r)
{
//-------------------------------------------------//
case H_SPUaddr:
spuAddr = (u32) val<<3;
break;
//-------------------------------------------------//
case H_SPUdata:
spuMem[spuAddr>>1] = BFLIP16(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 s32 iv=(u32)val<<2;
if(rvb.StartAddr!=iv)
{
rvb.StartAddr=(u32)val<<2;
rvb.CurrAddr=rvb.StartAddr;
}
}
break;
//-------------------------------------------------//
case H_SPUirqAddr:
spuIrq = val;
pSpuIrq=spuMemC+((u32) val<<3);
break;
//-------------------------------------------------//
/* Volume settings appear to be at least 15-bit unsigned in this case.
Definitely NOT 15-bit signed. Probably 16-bit signed, so s16 type cast.
Check out "Chrono Cross: Shadow's End Forest"
*/
case H_SPUrvolL:
rvb.VolLeft=(s16)val;
//printf("%d\n",val);
break;
//-------------------------------------------------//
case H_SPUrvolR:
rvb.VolRight=(s16)val;
//printf("%d\n",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:
//printf("M0 %04x\n",val);
break;
//-------------------------------------------------//
case H_SPUMute2:
// printf("M1 %04x\n",val);
break;
*/
//-------------------------------------------------//
case H_SPUon1:
SoundOn(0,16,val);
break;
//-------------------------------------------------//
case H_SPUon2:
// printf("Boop: %08x: %04x\n",reg,val);
SoundOn(16,24,val);
break;
//-------------------------------------------------//
case H_SPUoff1:
SoundOff(0,16,val);
break;
//-------------------------------------------------//
case H_SPUoff2:
SoundOff(16,24,val);
// printf("Boop: %08x: %04x\n",reg,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:
rvb.Enabled&=~0xFFFF;
rvb.Enabled|=val;
break;
//-------------------------------------------------//
case H_RVBon2:
rvb.Enabled&=0xFFFF;
rvb.Enabled|=val<<16;
break;
//-------------------------------------------------//
case H_Reverb+0:
rvb.FB_SRC_A=val;
break;
case H_Reverb+2 : rvb.FB_SRC_B=(s16)val; break;
case H_Reverb+4 : rvb.IIR_ALPHA=(s16)val; break;
case H_Reverb+6 : rvb.ACC_COEF_A=(s16)val; break;
case H_Reverb+8 : rvb.ACC_COEF_B=(s16)val; break;
case H_Reverb+10 : rvb.ACC_COEF_C=(s16)val; break;
case H_Reverb+12 : rvb.ACC_COEF_D=(s16)val; break;
case H_Reverb+14 : rvb.IIR_COEF=(s16)val; break;
case H_Reverb+16 : rvb.FB_ALPHA=(s16)val; break;
case H_Reverb+18 : rvb.FB_X=(s16)val; break;
case H_Reverb+20 : rvb.IIR_DEST_A0=(s16)val; break;
case H_Reverb+22 : rvb.IIR_DEST_A1=(s16)val; break;
case H_Reverb+24 : rvb.ACC_SRC_A0=(s16)val; break;
case H_Reverb+26 : rvb.ACC_SRC_A1=(s16)val; break;
case H_Reverb+28 : rvb.ACC_SRC_B0=(s16)val; break;
case H_Reverb+30 : rvb.ACC_SRC_B1=(s16)val; break;
case H_Reverb+32 : rvb.IIR_SRC_A0=(s16)val; break;
case H_Reverb+34 : rvb.IIR_SRC_A1=(s16)val; break;
case H_Reverb+36 : rvb.IIR_DEST_B0=(s16)val; break;
case H_Reverb+38 : rvb.IIR_DEST_B1=(s16)val; break;
case H_Reverb+40 : rvb.ACC_SRC_C0=(s16)val; break;
case H_Reverb+42 : rvb.ACC_SRC_C1=(s16)val; break;
case H_Reverb+44 : rvb.ACC_SRC_D0=(s16)val; break;
case H_Reverb+46 : rvb.ACC_SRC_D1=(s16)val; break;
case H_Reverb+48 : rvb.IIR_SRC_B1=(s16)val; break;
case H_Reverb+50 : rvb.IIR_SRC_B0=(s16)val; break;
case H_Reverb+52 : rvb.MIX_DEST_A0=(s16)val; break;
case H_Reverb+54 : rvb.MIX_DEST_A1=(s16)val; break;
case H_Reverb+56 : rvb.MIX_DEST_B0=(s16)val; break;
case H_Reverb+58 : rvb.MIX_DEST_B1=(s16)val; break;
case H_Reverb+60 : rvb.IN_COEF_L=(s16)val; break;
case H_Reverb+62 : rvb.IN_COEF_R=(s16)val; break;
}
}
////////////////////////////////////////////////////////////////////////
// READ REGISTER: called by main emu
////////////////////////////////////////////////////////////////////////
u16 SPUreadRegister(u32 reg)
{
const u32 r=reg&0xfff;
if(r>=0x0c00 && r<0x0d80)
{
switch(r&0x0f)
{
case 0xC: // 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 (u16)(s_chan[ch].ADSRX.EnvelopeVol>>16);
}
case 0xE: // get loop address
{
const int ch=(r>>4)-0xc0;
if(s_chan[ch].pLoop==NULL) return 0;
return (u16)((s_chan[ch].pLoop-spuMemC)>>3);
}
}
}
switch(r)
{
case H_SPUctrl:
return spuCtrl;
case H_SPUstat:
return spuStat;
case H_SPUaddr:
return (u16)(spuAddr>>3);
case H_SPUdata:
{
u16 s=BFLIP16(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
////////////////////////////////////////////////////////////////////////
static void SoundOn(int start,int end,u16 val) // SOUND ON PSX COMAND
{
int ch;
for(ch=start;ch<end;ch++,val>>=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;
}
}
}
////////////////////////////////////////////////////////////////////////
// SOUND OFF register write
////////////////////////////////////////////////////////////////////////
static void SoundOff(int start,int end,u16 val) // SOUND OFF PSX COMMAND
{
int ch;
for(ch=start;ch<end;ch++,val>>=1) // loop channels
{
if(val&1) // && s_chan[i].bOn) mmm...
{
s_chan[ch].bStop=1;
}
}
}
////////////////////////////////////////////////////////////////////////
// FMOD register write
////////////////////////////////////////////////////////////////////////
static void FModOn(int start,int end,u16 val) // FMOD ON PSX COMMAND
{
int ch;
for(ch=start;ch<end;ch++,val>>=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
////////////////////////////////////////////////////////////////////////
static void NoiseOn(int start,int end,u16 val) // NOISE ON PSX COMMAND
{
int ch;
for(ch=start;ch<end;ch++,val>>=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 is wrong.
static void SetVolumeLR(int right, u8 ch,s16 vol) // LEFT VOLUME
{
//if(vol&0xc000)
//printf("%d %08x\n",right,vol);
if(right)
s_chan[ch].iRightVolRaw=vol;
else
s_chan[ch].iLeftVolRaw=vol;
if(vol&0x8000) // sweep?
{
s16 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;
vol&=0x3fff;
//puts("Sweep");
}
else // no sweep:
{
if(vol&0x4000)
vol=(vol&0x3FFF)-0x4000;
else
vol&=0x3FFF;
//if(vol&0x4000) // -> mmm... phase inverted? have to investigate this
// vol=0-(0x3fff-(vol&0x3fff));
//else
// vol&=0x3fff;
}
if(right)
s_chan[ch].iRightVolume=vol;
else
s_chan[ch].iLeftVolume=vol; // store volume
}
////////////////////////////////////////////////////////////////////////
// PITCH register write
////////////////////////////////////////////////////////////////////////
static void SetPitch(int ch,u16 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
}

View file

@ -1,153 +0,0 @@
/***************************************************************************
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

View file

@ -1,34 +0,0 @@
/***************************************************************************
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
//
//*************************************************************************//
static void SoundOn(int start,int end,u16 val);
static void SoundOff(int start,int end,u16 val);
static void FModOn(int start,int end,u16 val);
static void NoiseOn(int start,int end,u16 val);
static void SetVolumeLR(int right, u8 ch,s16 vol);
static void SetPitch(int ch,u16 val);
void SPUwriteRegister(u32 reg, u16 val);

View file

@ -1,383 +0,0 @@
/***************************************************************************
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/03/17 - xodnizel
// - Implemented Neill's 44.1Khz-22050Hz downsampling data
// I also need to check if the ~4 sample delay doesn't screw any sounds
// up by making things too out of phase. It could be fixed easily(elsewhere).
//
// 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
//
//*************************************************************************//
#define _IN_REVERB
// will be included from spu.c
#ifdef _IN_SPU
////////////////////////////////////////////////////////////////////////
// globals
////////////////////////////////////////////////////////////////////////
// REVERB info and timing vars...
////////////////////////////////////////////////////////////////////////
static INLINE s64 g_buffer(int iOff) // get_buffer content helper: takes care about wraps
{
s16 * p=(s16 *)spuMem;
iOff=(iOff*4)+rvb.CurrAddr;
while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);
while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
return (int)(s16)BFLIP16(*(p+iOff));
}
////////////////////////////////////////////////////////////////////////
static INLINE void s_buffer(int iOff,int iVal) // set_buffer content helper: takes care about wraps and clipping
{
s16 * p=(s16 *)spuMem;
iOff=(iOff*4)+rvb.CurrAddr;
while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);
while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
if(iVal<-32768L) iVal=-32768L;
if(iVal>32767L) iVal=32767L;
*(p+iOff)=(s16)BFLIP16((s16)iVal);
}
////////////////////////////////////////////////////////////////////////
static INLINE void s_buffer1(int iOff,int iVal) // set_buffer (+1 sample) content helper: takes care about wraps and clipping
{
s16 * p=(s16 *)spuMem;
iOff=(iOff*4)+rvb.CurrAddr+1;
while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);
while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;
*(p+iOff)=(s16)BFLIP16((s16)iVal);
}
static INLINE void MixREVERBLeftRight(s32 *oleft, s32 *oright, s32 inleft, s32 inright)
{
static s32 downbuf[2][8];
static s32 upbuf[2][8];
static int dbpos=0,ubpos=0;
static s32 downcoeffs[8]={ /* Symmetry is sexy. */
1283,5344,10895,15243,
15243,10895,5344,1283
};
int x;
if(!rvb.StartAddr) // reverb is off
{
rvb.iRVBLeft=rvb.iRVBRight=0;
return;
}
//if(inleft<-32767 || inleft>32767) printf("%d\n",inleft);
//if(inright<-32767 || inright>32767) printf("%d\n",inright);
downbuf[0][dbpos]=inleft;
downbuf[1][dbpos]=inright;
dbpos=(dbpos+1)&7;
if(dbpos&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;
s32 INPUT_SAMPLE_L=0;
s32 INPUT_SAMPLE_R=0;
for(x=0;x<8;x++)
{
INPUT_SAMPLE_L+=(downbuf[0][(dbpos+x)&7]*downcoeffs[x])>>8; /* Lose insignificant
digits to prevent
overflow(check this) */
INPUT_SAMPLE_R+=(downbuf[1][(dbpos+x)&7]*downcoeffs[x])>>8;
}
INPUT_SAMPLE_L>>=(16-8);
INPUT_SAMPLE_R>>=(16-8);
{
const s64 IIR_INPUT_A0 = ((g_buffer(rvb.IIR_SRC_A0) * rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_L * rvb.IN_COEF_L)>>15);
const s64 IIR_INPUT_A1 = ((g_buffer(rvb.IIR_SRC_A1) * rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_R * rvb.IN_COEF_R)>>15);
const s64 IIR_INPUT_B0 = ((g_buffer(rvb.IIR_SRC_B0) * rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_L * rvb.IN_COEF_L)>>15);
const s64 IIR_INPUT_B1 = ((g_buffer(rvb.IIR_SRC_B1) * rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_R * rvb.IN_COEF_R)>>15);
const s64 IIR_A0 = ((IIR_INPUT_A0 * rvb.IIR_ALPHA)>>15) + ((g_buffer(rvb.IIR_DEST_A0) * (32768L - rvb.IIR_ALPHA))>>15);
const s64 IIR_A1 = ((IIR_INPUT_A1 * rvb.IIR_ALPHA)>>15) + ((g_buffer(rvb.IIR_DEST_A1) * (32768L - rvb.IIR_ALPHA))>>15);
const s64 IIR_B0 = ((IIR_INPUT_B0 * rvb.IIR_ALPHA)>>15) + ((g_buffer(rvb.IIR_DEST_B0) * (32768L - rvb.IIR_ALPHA))>>15);
const s64 IIR_B1 = ((IIR_INPUT_B1 * rvb.IIR_ALPHA)>>15) + ((g_buffer(rvb.IIR_DEST_B1) * (32768L - rvb.IIR_ALPHA))>>15);
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)>>15) +
((g_buffer(rvb.ACC_SRC_B0) * rvb.ACC_COEF_B)>>15) +
((g_buffer(rvb.ACC_SRC_C0) * rvb.ACC_COEF_C)>>15) +
((g_buffer(rvb.ACC_SRC_D0) * rvb.ACC_COEF_D)>>15);
ACC1 = ((g_buffer(rvb.ACC_SRC_A1) * rvb.ACC_COEF_A)>>15) +
((g_buffer(rvb.ACC_SRC_B1) * rvb.ACC_COEF_B)>>15) +
((g_buffer(rvb.ACC_SRC_C1) * rvb.ACC_COEF_C)>>15) +
((g_buffer(rvb.ACC_SRC_D1) * rvb.ACC_COEF_D)>>15);
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)>>15));
s_buffer(rvb.MIX_DEST_A1, ACC1 - ((FB_A1 * rvb.FB_ALPHA)>>15));
s_buffer(rvb.MIX_DEST_B0, ((rvb.FB_ALPHA * ACC0)>>15) - ((FB_A0 * (int)(rvb.FB_ALPHA^0xFFFF8000))>>15) - ((FB_B0 * rvb.FB_X)>>15));
s_buffer(rvb.MIX_DEST_B1, ((rvb.FB_ALPHA * ACC1)>>15) - ((FB_A1 * (int)(rvb.FB_ALPHA^0xFFFF8000))>>15) - ((FB_B1 * rvb.FB_X)>>15));
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 = ((s64)rvb.iRVBLeft * rvb.VolLeft) >> 14;
rvb.iRVBRight = ((s64)rvb.iRVBRight * rvb.VolRight) >> 14;
upbuf[0][ubpos]=rvb.iRVBLeft;
upbuf[1][ubpos]=rvb.iRVBRight;
ubpos=(ubpos+1)&7;
} // Bracket hack(et).
}
else // -> reverb off
{
rvb.iRVBLeft=rvb.iRVBRight=0;
return;
}
rvb.CurrAddr++;
if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr;
}
else
{
upbuf[0][ubpos]=0;
upbuf[1][ubpos]=0;
ubpos=(ubpos+1)&7;
}
{
s32 retl=0,retr=0;
for(x=0;x<8;x++)
{
retl+=(upbuf[0][(ubpos+x)&7]*downcoeffs[x])>>8;
retr+=(upbuf[1][(ubpos+x)&7]*downcoeffs[x])>>8;
}
retl>>=(16-8-1); /* -1 To adjust for the null padding. */
retr>>=(16-8-1);
*oleft+=retl;
*oright+=retr;
}
}
////////////////////////////////////////////////////////////////////////
#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;
-----------------------------------------------------------------------------
*/

View file

@ -1,641 +0,0 @@
/***************************************************************************
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:
//
// 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
//
//*************************************************************************//
#define _IN_SPU
#include "../peops/stdafx.h"
#include "../peops/externals.h"
#include "../peops/regs.h"
#include "../peops/registers.h"
#include "../peops/spu.h"
void SPUirq(void) ;
//#include "PsxMem.h"
//#include "driver.h"
////////////////////////////////////////////////////////////////////////
// globals
////////////////////////////////////////////////////////////////////////
// psx buffer / addresses
static u16 regArea[0x200];
static u16 spuMem[256*1024];
static u8 * spuMemC;
static u8 * pSpuIrq=0;
static u8 * pSpuBuffer;
// user settings
static int iVolume;
// MAIN infos struct for each channel
static SPUCHAN s_chan[MAXCHAN+1]; // channel + 1 infos (1 is security for fmod handling)
static REVERBInfo rvb;
static u32 dwNoiseVal=1; // global noise generator
static u16 spuCtrl=0; // some vars to store psx reg infos
static u16 spuStat=0;
static u16 spuIrq=0;
static u32 spuAddr=0xffffffff; // address into spu mem
static int bSPUIsOpen=0;
static const int f[5][2] = {
{ 0, 0 },
{ 60, 0 },
{ 115, -52 },
{ 98, -55 },
{ 122, -60 } };
s16 * pS;
static s32 ttemp;
////////////////////////////////////////////////////////////////////////
// CODE AREA
////////////////////////////////////////////////////////////////////////
// dirty inline func includes
#include "../peops/reverb.c"
#include "../peops/adsr.c"
// Try this to increase speed.
#include "../peops/registers.c"
#include "../peops/dma.c"
////////////////////////////////////////////////////////////////////////
// helpers for so-called "gauss interpolation"
#define gval0 (((int *)(&s_chan[ch].SB[29]))[gpos])
#define gval(x) (((int *)(&s_chan[ch].SB[29]))[(gpos+x)&3])
#include "gauss_i.h"
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// START SOUND... called by main thread to setup a new sound on a channel
////////////////////////////////////////////////////////////////////////
static INLINE void StartSound(int ch)
{
StartADSR(ch);
s_chan[ch].pCurr=s_chan[ch].pStart; // set sample start
s_chan[ch].s_1=0; // init mixing vars
s_chan[ch].s_2=0;
s_chan[ch].iSBPos=28;
s_chan[ch].bNew=0; // init channel flags
s_chan[ch].bStop=0;
s_chan[ch].bOn=1;
s_chan[ch].SB[29]=0; // init our interpolation helpers
s_chan[ch].SB[30]=0;
s_chan[ch].spos=0x40000L;s_chan[ch].SB[28]=0; // -> start with more decoding
}
////////////////////////////////////////////////////////////////////////
// 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!
////////////////////////////////////////////////////////////////////////
static u32 sampcount;
static u32 decaybegin;
static u32 decayend;
// Counting to 65536 results in full volume offage.
void setlength(s32 stop, s32 fade)
{
if(stop==~0)
{
decaybegin=~0;
}
else
{
stop=(stop*441)/10;
fade=(fade*441)/10;
decaybegin=stop;
decayend=stop+fade;
}
}
#define CLIP(_x) {if(_x>32767) _x=32767; if(_x<-32767) _x=-32767;}
int SPUasync(u32 cycles)
{
int volmul=iVolume;
static s32 dosampies;
s32 temp;
ttemp+=cycles;
dosampies=ttemp/384;
if(!dosampies) return(1);
ttemp-=dosampies*384;
temp=dosampies;
while(temp)
{
s32 revLeft=0, revRight=0;
s32 sl=0, sr=0;
int ch,fa;
temp--;
//--------------------------------------------------//
//- main channel loop -//
//--------------------------------------------------//
{
for(ch=0;ch<MAXCHAN;ch++) // loop em all.
{
if(s_chan[ch].bNew) StartSound(ch); // start new sound
if(!s_chan[ch].bOn) continue; // channel not playing? next
if(s_chan[ch].iActFreq!=s_chan[ch].iUsedFreq) // new psx frequency?
{
s_chan[ch].iUsedFreq=s_chan[ch].iActFreq; // -> take it and calc steps
s_chan[ch].sinc=s_chan[ch].iRawPitch<<4;
if(!s_chan[ch].sinc) s_chan[ch].sinc=1;
}
while(s_chan[ch].spos>=0x10000L)
{
if(s_chan[ch].iSBPos==28) // 28 reached?
{
int predict_nr,shift_factor,flags,d,s;
u8* start;unsigned int nSample;
int s_1,s_2;
start=s_chan[ch].pCurr; // set up the current pos
if (start == (u8*)-1) // special "stop" sign
{
s_chan[ch].bOn=0; // -> turn everything off
s_chan[ch].ADSRX.lVolume=0;
s_chan[ch].ADSRX.EnvelopeVol=0;
goto ENDX; // -> and done for this channel
}
s_chan[ch].iSBPos=0; // Reset buffer play index.
//////////////////////////////////////////// spu irq handler here? mmm... do it later
s_1=s_chan[ch].s_1;
s_2=s_chan[ch].s_2;
predict_nr=(int)*start;start++;
shift_factor=predict_nr&0xf;
predict_nr >>= 4;
flags=(int)*start;start++;
// -------------------------------------- //
// Decode new samples into s_chan[ch].SB[0 through 27]
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);
s_chan[ch].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;
s_chan[ch].SB[nSample++]=fa;
}
//////////////////////////////////////////// irq check
if(spuCtrl&0x40) // 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 > s_chan[ch].pLoop-16 &&
pSpuIrq <= s_chan[ch].pLoop)))
{
//extern s32 spuirqvoodoo;
s_chan[ch].iIrqDone=1; // -> debug flag
SPUirq();
//puts("IRQ");
//if(spuirqvoodoo!=-1)
//{
// spuirqvoodoo=temp*384;
// temp=0;
//}
}
}
//////////////////////////////////////////// flag handler
if((flags&4) && (!s_chan[ch].bIgnoreLoop))
s_chan[ch].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 || s_chan[ch].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 = (u8*)-1;
}
else
{
start = s_chan[ch].pLoop;
}
}
s_chan[ch].pCurr=start; // store values for next cycle
s_chan[ch].s_1=s_1;
s_chan[ch].s_2=s_2;
////////////////////////////////////////////
}
fa=s_chan[ch].SB[s_chan[ch].iSBPos++]; // get sample data
if((spuCtrl&0x4000)==0) fa=0; // muted?
else CLIP(fa);
{
int gpos;
gpos = s_chan[ch].SB[28];
gval0 = fa;
gpos = (gpos+1) & 3;
s_chan[ch].SB[28] = gpos;
}
s_chan[ch].spos -= 0x10000L;
}
////////////////////////////////////////////////
// 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
if(s_chan[ch].bNoise)
{
//puts("Noise");
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=s_chan[ch].iOldNoise+((fa-s_chan[ch].iOldNoise)/((0x001f-((spuCtrl&0x3f00)>>9))+1));
if(fa>32767L) fa=32767L;
if(fa<-32767L) fa=-32767L;
s_chan[ch].iOldNoise=fa;
} //----------------------------------------
else // NO NOISE (NORMAL SAMPLE DATA) HERE
{
int vl, vr, gpos;
vl = (s_chan[ch].spos >> 6) & ~3;
gpos = s_chan[ch].SB[28];
vr=(gauss[vl]*gval0)>>9;
vr+=(gauss[vl+1]*gval(1))>>9;
vr+=(gauss[vl+2]*gval(2))>>9;
vr+=(gauss[vl+3]*gval(3))>>9;
fa = vr>>2;
}
s_chan[ch].sval = (MixADSR(ch) * fa)>>10; // / 1023; // add adsr
if(s_chan[ch].bFMod==2) // fmod freq channel
{
int NP=s_chan[ch+1].iRawPitch;
NP=((32768L+s_chan[ch].sval)*NP)>>15; ///32768L;
if(NP>0x3fff) NP=0x3fff;
if(NP<0x1) NP=0x1;
// mmmm... if I do this, all is screwed
// s_chan[ch+1].iRawPitch=NP;
NP=(44100L*NP)/(4096L); // calc frequency
s_chan[ch+1].iActFreq=NP;
s_chan[ch+1].iUsedFreq=NP;
s_chan[ch+1].sinc=(((NP/10)<<16)/4410);
if(!s_chan[ch+1].sinc) s_chan[ch+1].sinc=1;
// mmmm... set up freq decoding positions?
// s_chan[ch+1].iSBPos=28;
// s_chan[ch+1].spos=0x10000L;
}
else
{
//////////////////////////////////////////////
// ok, left/right sound volume (psx volume goes from 0 ... 0x3fff)
int tmpl,tmpr;
if (1) //ao_channel_enable[ch+PSF_1]) {
{
tmpl=(s_chan[ch].sval*s_chan[ch].iLeftVolume)>>14;
tmpr=(s_chan[ch].sval*s_chan[ch].iRightVolume)>>14;
} else {
tmpl = 0;
tmpr = 0;
}
sl+=tmpl;
sr+=tmpr;
if(((rvb.Enabled>>ch)&1) && (spuCtrl&0x80))
{
revLeft+=tmpl;
revRight+=tmpr;
}
}
s_chan[ch].spos += s_chan[ch].sinc;
ENDX: ;
}
}
///////////////////////////////////////////////////////
// mix all channels (including reverb) into one buffer
MixREVERBLeftRight(&sl,&sr,revLeft,revRight);
// printf("sampcount %d decaybegin %d decayend %d\n", sampcount, decaybegin, decayend);
if(sampcount>=decaybegin)
{
s32 dmul;
if(decaybegin!=~0) // Is anyone REALLY going to be playing a song
// for 13 hours?
{
if(sampcount>=decayend)
{
// ao_song_done = 1;
return(0);
}
dmul=256-(256*(sampcount-decaybegin)/(decayend-decaybegin));
sl=(sl*dmul)>>8;
sr=(sr*dmul)>>8;
}
}
sampcount++;
sl=(sl*volmul)>>8;
sr=(sr*volmul)>>8;
//{
// static double asl=0;
// static double asr=0;
// asl+=(sl-asl)/5;
// asr+=(sl-asr)/5;
//sl-=asl;
//sr-=asr;
// if(sl>32767 || sl < -32767) printf("Left: %d, %f\n",sl,asl);
// if(sr>32767 || sr < -32767) printf("Right: %d, %f\n",sl,asl);
//}
if(sl>32767) sl=32767; if(sl<-32767) sl=-32767;
if(sr>32767) sr=32767; if(sr<-32767) sr=-32767;
*pS++=sl;
*pS++=sr;
}
return(1);
}
void SPU_flushboot(void)
{
if((u8*)pS>((u8*)pSpuBuffer+1024))
{
spu_update((u8*)pSpuBuffer,(u8*)pS-(u8*)pSpuBuffer);
pS=(s16 *)pSpuBuffer;
}
}
#ifdef TIMEO
static u64 begintime;
static u64 gettime64(void)
{
struct timeval tv;
u64 ret;
gettimeofday(&tv,0);
ret=tv.tv_sec;
ret*=1000000;
ret+=tv.tv_usec;
return(ret);
}
#endif
////////////////////////////////////////////////////////////////////////
// INIT/EXIT STUFF
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// SPUINIT: this func will be called first by the main emu
////////////////////////////////////////////////////////////////////////
int SPUinit(void)
{
spuMemC=(u8*)spuMem; // just small setup
memset((void *)s_chan,0,MAXCHAN*sizeof(SPUCHAN));
memset((void *)&rvb,0,sizeof(REVERBInfo));
memset(regArea,0,sizeof(regArea));
memset(spuMem,0,sizeof(spuMem));
InitADSR();
sampcount=ttemp=0;
#ifdef TIMEO
begintime=gettime64();
#endif
return 0;
}
////////////////////////////////////////////////////////////////////////
// SETUPSTREAMS: init most of the spu buffers
////////////////////////////////////////////////////////////////////////
void SetupStreams(void)
{
int i;
pSpuBuffer=(u8*)malloc(32768); // alloc mixing buffer
pS=(s16 *)pSpuBuffer;
for(i=0;i<MAXCHAN;i++) // loop sound channels
{
s_chan[i].ADSRX.SustainLevel = 1024; // -> init sustain
s_chan[i].iIrqDone=0;
s_chan[i].pLoop=spuMemC;
s_chan[i].pStart=spuMemC;
s_chan[i].pCurr=spuMemC;
}
}
////////////////////////////////////////////////////////////////////////
// REMOVESTREAMS: free most buffer
////////////////////////////////////////////////////////////////////////
void RemoveStreams(void)
{
free(pSpuBuffer); // free mixing buffer
pSpuBuffer=NULL;
#ifdef TIMEO
{
u64 tmp;
tmp=gettime64();
tmp-=begintime;
if(tmp)
tmp=(u64)sampcount*1000000/tmp;
printf("%lld samples per second\n",tmp);
}
#endif
}
////////////////////////////////////////////////////////////////////////
// SPUOPEN: called by main emu after init
////////////////////////////////////////////////////////////////////////
int SPUopen(void)
{
if(bSPUIsOpen) return 0; // security for some stupid main emus
spuIrq=0;
spuStat=spuCtrl=0;
spuAddr=0xffffffff;
dwNoiseVal=1;
spuMemC=(u8*)spuMem;
memset((void *)s_chan,0,(MAXCHAN+1)*sizeof(SPUCHAN));
pSpuIrq=0;
iVolume=255; //85;
SetupStreams(); // prepare streaming
bSPUIsOpen=1;
return 1;
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// SPUCLOSE: called before shutdown
////////////////////////////////////////////////////////////////////////
int SPUclose(void)
{
if(!bSPUIsOpen) return 0; // some security
bSPUIsOpen=0; // no more open
RemoveStreams(); // no more streaming
return 0;
}
////////////////////////////////////////////////////////////////////////
// SPUSHUTDOWN: called by main emu on final exit
////////////////////////////////////////////////////////////////////////
int SPUshutdown(void)
{
return 0;
}
void SPUinjectRAMImage(u16 *pIncoming)
{
int i;
for (i = 0; i < (256*1024); i++)
{
spuMem[i] = pIncoming[i];
}
}

View file

@ -1,39 +0,0 @@
/***************************************************************************
spu.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 sexyd_update(unsigned char* pSound,long lBytes);
int SPUasync(u32 cycles);
void SPU_flushboot(void);
int SPUinit(void);
int SPUopen(void);
int SPUclose(void);
int SPUshutdown(void);
void SPUinjectRAMImage(u16 *pIncoming);
void SPUreadDMAMem(u32 usPSXMem,int iSize);
void SPUwriteDMAMem(u32 usPSXMem,int iSize);
u16 SPUreadRegister(u32 reg);

View file

@ -1,29 +0,0 @@
/***************************************************************************
StdAfx.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
//
//*************************************************************************//
#include <stdlib.h>
#include <string.h>
#include <math.h>

View file

@ -1,656 +0,0 @@
/***************************************************************************
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:
//
// 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
////////////////////////////////////////////////////////////////////////
unsigned long 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;
}
}
////////////////////////////////////////////////////////////////////////
static INLINE void StartADSR(int ch) // MIX ADSR
{
s_chan[ch].ADSRX.lVolume=1; // and init some adsr vars
s_chan[ch].ADSRX.State=0;
s_chan[ch].ADSRX.EnvelopeVol=0;
}
////////////////////////////////////////////////////////////////////////
static INLINE int MixADSR(int ch) // MIX ADSR
{
if(s_chan[ch].bStop) // should be stopped:
{ // do release
if(s_chan[ch].ADSRX.ReleaseModeExp)
{
switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
{
case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +0 + 32]; break;
case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +4 + 32]; break;
case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +6 + 32]; break;
case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +8 + 32]; break;
case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +9 + 32]; break;
case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +10+ 32]; break;
case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +11+ 32]; break;
case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +12+ 32]; break;
}
}
else
{
s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x0C + 32];
}
if(s_chan[ch].ADSRX.EnvelopeVol<0)
{
s_chan[ch].ADSRX.EnvelopeVol=0;
s_chan[ch].bOn=0;
//s_chan[ch].bReverb=0;
//s_chan[ch].bNoise=0;
}
s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
return s_chan[ch].ADSRX.lVolume;
}
else // not stopped yet?
{
if(s_chan[ch].ADSRX.State==0) // -> attack
{
if(s_chan[ch].ADSRX.AttackModeExp)
{
if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
else
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x18 + 32];
}
else
{
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
}
if(s_chan[ch].ADSRX.EnvelopeVol<0)
{
s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
s_chan[ch].ADSRX.State=1;
}
s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
return s_chan[ch].ADSRX.lVolume;
}
//--------------------------------------------------//
if(s_chan[ch].ADSRX.State==1) // -> decay
{
switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
{
case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+0 + 32]; break;
case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+4 + 32]; break;
case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+6 + 32]; break;
case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+8 + 32]; break;
case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+9 + 32]; break;
case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+10+ 32]; break;
case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+11+ 32]; break;
case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+12+ 32]; break;
}
if(s_chan[ch].ADSRX.EnvelopeVol<0) s_chan[ch].ADSRX.EnvelopeVol=0;
if(((s_chan[ch].ADSRX.EnvelopeVol>>27)&0xF) <= s_chan[ch].ADSRX.SustainLevel)
{
s_chan[ch].ADSRX.State=2;
}
s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
return s_chan[ch].ADSRX.lVolume;
}
//--------------------------------------------------//
if(s_chan[ch].ADSRX.State==2) // -> sustain
{
if(s_chan[ch].ADSRX.SustainIncrease)
{
if(s_chan[ch].ADSRX.SustainModeExp)
{
if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
else
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x18 + 32];
}
else
{
s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
}
if(s_chan[ch].ADSRX.EnvelopeVol<0)
{
s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
}
}
else
{
if(s_chan[ch].ADSRX.SustainModeExp)
{
switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
{
case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +0 + 32];break;
case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +4 + 32];break;
case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +6 + 32];break;
case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +8 + 32];break;
case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +9 + 32];break;
case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +10+ 32];break;
case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +11+ 32];break;
case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +12+ 32];break;
}
}
else
{
s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x0F + 32];
}
if(s_chan[ch].ADSRX.EnvelopeVol<0)
{
s_chan[ch].ADSRX.EnvelopeVol=0;
}
}
s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
return s_chan[ch].ADSRX.lVolume;
}
}
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<<value)*292)/10000
------------------------------------
3. Sustain rate value (linear mode)
Sustain rate range: 0 -> 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<<value)*446)/10000
------------------------------------
Other notes:
Log stuff not figured out. You may get some clues from the "Decay rate"
stuff above. For emu purposes it may not be important - use linear
approx.
To get timings in millisecs, multiply frames by 20.
- James Higgs 17/6/2000
james7780@yahoo.com
//---------------------------------------------------------------
OLD adsr mixing according to james' rules... has to be called
every one millisecond
long v,v2,lT,l1,l2,l3;
if(s_chan[ch].bStop) // psx wants to stop? -> 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<l1) // -> 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(lT<l1) // attack
{ // no exp mode used (yet)
// if(s_chan[ch].ADSR.AttackModeExp)
// {
// v=(v*lT)/l1;
// }
// else
{
v=(v*lT)/l1;
}
if(v==0) v=1;
}
else // decay
{ // should be exp, but who cares? ;)
l2=s_chan[ch].ADSR.DecayTime;
v2=s_chan[ch].ADSR.SustainLevel;
lT-=l1;
if(lT<l2)
{
v-=(((v-v2)*lT)/l2);
}
else // sustain
{ // no exp mode used (yet)
l3=s_chan[ch].ADSR.SustainTime;
lT-=l2;
if(s_chan[ch].ADSR.SustainModeDec>0)
{
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]
-----------------------------------------------------------------------------
*/

View file

@ -1,28 +0,0 @@
/***************************************************************************
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(int ch);
INLINE int MixADSR(int ch);

View file

@ -1,175 +0,0 @@
/***************************************************************************
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:
//
// 2004/04/04 - Pete
// - changed plugin to emulate PS2 spu
//
// 2002/05/15 - Pete
// - generic cleanup for the Peops release
//
//*************************************************************************//
#include "../peops2/stdafx.h"
#define _IN_DMA
#include "../peops2/externals.h"
#include "../peops2/registers.h"
//#include "debug.h"
extern uint32 psx_ram[(2*1024*1024)/4];
////////////////////////////////////////////////////////////////////////
// READ DMA (many values)
////////////////////////////////////////////////////////////////////////
EXPORT_GCC void CALLBACK SPU2readDMA4Mem(u32 usPSXMem,int iSize)
{
int i;
u16 *ram16 = (u16 *)&psx_ram[0];
for(i=0;i<iSize;i++)
{
ram16[usPSXMem>>1]=spuMem[spuAddr2[0]]; // spu addr 0 got by writeregister
usPSXMem+=2;
spuAddr2[0]++; // inc spu addr
if(spuAddr2[0]>0xfffff) spuAddr2[0]=0; // wrap
}
spuAddr2[0]+=0x20; //?????
iSpuAsyncWait=0;
// got from J.F. and Kanodin... is it needed?
regArea[(PS2_C0_ADMAS)>>1]=0; // Auto DMA complete
spuStat2[0]=0x80; // DMA complete
}
EXPORT_GCC void CALLBACK SPU2readDMA7Mem(u32 usPSXMem,int iSize)
{
int i;
u16 *ram16 = (u16 *)&psx_ram[0];
for(i=0;i<iSize;i++)
{
ram16[usPSXMem>>1]=spuMem[spuAddr2[1]]; // spu addr 1 got by writeregister
usPSXMem+=2;
spuAddr2[1]++; // inc spu addr
if(spuAddr2[1]>0xfffff) spuAddr2[1]=0; // wrap
}
spuAddr2[1]+=0x20; //?????
iSpuAsyncWait=0;
// got from J.F. and Kanodin... is it needed?
regArea[(PS2_C1_ADMAS)>>1]=0; // Auto DMA complete
spuStat2[1]=0x80; // DMA complete
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// 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 (many values)
////////////////////////////////////////////////////////////////////////
EXPORT_GCC void CALLBACK SPU2writeDMA4Mem(u32 usPSXMem,int iSize)
{
int i;
u16 *ram16 = (u16 *)&psx_ram[0];
for(i=0;i<iSize;i++)
{
spuMem[spuAddr2[0]] = ram16[usPSXMem>>1]; // spu addr 0 got by writeregister
usPSXMem+=2;
spuAddr2[0]++; // inc spu addr
if(spuAddr2[0]>0xfffff) spuAddr2[0]=0; // wrap
}
iSpuAsyncWait=0;
// got from J.F. and Kanodin... is it needed?
spuStat2[0]=0x80; // DMA complete
}
EXPORT_GCC void CALLBACK SPU2writeDMA7Mem(u32 usPSXMem,int iSize)
{
int i;
u16 *ram16 = (u16 *)&psx_ram[0];
for(i=0;i<iSize;i++)
{
spuMem[spuAddr2[1]] = ram16[usPSXMem>>1]; // spu addr 1 got by writeregister
spuAddr2[1]++; // inc spu addr
if(spuAddr2[1]>0xfffff) spuAddr2[1]=0; // wrap
}
iSpuAsyncWait=0;
// got from J.F. and Kanodin... is it needed?
spuStat2[1]=0x80; // DMA complete
}
////////////////////////////////////////////////////////////////////////
// INTERRUPTS
////////////////////////////////////////////////////////////////////////
void InterruptDMA4(void)
{
// taken from linuzappz NULL spu2
// spu2Rs16(CORE0_ATTR)&= ~0x30;
// spu2Rs16(REG__1B0) = 0;
// spu2Rs16(SPU2_STATX_WRDY_M)|= 0x80;
spuCtrl2[0]&=~0x30;
regArea[(PS2_C0_ADMAS)>>1]=0;
spuStat2[0]|=0x80;
}
EXPORT_GCC void CALLBACK SPU2interruptDMA4(void)
{
InterruptDMA4();
}
void InterruptDMA7(void)
{
// taken from linuzappz NULL spu2
// spu2Rs16(CORE1_ATTR)&= ~0x30;
// spu2Rs16(REG__5B0) = 0;
// spu2Rs16(SPU2_STATX_DREQ)|= 0x80;
spuCtrl2[1]&=~0x30;
regArea[(PS2_C1_ADMAS)>>1]=0;
spuStat2[1]|=0x80;
}
EXPORT_GCC void CALLBACK SPU2interruptDMA7(void)
{
InterruptDMA7();
}

View file

@ -1,29 +0,0 @@
/***************************************************************************
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
//
//*************************************************************************//
void InterruptDMA4(void);
void InterruptDMA7(void);

View file

@ -1,385 +0,0 @@
/***************************************************************************
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:
//
// 2004/04/04 - Pete
// - changed plugin to emulate PS2 spu
//
// 2002/04/04 - Pete
// - increased channel struct for interpolation
//
// 2002/05/15 - Pete
// - generic cleanup for the Peops release
//
//*************************************************************************//
#ifndef PEOPS2_EXTERNALS
#define PEOPS2_EXTERNALS
#include "ao.h"
typedef int8 s8;
typedef int16 s16;
typedef int32 s32;
typedef int64 s64;
typedef uint8 u8;
typedef uint16 u16;
typedef uint32 u32;
typedef uint64 u64;
#if LSB_FIRST
static INLINE u16 BFLIP16(u16 x)
{
return x;
}
#else
static INLINE u16 BFLIP16(u16 x)
{
return( ((x>>8)&0xFF)| ((x&0xFF)<<8) );
}
#endif
/////////////////////////////////////////////////////////
// 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 76800
// 137 ms test buffer... if less than that is buffered, a new upload will happen
#define TESTSIZE 26304
// num of channels
#define MAXCHAN 48
#define HLFCHAN 24
// ~ 1 ms of data (was 45)
#define NSSIZE 1
//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 iStartAdr;
int iLoopAdr;
int iNextAdr;
int bOn; // is channel active (sample playing?)
int bStop; // is channel stopped (sample _can_ still be playing, ADSR Release phase)
int bEndPoint; // end point reached
int bReverbL; // can we do reverb on this channel? must have ctrl register bit, to get active
int bReverbR;
int bVolumeL; // Volume on/off
int bVolumeR;
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 bNoise; // noise active flag
int bFMod; // freq mod (0=off, 1=sound channel, 2=freq channel)
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 EndAddr; // reverb area end addr in samples
int CurrAddr; // reverb area curr addr in samples
int VolLeft;
int VolRight;
int iLastRVBLeft;
int iLastRVBRight;
int iRVBLeft;
int iRVBRight;
int iCnt;
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;
// MISC
extern SPUCHAN s_chan[];
extern REVERBInfo rvb[];
extern unsigned long dwNoiseVal;
extern unsigned short spuCtrl2[];
extern unsigned short spuStat2[];
extern unsigned long spuIrq2[];
extern unsigned long spuAddr2[];
extern unsigned long spuRvbAddr2[];
extern unsigned long spuRvbAEnd2[];
extern int bEndThread;
extern int bThreadEnded;
extern int bSpuInit;
extern int SSumR[];
extern int SSumL[];
extern int iCycle;
extern short * pS;
extern unsigned long dwNewChannel2[];
extern unsigned long dwEndChannel2[];
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[];
#endif
#endif // PEOPS2_EXTERNALS

View file

@ -1,162 +0,0 @@
/***************************************************************************
gauss_i.h - description
-----------------------
begin : Sun Feb 08 2003
copyright : (C) 2003 by Chris Moeller, eh, whatever
email : chris@kode54.tk
***************************************************************************/
/***************************************************************************
* *
* 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/08 - kode54
// - generated by interleaving table from gauss.h from the libopenspc
// project; a gaussian bell curve table logged from the SPC-700,
// though Neill says he logged the same curve from a PSX SPU. Also
// says that interleaving the coefficients together runs faster. Meh.
//
//*************************************************************************//
#ifndef GAUSS_H
#define GAUSS_H
static const int gauss[]={
0x172, 0x519, 0x176, 0x000, 0x16E, 0x519, 0x17A, 0x000,
0x16A, 0x518, 0x17D, 0x000, 0x166, 0x518, 0x181, 0x000,
0x162, 0x518, 0x185, 0x000, 0x15F, 0x518, 0x189, 0x000,
0x15B, 0x518, 0x18D, 0x000, 0x157, 0x517, 0x191, 0x000,
0x153, 0x517, 0x195, 0x000, 0x150, 0x517, 0x19A, 0x000,
0x14C, 0x516, 0x19E, 0x000, 0x148, 0x516, 0x1A2, 0x000,
0x145, 0x515, 0x1A6, 0x000, 0x141, 0x514, 0x1AA, 0x000,
0x13E, 0x514, 0x1AE, 0x000, 0x13A, 0x513, 0x1B2, 0x000,
0x137, 0x512, 0x1B7, 0x001, 0x133, 0x511, 0x1BB, 0x001,
0x130, 0x511, 0x1BF, 0x001, 0x12C, 0x510, 0x1C3, 0x001,
0x129, 0x50F, 0x1C8, 0x001, 0x125, 0x50E, 0x1CC, 0x001,
0x122, 0x50D, 0x1D0, 0x001, 0x11E, 0x50C, 0x1D5, 0x001,
0x11B, 0x50B, 0x1D9, 0x001, 0x118, 0x50A, 0x1DD, 0x001,
0x114, 0x508, 0x1E2, 0x001, 0x111, 0x507, 0x1E6, 0x002,
0x10E, 0x506, 0x1EB, 0x002, 0x10B, 0x504, 0x1EF, 0x002,
0x107, 0x503, 0x1F3, 0x002, 0x104, 0x502, 0x1F8, 0x002,
0x101, 0x500, 0x1FC, 0x002, 0x0FE, 0x4FF, 0x201, 0x002,
0x0FB, 0x4FD, 0x205, 0x003, 0x0F8, 0x4FB, 0x20A, 0x003,
0x0F5, 0x4FA, 0x20F, 0x003, 0x0F2, 0x4F8, 0x213, 0x003,
0x0EF, 0x4F6, 0x218, 0x003, 0x0EC, 0x4F5, 0x21C, 0x004,
0x0E9, 0x4F3, 0x221, 0x004, 0x0E6, 0x4F1, 0x226, 0x004,
0x0E3, 0x4EF, 0x22A, 0x004, 0x0E0, 0x4ED, 0x22F, 0x004,
0x0DD, 0x4EB, 0x233, 0x005, 0x0DA, 0x4E9, 0x238, 0x005,
0x0D7, 0x4E7, 0x23D, 0x005, 0x0D4, 0x4E5, 0x241, 0x005,
0x0D2, 0x4E3, 0x246, 0x006, 0x0CF, 0x4E0, 0x24B, 0x006,
0x0CC, 0x4DE, 0x250, 0x006, 0x0C9, 0x4DC, 0x254, 0x006,
0x0C7, 0x4D9, 0x259, 0x007, 0x0C4, 0x4D7, 0x25E, 0x007,
0x0C1, 0x4D5, 0x263, 0x007, 0x0BF, 0x4D2, 0x267, 0x008,
0x0BC, 0x4D0, 0x26C, 0x008, 0x0BA, 0x4CD, 0x271, 0x008,
0x0B7, 0x4CB, 0x276, 0x009, 0x0B4, 0x4C8, 0x27B, 0x009,
0x0B2, 0x4C5, 0x280, 0x009, 0x0AF, 0x4C3, 0x284, 0x00A,
0x0AD, 0x4C0, 0x289, 0x00A, 0x0AB, 0x4BD, 0x28E, 0x00A,
0x0A8, 0x4BA, 0x293, 0x00B, 0x0A6, 0x4B7, 0x298, 0x00B,
0x0A3, 0x4B5, 0x29D, 0x00B, 0x0A1, 0x4B2, 0x2A2, 0x00C,
0x09F, 0x4AF, 0x2A6, 0x00C, 0x09C, 0x4AC, 0x2AB, 0x00D,
0x09A, 0x4A9, 0x2B0, 0x00D, 0x098, 0x4A6, 0x2B5, 0x00E,
0x096, 0x4A2, 0x2BA, 0x00E, 0x093, 0x49F, 0x2BF, 0x00F,
0x091, 0x49C, 0x2C4, 0x00F, 0x08F, 0x499, 0x2C9, 0x00F,
0x08D, 0x496, 0x2CE, 0x010, 0x08B, 0x492, 0x2D3, 0x010,
0x089, 0x48F, 0x2D8, 0x011, 0x086, 0x48C, 0x2DC, 0x011,
0x084, 0x488, 0x2E1, 0x012, 0x082, 0x485, 0x2E6, 0x013,
0x080, 0x481, 0x2EB, 0x013, 0x07E, 0x47E, 0x2F0, 0x014,
0x07C, 0x47A, 0x2F5, 0x014, 0x07A, 0x477, 0x2FA, 0x015,
0x078, 0x473, 0x2FF, 0x015, 0x076, 0x470, 0x304, 0x016,
0x075, 0x46C, 0x309, 0x017, 0x073, 0x468, 0x30E, 0x017,
0x071, 0x465, 0x313, 0x018, 0x06F, 0x461, 0x318, 0x018,
0x06D, 0x45D, 0x31D, 0x019, 0x06B, 0x459, 0x322, 0x01A,
0x06A, 0x455, 0x326, 0x01B, 0x068, 0x452, 0x32B, 0x01B,
0x066, 0x44E, 0x330, 0x01C, 0x064, 0x44A, 0x335, 0x01D,
0x063, 0x446, 0x33A, 0x01D, 0x061, 0x442, 0x33F, 0x01E,
0x05F, 0x43E, 0x344, 0x01F, 0x05E, 0x43A, 0x349, 0x020,
0x05C, 0x436, 0x34E, 0x020, 0x05A, 0x432, 0x353, 0x021,
0x059, 0x42E, 0x357, 0x022, 0x057, 0x42A, 0x35C, 0x023,
0x056, 0x425, 0x361, 0x024, 0x054, 0x421, 0x366, 0x024,
0x053, 0x41D, 0x36B, 0x025, 0x051, 0x419, 0x370, 0x026,
0x050, 0x415, 0x374, 0x027, 0x04E, 0x410, 0x379, 0x028,
0x04D, 0x40C, 0x37E, 0x029, 0x04C, 0x408, 0x383, 0x02A,
0x04A, 0x403, 0x388, 0x02B, 0x049, 0x3FF, 0x38C, 0x02C,
0x047, 0x3FB, 0x391, 0x02D, 0x046, 0x3F6, 0x396, 0x02E,
0x045, 0x3F2, 0x39B, 0x02F, 0x043, 0x3ED, 0x39F, 0x030,
0x042, 0x3E9, 0x3A4, 0x031, 0x041, 0x3E5, 0x3A9, 0x032,
0x040, 0x3E0, 0x3AD, 0x033, 0x03E, 0x3DC, 0x3B2, 0x034,
0x03D, 0x3D7, 0x3B7, 0x035, 0x03C, 0x3D2, 0x3BB, 0x036,
0x03B, 0x3CE, 0x3C0, 0x037, 0x03A, 0x3C9, 0x3C5, 0x038,
0x038, 0x3C5, 0x3C9, 0x03A, 0x037, 0x3C0, 0x3CE, 0x03B,
0x036, 0x3BB, 0x3D2, 0x03C, 0x035, 0x3B7, 0x3D7, 0x03D,
0x034, 0x3B2, 0x3DC, 0x03E, 0x033, 0x3AD, 0x3E0, 0x040,
0x032, 0x3A9, 0x3E5, 0x041, 0x031, 0x3A4, 0x3E9, 0x042,
0x030, 0x39F, 0x3ED, 0x043, 0x02F, 0x39B, 0x3F2, 0x045,
0x02E, 0x396, 0x3F6, 0x046, 0x02D, 0x391, 0x3FB, 0x047,
0x02C, 0x38C, 0x3FF, 0x049, 0x02B, 0x388, 0x403, 0x04A,
0x02A, 0x383, 0x408, 0x04C, 0x029, 0x37E, 0x40C, 0x04D,
0x028, 0x379, 0x410, 0x04E, 0x027, 0x374, 0x415, 0x050,
0x026, 0x370, 0x419, 0x051, 0x025, 0x36B, 0x41D, 0x053,
0x024, 0x366, 0x421, 0x054, 0x024, 0x361, 0x425, 0x056,
0x023, 0x35C, 0x42A, 0x057, 0x022, 0x357, 0x42E, 0x059,
0x021, 0x353, 0x432, 0x05A, 0x020, 0x34E, 0x436, 0x05C,
0x020, 0x349, 0x43A, 0x05E, 0x01F, 0x344, 0x43E, 0x05F,
0x01E, 0x33F, 0x442, 0x061, 0x01D, 0x33A, 0x446, 0x063,
0x01D, 0x335, 0x44A, 0x064, 0x01C, 0x330, 0x44E, 0x066,
0x01B, 0x32B, 0x452, 0x068, 0x01B, 0x326, 0x455, 0x06A,
0x01A, 0x322, 0x459, 0x06B, 0x019, 0x31D, 0x45D, 0x06D,
0x018, 0x318, 0x461, 0x06F, 0x018, 0x313, 0x465, 0x071,
0x017, 0x30E, 0x468, 0x073, 0x017, 0x309, 0x46C, 0x075,
0x016, 0x304, 0x470, 0x076, 0x015, 0x2FF, 0x473, 0x078,
0x015, 0x2FA, 0x477, 0x07A, 0x014, 0x2F5, 0x47A, 0x07C,
0x014, 0x2F0, 0x47E, 0x07E, 0x013, 0x2EB, 0x481, 0x080,
0x013, 0x2E6, 0x485, 0x082, 0x012, 0x2E1, 0x488, 0x084,
0x011, 0x2DC, 0x48C, 0x086, 0x011, 0x2D8, 0x48F, 0x089,
0x010, 0x2D3, 0x492, 0x08B, 0x010, 0x2CE, 0x496, 0x08D,
0x00F, 0x2C9, 0x499, 0x08F, 0x00F, 0x2C4, 0x49C, 0x091,
0x00F, 0x2BF, 0x49F, 0x093, 0x00E, 0x2BA, 0x4A2, 0x096,
0x00E, 0x2B5, 0x4A6, 0x098, 0x00D, 0x2B0, 0x4A9, 0x09A,
0x00D, 0x2AB, 0x4AC, 0x09C, 0x00C, 0x2A6, 0x4AF, 0x09F,
0x00C, 0x2A2, 0x4B2, 0x0A1, 0x00B, 0x29D, 0x4B5, 0x0A3,
0x00B, 0x298, 0x4B7, 0x0A6, 0x00B, 0x293, 0x4BA, 0x0A8,
0x00A, 0x28E, 0x4BD, 0x0AB, 0x00A, 0x289, 0x4C0, 0x0AD,
0x00A, 0x284, 0x4C3, 0x0AF, 0x009, 0x280, 0x4C5, 0x0B2,
0x009, 0x27B, 0x4C8, 0x0B4, 0x009, 0x276, 0x4CB, 0x0B7,
0x008, 0x271, 0x4CD, 0x0BA, 0x008, 0x26C, 0x4D0, 0x0BC,
0x008, 0x267, 0x4D2, 0x0BF, 0x007, 0x263, 0x4D5, 0x0C1,
0x007, 0x25E, 0x4D7, 0x0C4, 0x007, 0x259, 0x4D9, 0x0C7,
0x006, 0x254, 0x4DC, 0x0C9, 0x006, 0x250, 0x4DE, 0x0CC,
0x006, 0x24B, 0x4E0, 0x0CF, 0x006, 0x246, 0x4E3, 0x0D2,
0x005, 0x241, 0x4E5, 0x0D4, 0x005, 0x23D, 0x4E7, 0x0D7,
0x005, 0x238, 0x4E9, 0x0DA, 0x005, 0x233, 0x4EB, 0x0DD,
0x004, 0x22F, 0x4ED, 0x0E0, 0x004, 0x22A, 0x4EF, 0x0E3,
0x004, 0x226, 0x4F1, 0x0E6, 0x004, 0x221, 0x4F3, 0x0E9,
0x004, 0x21C, 0x4F5, 0x0EC, 0x003, 0x218, 0x4F6, 0x0EF,
0x003, 0x213, 0x4F8, 0x0F2, 0x003, 0x20F, 0x4FA, 0x0F5,
0x003, 0x20A, 0x4FB, 0x0F8, 0x003, 0x205, 0x4FD, 0x0FB,
0x002, 0x201, 0x4FF, 0x0FE, 0x002, 0x1FC, 0x500, 0x101,
0x002, 0x1F8, 0x502, 0x104, 0x002, 0x1F3, 0x503, 0x107,
0x002, 0x1EF, 0x504, 0x10B, 0x002, 0x1EB, 0x506, 0x10E,
0x002, 0x1E6, 0x507, 0x111, 0x001, 0x1E2, 0x508, 0x114,
0x001, 0x1DD, 0x50A, 0x118, 0x001, 0x1D9, 0x50B, 0x11B,
0x001, 0x1D5, 0x50C, 0x11E, 0x001, 0x1D0, 0x50D, 0x122,
0x001, 0x1CC, 0x50E, 0x125, 0x001, 0x1C8, 0x50F, 0x129,
0x001, 0x1C3, 0x510, 0x12C, 0x001, 0x1BF, 0x511, 0x130,
0x001, 0x1BB, 0x511, 0x133, 0x001, 0x1B7, 0x512, 0x137,
0x000, 0x1B2, 0x513, 0x13A, 0x000, 0x1AE, 0x514, 0x13E,
0x000, 0x1AA, 0x514, 0x141, 0x000, 0x1A6, 0x515, 0x145,
0x000, 0x1A2, 0x516, 0x148, 0x000, 0x19E, 0x516, 0x14C,
0x000, 0x19A, 0x517, 0x150, 0x000, 0x195, 0x517, 0x153,
0x000, 0x191, 0x517, 0x157, 0x000, 0x18D, 0x518, 0x15B,
0x000, 0x189, 0x518, 0x15F, 0x000, 0x185, 0x518, 0x162,
0x000, 0x181, 0x518, 0x166, 0x000, 0x17D, 0x518, 0x16A,
0x000, 0x17A, 0x519, 0x16E, 0x000, 0x176, 0x519, 0x172};
#endif

View file

@ -1,28 +0,0 @@
//============================================
//=== 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

File diff suppressed because it is too large Load diff

View file

@ -1,845 +0,0 @@
/***************************************************************************
registers.h - description
***************************************************************************/
/***************************************************************************
* *
* 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/04 - Pete
// - generic cleanup for the Peops release... register values by Kanodin &
// his team
//
//*************************************************************************//
//###########################################################################
#define PS2_C0_SPUaddr_Hi (0x000 + 0x1A8)
#define PS2_C0_SPUaddr_Lo (0x000 + 0x1AA)
#define PS2_C1_SPUaddr_Hi (0x400 + 0x1A8)
#define PS2_C1_SPUaddr_Lo (0x400 + 0x1AA)
#define PS2_C0_SPUdata (0x000 + 0x1AC)
#define PS2_C1_SPUdata (0x400 + 0x1AC)
#define PS2_C0_SPUDMActrl (0x000 + 0x1AE)
#define PS2_C1_SPUDMActrl (0x400 + 0x1AE)
#define PS2_C0_SPUstat (0x000 + 0x344)
#define PS2_C1_SPUstat (0x400 + 0x344)
#define PS2_C0_ReverbAddr_Hi (0x000 + 0x2E0)
#define PS2_C0_ReverbAddr_Lo (0x000 + 0x2E2)
#define PS2_C1_ReverbAddr_Hi (0x400 + 0x2E0)
#define PS2_C1_ReverbAddr_Lo (0x400 + 0x2E2)
#define PS2_C0_ReverbAEnd_Hi (0x000 + 0x33C)
#define PS2_C0_ReverbAEnd_Lo (0x000 + 0x33E)
#define PS2_C1_ReverbAEnd_Hi (0x400 + 0x33C)
#define PS2_C1_ReverbAEnd_Lo (0x400 + 0x33E)
#define PS2_C0_DryL1 (0x000 + 0x188)
#define PS2_C1_DryL1 (0x400 + 0x188)
#define PS2_C0_DryL2 (0x000 + 0x18A)
#define PS2_C1_DryL2 (0x400 + 0x18A)
#define PS2_C0_DryR1 (0x000 + 0x190)
#define PS2_C1_DryR1 (0x400 + 0x190)
#define PS2_C0_DryR2 (0x000 + 0x192)
#define PS2_C1_DryR2 (0x400 + 0x192)
#define PS2_C0_ATTR (0x000 + 0x19A)
#define PS2_C1_ATTR (0x400 + 0x19A)
#define PS2_C0_ADMAS (0x000 + 0x1B0)
#define PS2_C1_ADMAS (0x400 + 0x1B0)
#define PS2_C0_SPUirqAddr_Hi (0x000 + 0x19C)
#define PS2_C0_SPUirqAddr_Lo (0x000 + 0x19D)
#define PS2_C1_SPUirqAddr_Hi (0x400 + 0x19C)
#define PS2_C1_SPUirqAddr_Lo (0x400 + 0x19D)
#define PS2_C0_SPUrvolL (0x000 + 0x764)
#define PS2_C0_SPUrvolR (0x000 + 0x766)
#define PS2_C1_SPUrvolL (0x028 + 0x764)
#define PS2_C1_SPUrvolR (0x028 + 0x766)
#define PS2_C0_SPUon1 (0x000 + 0x1A0)
#define PS2_C0_SPUon2 (0x000 + 0x1A2)
#define PS2_C1_SPUon1 (0x400 + 0x1A0)
#define PS2_C1_SPUon2 (0x400 + 0x1A2)
#define PS2_C0_SPUoff1 (0x000 + 0x1A4)
#define PS2_C0_SPUoff2 (0x000 + 0x1A6)
#define PS2_C1_SPUoff1 (0x400 + 0x1A4)
#define PS2_C1_SPUoff2 (0x400 + 0x1A6)
#define PS2_C0_FMod1 (0x000 + 0x180)
#define PS2_C0_FMod2 (0x000 + 0x182)
#define PS2_C1_FMod1 (0x400 + 0x180)
#define PS2_C1_FMod2 (0x400 + 0x182)
#define PS2_C0_Noise1 (0x000 + 0x184)
#define PS2_C0_Noise2 (0x000 + 0x186)
#define PS2_C1_Noise1 (0x400 + 0x184)
#define PS2_C1_Noise2 (0x400 + 0x186)
#define PS2_C0_RVBon1_L (0x000 + 0x18C)
#define PS2_C0_RVBon2_L (0x000 + 0x18E)
#define PS2_C0_RVBon1_R (0x000 + 0x194)
#define PS2_C0_RVBon2_R (0x000 + 0x196)
#define PS2_C1_RVBon1_L (0x400 + 0x18C)
#define PS2_C1_RVBon2_L (0x400 + 0x18E)
#define PS2_C1_RVBon1_R (0x400 + 0x194)
#define PS2_C1_RVBon2_R (0x400 + 0x196)
#define PS2_C0_Reverb (0x000 + 0x2E4)
#define PS2_C1_Reverb (0x400 + 0x2E4)
#define PS2_C0_ReverbX (0x000 + 0x774)
#define PS2_C1_ReverbX (0x028 + 0x774)
#define PS2_C0_SPUend1 (0x000 + 0x340)
#define PS2_C0_SPUend2 (0x000 + 0x342)
#define PS2_C1_SPUend1 (0x400 + 0x340)
#define PS2_C1_SPUend2 (0x400 + 0x342)
#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
//###########################################################################
/*
Included the info received in Regs.txt list by Neill Corlett - Kanodin
Voice parameters:
SD_VP_VOLL, SD_VP_VOLR - Volume left/right per voice. Assuming identical to PS1.
SD_VP_PITCH - Pitch scaler 0000-3FFF. Assuming identical to PS1.
SD_VP_ADSR1, SD_VP_ADSR1 - Envelope data. Bitfields are documented as identical to PS1.
SD_VP_ENVX - Current envelope value. Assuming identical to PS1.
SD_VP_VOLXL, SD_VP_VOLXR - Current voice volume left/right. Does not exist on the PS1.
Guessing that this is handy for the increase/decrease modes.
Voice addresses:
SD_VA_SSA - Sample start address; assuming identical to PS1
SD_VA_LSAX - Loop start address; assuming identical to PS1
SD_VA_NAX - Seems to be documented as the current playing address.
Does not exist on PS1.
Switches:
SD_S_PMON - Pitch mod; assuming identical to PS1
SD_S_NON - Noise; assuming identical to PS1
SD_S_VMIXL, SD_S_VMIXR - Voice mix L/R. Guessing this is just a separate L/R version
of the "voice enable" bits on the PS1.
SD_S_VMIXEL, SD_S_VMIXER - Voice effect mix L/R. Guessing this is just a separate L/R
version of the "voice reverb enable" bits on the PS1.
SD_S_KON, SD_S_KOFF - Key on/off; assuming identical to PS1
Addresses:
SD_A_TSA - Transfer start address; assuming identical to PS1
SD_A_ESA - Effect start address - this is probably analogous to the
PS1's reverb work area start address
SD_A_EEA - Effect end address - this would've been fixed to 0x7FFFF on
the PS1; settable in 128K increments on the PS2.
SD_A_IRQA - IRQ address; assuming identical to PS1
Volume parameters:
SD_P_MVOLL, SD_P_MVOLR - Master volume L/R; assuming identical to PS1
SD_P_EVOLL, SD_P_EVOLR - Effect volume L/R; assuming analogous to RVOL on the PS1
SD_P_AVOLL, SD_P_AVOLR - External input volume L/R
This is probably where CORE0 connects to CORE1
SD_P_BVOLL, SD_P_BVOLR - Sound data input volume - perhaps this is the volume of
the raw PCM auto-DMA input? analogous to CD input volume?
SD_P_MVOLXL, SD_P_MVOLXR - Current master volume L/R; seems self-explanatory
SD_P_MMIX - Mixer / effect enable bits.
bit 11 = MSNDL = voice output dry L
10 = MSNDR = voice output dry R
9 = MSNDEL = voice output wet L
8 = MSNDER = voice output wet R
7 = MINL = sound data input dry L
6 = MINR = sound data input dry R
5 = MINEL = sound data input wet L
4 = MINER = sound data input wet R
3 = SINL = core external input dry L
2 = SINR = core external input dry R
1 = SINEL = core external input wet L
0 = SINER = core external input wet R
Core attributes (SD_C)
bit 4..5 - DMA related
bit 6 - IRQ enable
bit 7 - effect enable (reverb enable)
bit 13..8 - noise clock
bit 14 - mute
- if you READ the two DMA related bits, if either are set, the channel is
considered "busy" by sceSdVoiceTrans
Reverb parameters:
Same as PS1 reverb (I used the names from my reverb doc).
Other PS2 IOP notes
There's two DMA controllers:
The original one at 1F801080-1F8010FF (channels 0-6)
A new one at 1F801500-1F80157F (channels 7-13)
They appear to function the same way - 7 channels each.
SPU CORE0's DMA channel is 4 as per usual
SPU CORE1's DMA channel is 7
DMA channel 10 is SIF
Original INTR controller at 1F801000-1F80107F
All interrupt handling seems to be done using the old INTR, but
with some new bits defined:
Reading from 1F801078 masks interrupts and returns 1 if they weren't
masked before. Writing 1 to 1F801078 re-enables interrupts.
Writing 0 doesn't. Maybe it was like that on the original PS1 too.
Six root counters:
RTC# address sources size prescale interrupt#
0 0x1F801100 sysclock,pixel 16 bit 1 only 4
1 0x1F801110 sysclock,hline 16 bit 1 only 5
2 0x1F801120 sysclock 16 bit 1,8 6
3 0x1F801480 sysclock,hline 32 bit 1 only 14
4 0x1F801490 sysclock 32 bit 1,8,16,256 15
5 0x1F8014A0 sysclock 32 bit 1,8,16,256 16
Count (0x0) and Compare (0x8) registers work as before, only with more bits
in the new counters.
Mode (0x4) works like this when written:
bits 0..2 gate
bit 3 reset on target
bit 4 target interrupt enable
bit 5 overflow interrupt enable
bit 6 master enable (?)
bit 7 ?
bit 8 clock select
bit 9 prescale (OLD)
bit 10..12 ?
bit 13..14 prescale (NEW)
bit 15 ? always set to 1
Gate:
TM_NO_GATE 000
TM_GATE_ON_Count 001
TM_GATE_ON_ClearStart 011
TM_GATE_ON_Clear_OFF_Start 101
TM_GATE_ON_Start 111
V-blank ----+ +----------------------------+ +------
| | | |
| | | |
+----+ +----+
TM_NO_GATE:
0================================>============
TM_GATE_ON_Count:
<---->0==========================><---->0=====
TM_GATE_ON_ClearStart:
0====>0================================>0=====
TM_GATE_ON_Clear_OFF_Start:
0====><-------------------------->0====><-----
TM_GATE_ON_Start:
<---->0==========================>============
reset on target: if set, counter resets to 0 when Compare value is reached
target interrupt enable: if set, interrupt when Compare value is reached
overflow interrupt enable: if set, interrupt when counter overflows
master enable: if this bit is clear, the timer should do nothing.
clock select: for counters 0, 1, and 3, setting this will select the alternate
counter (pixel or hline)
prescale (OLD): for counter 2 only. set this to prescale (divide) by 8.
prescale (NEW): for counters 4 and 5 only:
00 = prescale by 1
01 = prescale by 8
10 = prescale by 16
11 = prescale by 256
Writing 0x4 also clears the counter. (I think.)
When 0x4 is read, it becomes Status:
bit 0..10 ?
bit 11 compare value was reached
bit 12 count overflowed
bit 13..15 ?
Reading probably clears these bits.
1F8014B0 (word) - timer-related but otherwise unknown
1F8014C0 (word) - timer-related but otherwise unknown
don't currently know how the interrupts work for DMA ch7 yet
1F801060 (word) - address of some kind.
1F801450 (word) -
if bit 3 is SET, we're in PS1 mode.
if bit 3 is CLEAR, we're in PS2 IOP mode.
1F802070 (byte) - unknown. status byte of some kind? visible to EE?
1D000000-1D00007F (?) - SIF related
1D000020 (word) - read counter of some sort?
sceSifInit waits for bit 0x10000 of this to be set.
1D000030 (word) - read counter of some sort?
1D000040 (word) - read bits 0x20, 0x40 mean something
1D000060 (word) - used to detect whether the SIF interface exists
read must be 0x1D000060, or the top 20 bits must be zero
*/
/*
// DirectX Audio SPU2 Driver for PCSX2
// audio.c by J.F. and Kanodin (hooper1@cox.net)
//
// Copyright 2003 J.F. and Kanodin, and distributed under the
// terms of the GNU General Public License, v2 or later.
// http://www.gnu.org/copyleft/gpl.html.
Included these just in case you need them J.F. - Kanodin
// Core Start Addresses
#define CORE0 0x1f900000
#define CORE1 0x1f900400
#define IOP_INT_VBLANK (1<<0)
#define IOP_INT_GM (1<<1)
#define IOP_INT_CDROM (1<<2)
#define IOP_INT_DMA (1<<3)
#define IOP_INT_RTC0 (1<<4)
#define IOP_INT_RTC1 (1<<5)
#define IOP_INT_RTC2 (1<<6)
#define IOP_INT_SIO0 (1<<7)
#define IOP_INT_SIO1 (1<<8)
#define IOP_INT_SPU (1<<9)
#define IOP_INT_PIO (1<<10)
#define IOP_INT_EVBLANK (1<<11)
#define IOP_INT_DVD (1<<12)
#define IOP_INT_PCMCIA (1<<13)
#define IOP_INT_RTC3 (1<<14)
#define IOP_INT_RTC4 (1<<15)
#define IOP_INT_RTC5 (1<<16)
#define IOP_INT_SIO2 (1<<17)
#define IOP_INT_HTR0 (1<<18)
#define IOP_INT_HTR1 (1<<19)
#define IOP_INT_HTR2 (1<<20)
#define IOP_INT_HTR3 (1<<21)
#define IOP_INT_USB (1<<22)
#define IOP_INT_EXTR (1<<23)
#define IOP_INT_FWRE (1<<24)
#define IOP_INT_FDMA (1<<25)
// CORE0 => +0x000, CORE1 => +0x400
// individual voice parameter regs
#define VP_VOLL(cr, vc) (0x400 * cr + 0x000 + (vc << 4)) // voice volume (left)
#define VP_VOLR(cr, vc) (0x400 * cr + 0x002 + (vc << 4)) // voice volume (right)
#define VP_PITCH(cr, vc) (0x400 * cr + 0x004 + (vc << 4)) // voice pitch
#define VP_ADSR1(cr, vc) (0x400 * cr + 0x006 + (vc << 4)) // voice envelope (AR, DR, SL)
#define VP_ADSR2(cr, vc) (0x400 * cr + 0x008 + (vc << 4)) // voice envelope (SR, RR)
#define VP_ENVX(cr, vc) (0x400 * cr + 0x00A + (vc << 4)) // voice envelope (current value)
#define VP_VOLXL(cr, vc) (0x400 * cr + 0x00C + (vc << 4)) // voice volume (current value left)
#define VP_VOLXR(cr, vc) (0x400 * cr + 0x00E + (vc << 4)) // voice volume (current value right)
#define VA_SSA(cr, vc) (0x400 * cr + 0x1C0 + (vc * 12)) // voice waveform data start address
#define VA_LSAX(cr, vc) (0x400 * cr + 0x1C4 + (vc * 12)) // voice waveform data loop address
#define VA_NAX(cr, vc) (0x400 * cr + 0x1C8 + (vc * 12)) // voice waveform data next address
// common settings
#define S_PMON(cr) (0x400 * cr + 0x180) // pitch modulation on
#define S_NON(cr) (0x400 * cr + 0x184) // noise generator on
#define S_VMIXL(cr) (0x400 * cr + 0x188) // voice output mixing (dry left)
#define S_VMIXEL(cr) (0x400 * cr + 0x18C) // voice output mixing (wet left)
#define S_VMIXR(cr) (0x400 * cr + 0x190) // voice output mixing (dry right)
#define S_VMIXER(cr) (0x400 * cr + 0x194) // voice output mixing (wet right)
#define P_MMIX(cr) (0x400 * cr + 0x198) // output type after voice mixing (See paragraph below)
#define P_ATTR(cr) (0x400 * cr + 0x19A) // core attributes (See paragraph below)
#define A_IRQA(cr) (0x400 * cr + 0x19C) // IRQ address
#define S_KON(cr) (0x400 * cr + 0x1A0) // key on (start voice sound generation)
#define S_KOFF(cr) (0x400 * cr + 0x1A4) // key off (end voice sound generation)
#define A_TSA(cr) (0x400 * cr + 0x1A8) // DMA transfer start address
#define P_DATA(cr) (0x400 * cr + 0x1AC) // DMA data register
#define P_CTRL(cr) (0x400 * cr + 0x1AE) // DMA control register
#define P_ADMAS(cr) (0x400 * cr + 0x1B0) // AutoDMA status
#define A_ESA(cr) (0x400 * cr + 0x2E0) // effects work area start address
#define FB_SRC_A(cr) (0x400 * cr + 0x2E4)
#define FB_SRC_B(cr) (0x400 * cr + 0x2E8)
#define IIR_DEST_A0(cr) (0x400 * cr + 0x2EC)
#define IIR_DEST_A1(cr) (0x400 * cr + 0x2F0)
#define ACC_SRC_A0(cr) (0x400 * cr + 0x2F4)
#define ACC_SRC_A1(cr) (0x400 * cr + 0x2F8)
#define ACC_SRC_B0(cr) (0x400 * cr + 0x2FC)
#define ACC_SRC_B1(cr) (0x400 * cr + 0x300)
#define IIR_SRC_A0(cr) (0x400 * cr + 0x304)
#define IIR_SRC_A1(cr) (0x400 * cr + 0x308)
#define IIR_DEST_B0(cr) (0x400 * cr + 0x30C)
#define IIR_DEST_B1(cr) (0x400 * cr + 0x310)
#define ACC_SRC_C0(cr) (0x400 * cr + 0x314)
#define ACC_SRC_C1(cr) (0x400 * cr + 0x318)
#define ACC_SRC_D0(cr) (0x400 * cr + 0x31C)
#define ACC_SRC_D1(cr) (0x400 * cr + 0x320)
#define IIR_SRC_B1(cr) (0x400 * cr + 0x324)
#define IIR_SRC_B0(cr) (0x400 * cr + 0x328)
#define MIX_DEST_A0(cr) (0x400 * cr + 0x32C)
#define MIX_DEST_A1(cr) (0x400 * cr + 0x330)
#define MIX_DEST_B0(cr) (0x400 * cr + 0x334)
#define MIX_DEST_B1(cr) (0x400 * cr + 0x338)
#define A_EEA(cr) (0x400 * cr + 0x33C) // effects work area end address
#define P_ENDX(cr) (0x400 * cr + 0x340) // voice loop end status
#define P_STAT(cr) (0x400 * cr + 0x344) // DMA status register
#define P_ENDS(cr) (0x400 * cr + 0x346) // ?
// CORE0 => +0x400, CORE1 => +0x428
#define P_MVOLL(cr) (0x28 * cr + 0x760) // master volume (left)
#define P_MVOLR(cr) (0x28 * cr + 0x762) // master volume (right)
#define P_EVOLL(cr) (0x28 * cr + 0x764) // effect return volume (left)
#define P_EVOLR(cr) (0x28 * cr + 0x766) // effect return volume (right)
#define P_AVOLL(cr) (0x28 * cr + 0x768) // core external input volume (left)
#define P_AVOLR(cr) (0x28 * cr + 0x76A) // core external input volume (right)
#define P_BVOLL(cr) (0x28 * cr + 0x76C) // sound data input volume (left)
#define P_BVOLR(cr) (0x28 * cr + 0x76E) // sound data input volume (right)
#define P_MVOLXL(cr) (0x28 * cr + 0x770) // current master volume (left)
#define P_MVOLXR(cr) (0x28 * cr + 0x772) // current master volume (right)
#define IIR_ALPHA(cr) (0x28 * cr + 0x774)
#define ACC_COEF_A(cr) (0x28 * cr + 0x776)
#define ACC_COEF_B(cr) (0x28 * cr + 0x778)
#define ACC_COEF_C(cr) (0x28 * cr + 0x77A)
#define ACC_COEF_D(cr) (0x28 * cr + 0x77C)
#define IIR_COEF(cr) (0x28 * cr + 0x77E)
#define FB_ALPHA(cr) (0x28 * cr + 0x780)
#define FB_X(cr) (0x28 * cr + 0x782)
#define IN_COEF_L(cr) (0x28 * cr + 0x784)
#define IN_COEF_R(cr) (0x28 * cr + 0x786)
// CORE1 only => +0x400
#define SPDIF_OUT 0x7C0 // SPDIF Out: OFF/'PCM'/Bitstream/Bypass
#define SPDIF_MODE 0x7C6
#define SPDIF_MEDIA 0x7C8 // SPDIF Media: 'CD'/DVD
#define SPDIF_COPY 0x7CA // SPDIF Copy Protection
// PS1 SPU CORE
// individual voice settings
#define SPU_VP_PITCH(vc) (0xC04 + (vc << 4)) // voice pitch
#define SPU_VA_SSA(vc) (0xC06 + (vc << 4)) // voice waveform data start address
#define SPU_VP_ADSR(vc) (0xC08 + (vc << 4)) // voice envelope
#define SPU_VA_SSA(vc) (0xC0E + (vc << 4)) // voice waveform data loop address
// common settings
#define SPU_P_MVOLL 0xD80 // master volume (left)
#define SPU_P_MVOLR 0xD82 // master volume (right)
#define SPU_P_RVOLL 0xD84 // effect return volume (left)
#define SPU_P_RVOLR 0xD86 // effect return volume (right)
#define SPU_S_KON1 0xD88 // key on
#define SPU_S_KON2 0xD8A //
#define SPU_S_KOFF1 0xD8C // key off
#define SPU_S_KOFF2 0xD8E //
#define SPU_S_PMON1 0xD90 // pitch modulation on
#define SPU_S_PMON2 0xD92 //
#define SPU_S_NON1 0xD94 // noise generator on
#define SPU_S_NON2 0xD96 //
#define SPU_S_RVBON1 0xD98 // effects on
#define SPU_S_RVBON2 0xD9A //
#define SPU_S_MUTE1 0xD9C // voice mute
#define SPU_S_MUTE2 0xD9E //
#define SPU_A_ESA 0xDA2 // effects work area start
#define SPU_A_IRQA 0xDA4 // IRQ address
#define SPU_A_TSA 0xDA6 // DMA transfer start address
#define SPU_P_DATA 0xDA8 // DMA data register
#define SPU_P_CTRL 0xDAA // DMA control register
#define SPU_P_STAT 0xDAE // DMA status register
#define SPU_P_CDL 0xDB0 // sound data input volume (left)
#define SPU_P_CDR 0xDB2 // sound data input volume (right)
#define SPU_P_EXTL 0xDB4 // external input volume (left)
#define SPU_P_EXTR 0xDB6 // external input volume (right)
#define SPU_P_REVERB 0xDC0 // effects control
// Individual voice parameter regs CORE 0
// Only
#define VP_VOLL(cr, vc) (0x400 * cr + 0x000 + (vc << 4)) // voice volume (left)
#define VP_VOLR(cr, vc) (0x400 * cr + 0x002 + (vc << 4)) // voice volume (right)
#define VP_PITCH(cr, vc) (0x400 * cr + 0x004 + (vc << 4)) // voice pitch
#define VP_ADSR1(cr, vc) (0x400 * cr + 0x006 + (vc << 4)) // voice envelope (AR, DR, SL)
#define VP_ADSR2(cr, vc) (0x400 * cr + 0x008 + (vc << 4)) // voice envelope (SR, RR)
#define VP_ENVX(cr, vc) (0x400 * cr + 0x00A + (vc << 4)) // voice envelope (current value)
#define VP_VOLXL(cr, vc) (0x400 * cr + 0x00C + (vc << 4)) // voice volume (current value left)
#define VP_VOLXR(cr, vc) (0x400 * cr + 0x00E + (vc << 4)) // voice volume (current value right)
#define VA_SSA(cr, vc) (0x400 * cr + 0x1C0 + (vc * 12)) // voice waveform data start address
#define VA_LSAX(cr, vc) (0x400 * cr + 0x1C4 + (vc * 12)) // voice waveform data loop address
#define VA_NAX(cr, vc) (0x400 * cr + 0x1C8 + (vc * 12)) // voice waveform data next address
// CORE 0 Common Settings
#define S_PMON(cr) (0x400 * cr + 0x180) // pitch modulation on
#define S_NON(cr) (0x400 * cr + 0x184) // noise generator on
#define S_VMIXL(cr) (0x400 * cr + 0x188) // voice output mixing (dry left)
#define S_VMIXEL(cr) (0x400 * cr + 0x18C) // voice output mixing (wet left)
#define S_VMIXR(cr) (0x400 * cr + 0x190) // voice output mixing (dry right)
#define S_VMIXER(cr) (0x400 * cr + 0x194) // voice output mixing (wet right)
#define P_MMIX(cr) (0x400 * cr + 0x198) // output type after voice mixing (See paragraph below)
#define P_ATTR(cr) (0x400 * cr + 0x19A) // core attributes (See paragraph below)
#define A_IRQA(cr) (0x400 * cr + 0x19C) // IRQ address
#define S_KON(cr) (0x400 * cr + 0x1A0) // key on (start voice sound generation)
#define S_KOFF(cr) (0x400 * cr + 0x1A4) // key off (end voice sound generation)
#define A_TSA(cr) (0x400 * cr + 0x1A8) // DMA transfer start address
#define P_DATA(cr) (0x400 * cr + 0x1AC) // DMA data register
#define P_CTRL(cr) (0x400 * cr + 0x1AE) // DMA control register
#define P_ADMAS(cr) (0x400 * cr + 0x1B0) // AutoDMA status
#define A_ESA(cr) (0x400 * cr + 0x2E0) // effects work area start address
// Core 0 Reverb Addresses
#define FB_SRC_A(cr) (0x400 * cr + 0x2E4)
#define FB_SRC_B(cr) (0x400 * cr + 0x2E8)
#define IIR_DEST_A0(cr) (0x400 * cr + 0x2EC)
#define IIR_DEST_A1(cr) (0x400 * cr + 0x2F0)
#define ACC_SRC_A0(cr) (0x400 * cr + 0x2F4)
#define ACC_SRC_A1(cr) (0x400 * cr + 0x2F8)
#define ACC_SRC_B0(cr) (0x400 * cr + 0x2FC)
#define ACC_SRC_B1(cr) (0x400 * cr + 0x300)
#define IIR_SRC_A0(cr) (0x400 * cr + 0x304)
#define IIR_SRC_A1(cr) (0x400 * cr + 0x308)
#define IIR_DEST_B0(cr) (0x400 * cr + 0x30C)
#define IIR_DEST_B1(cr) (0x400 * cr + 0x310)
#define ACC_SRC_C0(cr) (0x400 * cr + 0x314)
#define ACC_SRC_C1(cr) (0x400 * cr + 0x318)
#define ACC_SRC_D0(cr) (0x400 * cr + 0x31C)
#define ACC_SRC_D1(cr) (0x400 * cr + 0x320)
#define IIR_SRC_B1(cr) (0x400 * cr + 0x324)
#define IIR_SRC_B0(cr) (0x400 * cr + 0x328)
#define MIX_DEST_A0(cr) (0x400 * cr + 0x32C)
#define MIX_DEST_A1(cr) (0x400 * cr + 0x330)
#define MIX_DEST_B0(cr) (0x400 * cr + 0x334)
#define MIX_DEST_B1(cr) (0x400 * cr + 0x338)
#define A_EEA(cr) (0x400 * cr + 0x33C) // effects work area end address
#define P_ENDX(cr) (0x400 * cr + 0x340) // voice loop end status
#define P_STAT(cr) (0x400 * cr + 0x344) // DMA status register
#define P_ENDS(cr) (0x400 * cr + 0x346) // ?
// CORE 0 Specific
#define P_MVOLL(cr) (0x28 * cr + 0x760) // master volume (left)
#define P_MVOLR(cr) (0x28 * cr + 0x762) // master volume (right)
#define P_EVOLL(cr) (0x28 * cr + 0x764) // effect return volume (left)
#define P_EVOLR(cr) (0x28 * cr + 0x766) // effect return volume (right)
#define P_AVOLL(cr) (0x28 * cr + 0x768) // core external input volume (left)
#define P_AVOLR(cr) (0x28 * cr + 0x76A) // core external input volume (right)
#define P_BVOLL(cr) (0x28 * cr + 0x76C) // sound data input volume (left)
#define P_BVOLR(cr) (0x28 * cr + 0x76E) // sound data input volume (right)
#define P_MVOLXL(cr) (0x28 * cr + 0x770) // current master volume (left)
#define P_MVOLXR(cr) (0x28 * cr + 0x772) // current master volume (right)
// More CORE 0 Reverb
#define IIR_ALPHA(cr) (0x28 * cr + 0x774)
#define ACC_COEF_A(cr) (0x28 * cr + 0x776)
#define ACC_COEF_B(cr) (0x28 * cr + 0x778)
#define ACC_COEF_C(cr) (0x28 * cr + 0x77A)
#define ACC_COEF_D(cr) (0x28 * cr + 0x77C)
#define IIR_COEF(cr) (0x28 * cr + 0x77E)
#define FB_ALPHA(cr) (0x28 * cr + 0x780)
#define FB_X(cr) (0x28 * cr + 0x782)
#define IN_COEF_L(cr) (0x28 * cr + 0x784)
#define IN_COEF_R(cr) (0x28 * cr + 0x786)
// CORE 1 only
#define SPDIF_OUT 0x7C0 // SPDIF Out: OFF/'PCM'/Bitstream/Bypass
#define SPDIF_MODE 0x7C6
#define SPDIF_MEDIA 0x7C8 // SPDIF Media: 'CD'/DVD
#define SPDIF_COPY 0x7CA // SPDIF Copy Protection
*/
/* PS1 SPU CORE
*** The below really isn't needed, only if you ***
*** want to add SPU support to the plugin ***
*** which I see no need to add at this time. ***
*** individual voice settings ***
#define SPU_VP_PITCH(vc) (0xC04 + (vc << 4)) // voice pitch
#define SPU_VA_SSA(vc) (0xC06 + (vc << 4)) // voice waveform data start address
#define SPU_VP_ADSR(vc) (0xC08 + (vc << 4)) // voice envelope
#define SPU_VA_SSA(vc) (0xC0E + (vc << 4)) // voice waveform data loop address
// common settings
#define SPU_P_MVOLL 0xD80 // master volume (left)
#define SPU_P_MVOLR 0xD82 // master volume (right)
#define SPU_P_RVOLL 0xD84 // effect return volume (left)
#define SPU_P_RVOLR 0xD86 // effect return volume (right)
#define SPU_S_KON1 0xD88 // key on
#define SPU_S_KON2 0xD8A //
#define SPU_S_KOFF1 0xD8C // key off
#define SPU_S_KOFF2 0xD8E //
#define SPU_S_PMON1 0xD90 // pitch modulation on
#define SPU_S_PMON2 0xD92 //
#define SPU_S_NON1 0xD94 // noise generator on
#define SPU_S_NON2 0xD96 //
#define SPU_S_RVBON1 0xD98 // effects on
#define SPU_S_RVBON2 0xD9A //
#define SPU_S_MUTE1 0xD9C // voice mute
#define SPU_S_MUTE2 0xD9E //
#define SPU_A_ESA 0xDA2 // effects work area start
#define SPU_A_IRQA 0xDA4 // IRQ address
#define SPU_A_TSA 0xDA6 // DMA transfer start address
#define SPU_P_DATA 0xDA8 // DMA data register
#define SPU_P_CTRL 0xDAA // DMA control register
#define SPU_P_STAT 0xDAE // DMA status register
#define SPU_P_CDL 0xDB0 // sound data input volume (left)
#define SPU_P_CDR 0xDB2 // sound data input volume (right)
#define SPU_P_EXTL 0xDB4 // external input volume (left)
#define SPU_P_EXTR 0xDB6 // external input volume (right)
#define SPU_P_REVERB 0xDC0 // effects control
*/
/*
#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
*/

View file

@ -1,43 +0,0 @@
/***************************************************************************
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:
//
// 2004/04/04 - Pete
// - changed plugin to emulate PS2 spu
//
// 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 VolumeOn(int start,int end,unsigned short val,int iRight);
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,int iRight);
void SetReverbAddr(int core);
EXPORT_GCC void CALLBACK SPU2write(unsigned long reg, unsigned short val);

View file

@ -1,420 +0,0 @@
/***************************************************************************
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:
//
// 2004/04/04 - Pete
// - changed to SPU2 functionality
//
// 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[2];
int * sRVBEnd[2];
int * sRVBStart[2];
////////////////////////////////////////////////////////////////////////
// START REVERB
////////////////////////////////////////////////////////////////////////
static INLINE void StartREVERB(int ch)
{
int core=ch/24;
if((s_chan[ch].bReverbL || s_chan[ch].bReverbR) && (spuCtrl2[core]&0x80)) // reverb possible?
{
if(iUseReverb==1) s_chan[ch].bRVBActive=1;
}
else s_chan[ch].bRVBActive=0; // else -> no reverb
}
////////////////////////////////////////////////////////////////////////
// HELPER FOR NEILL'S REVERB: re-inits our reverb mixing buf
////////////////////////////////////////////////////////////////////////
static INLINE void InitREVERB(void)
{
if(iUseReverb==1)
{
memset(sRVBStart[0],0,NSSIZE*2*4);
memset(sRVBStart[1],0,NSSIZE*2*4);
}
}
////////////////////////////////////////////////////////////////////////
// STORE REVERB
////////////////////////////////////////////////////////////////////////
static INLINE void StoreREVERB(int ch,int ns)
{
int core=ch/24;
if(iUseReverb==0) return;
else
if(iUseReverb==1) // -------------------------------- // Neil's reverb
{
const int iRxl=(s_chan[ch].sval*s_chan[ch].iLeftVolume*s_chan[ch].bReverbL)/0x4000;
const int iRxr=(s_chan[ch].sval*s_chan[ch].iRightVolume*s_chan[ch].bReverbR)/0x4000;
ns<<=1;
*(sRVBStart[core]+ns) +=iRxl; // -> we mix all active reverb channels into an extra buffer
*(sRVBStart[core]+ns+1)+=iRxr;
}
}
////////////////////////////////////////////////////////////////////////
static INLINE int g_buffer(int iOff,int core) // get_buffer content helper: takes care about wraps
{
short * p=(short *)spuMem;
iOff=(iOff)+rvb[core].CurrAddr;
while(iOff>rvb[core].EndAddr) iOff=rvb[core].StartAddr+(iOff-(rvb[core].EndAddr+1));
while(iOff<rvb[core].StartAddr) iOff=rvb[core].EndAddr-(rvb[core].StartAddr-iOff);
return (int)*(p+iOff);
}
////////////////////////////////////////////////////////////////////////
static INLINE void s_buffer(int iOff,int iVal,int core) // set_buffer content helper: takes care about wraps and clipping
{
short * p=(short *)spuMem;
iOff=(iOff)+rvb[core].CurrAddr;
while(iOff>rvb[core].EndAddr) iOff=rvb[core].StartAddr+(iOff-(rvb[core].EndAddr+1));
while(iOff<rvb[core].StartAddr) iOff=rvb[core].EndAddr-(rvb[core].StartAddr-iOff);
if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;
*(p+iOff)=(short)iVal;
}
////////////////////////////////////////////////////////////////////////
static INLINE void s_buffer1(int iOff,int iVal,int core) // set_buffer (+1 sample) content helper: takes care about wraps and clipping
{
short * p=(short *)spuMem;
iOff=(iOff)+rvb[core].CurrAddr+1;
while(iOff>rvb[core].EndAddr) iOff=rvb[core].StartAddr+(iOff-(rvb[core].EndAddr+1));
while(iOff<rvb[core].StartAddr) iOff=rvb[core].EndAddr-(rvb[core].StartAddr-iOff);
if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;
*(p+iOff)=(short)iVal;
}
////////////////////////////////////////////////////////////////////////
static INLINE int MixREVERBLeft(int ns,int core)
{
if(iUseReverb==1)
{
if(!rvb[core].StartAddr || !rvb[core].EndAddr ||
rvb[core].StartAddr>=rvb[core].EndAddr) // reverb is off
{
rvb[core].iLastRVBLeft=rvb[core].iLastRVBRight=rvb[core].iRVBLeft=rvb[core].iRVBRight=0;
return 0;
}
rvb[core].iCnt++;
if(rvb[core].iCnt&1) // we work on every second left value: downsample to 22 khz
{
if((spuCtrl2[core]&0x80)) // -> reverb on? oki
{
int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1;
const int INPUT_SAMPLE_L=*(sRVBStart[core]+(ns<<1));
const int INPUT_SAMPLE_R=*(sRVBStart[core]+(ns<<1)+1);
const int IIR_INPUT_A0 = (g_buffer(rvb[core].IIR_SRC_A0,core) * rvb[core].IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb[core].IN_COEF_L)/32768L;
const int IIR_INPUT_A1 = (g_buffer(rvb[core].IIR_SRC_A1,core) * rvb[core].IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb[core].IN_COEF_R)/32768L;
const int IIR_INPUT_B0 = (g_buffer(rvb[core].IIR_SRC_B0,core) * rvb[core].IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb[core].IN_COEF_L)/32768L;
const int IIR_INPUT_B1 = (g_buffer(rvb[core].IIR_SRC_B1,core) * rvb[core].IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb[core].IN_COEF_R)/32768L;
const int IIR_A0 = (IIR_INPUT_A0 * rvb[core].IIR_ALPHA)/32768L + (g_buffer(rvb[core].IIR_DEST_A0,core) * (32768L - rvb[core].IIR_ALPHA))/32768L;
const int IIR_A1 = (IIR_INPUT_A1 * rvb[core].IIR_ALPHA)/32768L + (g_buffer(rvb[core].IIR_DEST_A1,core) * (32768L - rvb[core].IIR_ALPHA))/32768L;
const int IIR_B0 = (IIR_INPUT_B0 * rvb[core].IIR_ALPHA)/32768L + (g_buffer(rvb[core].IIR_DEST_B0,core) * (32768L - rvb[core].IIR_ALPHA))/32768L;
const int IIR_B1 = (IIR_INPUT_B1 * rvb[core].IIR_ALPHA)/32768L + (g_buffer(rvb[core].IIR_DEST_B1,core) * (32768L - rvb[core].IIR_ALPHA))/32768L;
s_buffer1(rvb[core].IIR_DEST_A0, IIR_A0,core);
s_buffer1(rvb[core].IIR_DEST_A1, IIR_A1,core);
s_buffer1(rvb[core].IIR_DEST_B0, IIR_B0,core);
s_buffer1(rvb[core].IIR_DEST_B1, IIR_B1,core);
ACC0 = (g_buffer(rvb[core].ACC_SRC_A0,core) * rvb[core].ACC_COEF_A)/32768L +
(g_buffer(rvb[core].ACC_SRC_B0,core) * rvb[core].ACC_COEF_B)/32768L +
(g_buffer(rvb[core].ACC_SRC_C0,core) * rvb[core].ACC_COEF_C)/32768L +
(g_buffer(rvb[core].ACC_SRC_D0,core) * rvb[core].ACC_COEF_D)/32768L;
ACC1 = (g_buffer(rvb[core].ACC_SRC_A1,core) * rvb[core].ACC_COEF_A)/32768L +
(g_buffer(rvb[core].ACC_SRC_B1,core) * rvb[core].ACC_COEF_B)/32768L +
(g_buffer(rvb[core].ACC_SRC_C1,core) * rvb[core].ACC_COEF_C)/32768L +
(g_buffer(rvb[core].ACC_SRC_D1,core) * rvb[core].ACC_COEF_D)/32768L;
FB_A0 = g_buffer(rvb[core].MIX_DEST_A0 - rvb[core].FB_SRC_A,core);
FB_A1 = g_buffer(rvb[core].MIX_DEST_A1 - rvb[core].FB_SRC_A,core);
FB_B0 = g_buffer(rvb[core].MIX_DEST_B0 - rvb[core].FB_SRC_B,core);
FB_B1 = g_buffer(rvb[core].MIX_DEST_B1 - rvb[core].FB_SRC_B,core);
s_buffer(rvb[core].MIX_DEST_A0, ACC0 - (FB_A0 * rvb[core].FB_ALPHA)/32768L,core);
s_buffer(rvb[core].MIX_DEST_A1, ACC1 - (FB_A1 * rvb[core].FB_ALPHA)/32768L,core);
s_buffer(rvb[core].MIX_DEST_B0, (rvb[core].FB_ALPHA * ACC0)/32768L - (FB_A0 * (int)(rvb[core].FB_ALPHA^0xFFFF8000))/32768L - (FB_B0 * rvb[core].FB_X)/32768L,core);
s_buffer(rvb[core].MIX_DEST_B1, (rvb[core].FB_ALPHA * ACC1)/32768L - (FB_A1 * (int)(rvb[core].FB_ALPHA^0xFFFF8000))/32768L - (FB_B1 * rvb[core].FB_X)/32768L,core);
rvb[core].iLastRVBLeft = rvb[core].iRVBLeft;
rvb[core].iLastRVBRight = rvb[core].iRVBRight;
rvb[core].iRVBLeft = (g_buffer(rvb[core].MIX_DEST_A0,core)+g_buffer(rvb[core].MIX_DEST_B0,core))/3;
rvb[core].iRVBRight = (g_buffer(rvb[core].MIX_DEST_A1,core)+g_buffer(rvb[core].MIX_DEST_B1,core))/3;
rvb[core].iRVBLeft = (rvb[core].iRVBLeft * rvb[core].VolLeft) / 0x4000;
rvb[core].iRVBRight = (rvb[core].iRVBRight * rvb[core].VolRight) / 0x4000;
rvb[core].CurrAddr++;
if(rvb[core].CurrAddr>rvb[core].EndAddr) rvb[core].CurrAddr=rvb[core].StartAddr;
return rvb[core].iLastRVBLeft+(rvb[core].iRVBLeft-rvb[core].iLastRVBLeft)/2;
}
else // -> reverb off
{
rvb[core].iLastRVBLeft=rvb[core].iLastRVBRight=rvb[core].iRVBLeft=rvb[core].iRVBRight=0;
}
rvb[core].CurrAddr++;
if(rvb[core].CurrAddr>rvb[core].EndAddr) rvb[core].CurrAddr=rvb[core].StartAddr;
}
return rvb[core].iLastRVBLeft;
}
return 0;
}
////////////////////////////////////////////////////////////////////////
static INLINE int MixREVERBRight(int core)
{
if(iUseReverb==1) // Neill's reverb:
{
int i=rvb[core].iLastRVBRight+(rvb[core].iRVBRight-rvb[core].iLastRVBRight)/2;
rvb[core].iLastRVBRight=rvb[core].iRVBRight;
return i; // -> just return the last right reverb val (little bit scaled by the previous right val)
}
return 0;
}
////////////////////////////////////////////////////////////////////////
#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;
-----------------------------------------------------------------------------
*/

View file

@ -1,33 +0,0 @@
/***************************************************************************
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:
//
// 2004/04/04 - Pete
// - changed plugin to emulate PS2 spu
//
// 2002/05/15 - Pete
// - generic cleanup for the Peops release
//
//*************************************************************************//
INLINE void StartREVERB(int ch);
INLINE void StoreREVERB(int ch,int ns);

File diff suppressed because it is too large Load diff

View file

@ -1,39 +0,0 @@
/***************************************************************************
spu.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:
//
// 2004/04/04 - Pete
// - changed plugin to emulate PS2 spu
//
// 2002/05/15 - Pete
// - generic cleanup for the Peops release
//
//*************************************************************************//
void SetupTimer(void);
void RemoveTimer(void);
EXPORT_GCC void CALLBACK SPU2playADPCMchannel(xa_decode_t *xap);
EXPORT_GCC long CALLBACK SPU2init(void);
EXPORT_GCC long CALLBACK SPU2open(void *pDsp);
EXPORT_GCC void CALLBACK SPU2async(unsigned long cycle);
EXPORT_GCC void CALLBACK SPU2close(void);

View file

@ -1,41 +0,0 @@
/***************************************************************************
StdAfx.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 EXPORT_GCC
#include <stdlib.h>
#define RRand(range) (random()%range)
#include <string.h>
#include <math.h>
#undef CALLBACK
#define CALLBACK
#define DWORD unsigned long
#define LOWORD(l) ((unsigned short)(l))
#define HIWORD(l) ((unsigned short)(((unsigned long)(l) >> 16) & 0xFFFF))
#include "psemuxa.h"

View file

@ -1,363 +0,0 @@
/***************************************************************************
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
////////////////////////////////////////////////////////////////////////
// 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<NSSIZE && XAPlay!=XAFeed;ns++)
{
XALastVal=*XAPlay++;
if(XAPlay==XAEnd) XAPlay=XAStart;
SSumL[ns]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32767;
SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767;
}
if(XAPlay==XAFeed && XARepeat)
{
XARepeat--;
for(;ns<NSSIZE;ns++)
{
SSumL[ns]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32767;
SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767;
}
}
}
////////////////////////////////////////////////////////////////////////
// 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
iSize=((44100*xap->nsamples)/xap->freq); // get size
if(!iSize) return; // none? bye
if(XAFeed<XAPlay) iPlace=XAPlay-XAFeed; // how much space in my buf?
else iPlace=(XAEnd-XAFeed) + (XAPlay-XAStart);
if(iPlace==0) return; // no place at all
//----------------------------------------------------//
if(iXAPitch) // pitch change option?
{
static DWORD dwLT=0;
static DWORD dwFPS=0;
static int iFPSCnt=0;
static int iLastSize=0;
static DWORD dwL1=0;
DWORD dw=timeGetTime(),dw1,dw2;
iPlace=iSize;
dwFPS+=dw-dwLT;iFPSCnt++;
dwLT=dw;
if(iFPSCnt>=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<iSize;i++)
{
if(iUseInterpolation==2)
{
while(spos>=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<iSize;i++)
{
if(iUseInterpolation==2)
{
while(spos>=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<iSize;i++)
{
if(iUseInterpolation==2)
{
while(spos>=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<iSize;i++)
{
if(iUseInterpolation==2)
{
while(spos>=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

File diff suppressed because it is too large Load diff

View file

@ -1,288 +0,0 @@
#ifndef _MIPS_H
#define _MIPS_H
#include "ao.h"
//#include "driver.h"
typedef void genf(void);
typedef int offs_t;
#define cpu_readop32(pc) program_read_dword_32le(pc)
#define change_pc(pc) \
#ifdef __GNUC__
#if (__GNUC__ < 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ <= 7))
#define UNUSEDARG
#else
#define UNUSEDARG __attribute__((__unused__))
#endif
#else
#define UNUSEDARG
#endif
typedef int8 (*read8_handler) (UNUSEDARG offs_t offset);
typedef void (*write8_handler) (UNUSEDARG offs_t offset, UNUSEDARG int8 data);
typedef int16 (*read16_handler) (UNUSEDARG offs_t offset, UNUSEDARG int16 mem_mask);
typedef void (*write16_handler)(UNUSEDARG offs_t offset, UNUSEDARG int16 data, UNUSEDARG int16 mem_mask);
typedef int32 (*read32_handler) (UNUSEDARG offs_t offset, UNUSEDARG int32 mem_mask);
typedef void (*write32_handler)(UNUSEDARG offs_t offset, UNUSEDARG int32 data, UNUSEDARG int32 mem_mask);
typedef int64 (*read64_handler) (UNUSEDARG offs_t offset, UNUSEDARG int64 mem_mask);
typedef void (*write64_handler)(UNUSEDARG offs_t offset, UNUSEDARG int64 data, UNUSEDARG int64 mem_mask);
union read_handlers_t
{
genf * handler;
read8_handler handler8;
read16_handler handler16;
read32_handler handler32;
read64_handler handler64;
};
union write_handlers_t
{
genf * handler;
write8_handler handler8;
write16_handler handler16;
write32_handler handler32;
write64_handler handler64;
};
struct address_map_t
{
uint32 flags; /* flags and additional info about this entry */
offs_t start, end; /* start/end (or mask/match) values */
offs_t mirror; /* mirror bits */
offs_t mask; /* mask bits */
union read_handlers_t read; /* read handler callback */
union write_handlers_t write; /* write handler callback */
void * memory; /* pointer to memory backing this entry */
uint32 share; /* index of a shared memory block */
void ** base; /* receives pointer to memory (optional) */
size_t * size; /* receives size of area in bytes (optional) */
};
typedef struct address_map_t *(*construct_map_t)(struct address_map_t *map);
union cpuinfo
{
int64 i; /* generic integers */
void * p; /* generic pointers */
genf * f; /* generic function pointers */
char * s; /* generic strings */
void (*setinfo)(UINT32 state, union cpuinfo *info);/* CPUINFO_PTR_SET_INFO */
void (*getcontext)(void *context); /* CPUINFO_PTR_GET_CONTEXT */
void (*setcontext)(void *context); /* CPUINFO_PTR_SET_CONTEXT */
void (*init)(void); /* CPUINFO_PTR_INIT */
void (*reset)(void *param); /* CPUINFO_PTR_RESET */
void (*exit)(void); /* CPUINFO_PTR_EXIT */
int (*execute)(int cycles); /* CPUINFO_PTR_EXECUTE */
void (*burn)(int cycles); /* CPUINFO_PTR_BURN */
offs_t (*disassemble)(char *buffer, offs_t pc); /* CPUINFO_PTR_DISASSEMBLE */
int (*irqcallback)(int state); /* CPUINFO_PTR_IRQCALLBACK */
int * icount; /* CPUINFO_PTR_INSTRUCTION_COUNTER */
construct_map_t internal_map; /* CPUINFO_PTR_INTERNAL_MEMORY_MAP */
};
enum
{
MIPS_PC = 1,
MIPS_DELAYV, MIPS_DELAYR,
MIPS_HI, MIPS_LO,
MIPS_R0, MIPS_R1,
MIPS_R2, MIPS_R3,
MIPS_R4, MIPS_R5,
MIPS_R6, MIPS_R7,
MIPS_R8, MIPS_R9,
MIPS_R10, MIPS_R11,
MIPS_R12, MIPS_R13,
MIPS_R14, MIPS_R15,
MIPS_R16, MIPS_R17,
MIPS_R18, MIPS_R19,
MIPS_R20, MIPS_R21,
MIPS_R22, MIPS_R23,
MIPS_R24, MIPS_R25,
MIPS_R26, MIPS_R27,
MIPS_R28, MIPS_R29,
MIPS_R30, MIPS_R31,
MIPS_CP0R0, MIPS_CP0R1,
MIPS_CP0R2, MIPS_CP0R3,
MIPS_CP0R4, MIPS_CP0R5,
MIPS_CP0R6, MIPS_CP0R7,
MIPS_CP0R8, MIPS_CP0R9,
MIPS_CP0R10, MIPS_CP0R11,
MIPS_CP0R12, MIPS_CP0R13,
MIPS_CP0R14, MIPS_CP0R15,
MIPS_CP0R16, MIPS_CP0R17,
MIPS_CP0R18, MIPS_CP0R19,
MIPS_CP0R20, MIPS_CP0R21,
MIPS_CP0R22, MIPS_CP0R23,
MIPS_CP0R24, MIPS_CP0R25,
MIPS_CP0R26, MIPS_CP0R27,
MIPS_CP0R28, MIPS_CP0R29,
MIPS_CP0R30, MIPS_CP0R31,
MIPS_CP2DR0, MIPS_CP2DR1,
MIPS_CP2DR2, MIPS_CP2DR3,
MIPS_CP2DR4, MIPS_CP2DR5,
MIPS_CP2DR6, MIPS_CP2DR7,
MIPS_CP2DR8, MIPS_CP2DR9,
MIPS_CP2DR10, MIPS_CP2DR11,
MIPS_CP2DR12, MIPS_CP2DR13,
MIPS_CP2DR14, MIPS_CP2DR15,
MIPS_CP2DR16, MIPS_CP2DR17,
MIPS_CP2DR18, MIPS_CP2DR19,
MIPS_CP2DR20, MIPS_CP2DR21,
MIPS_CP2DR22, MIPS_CP2DR23,
MIPS_CP2DR24, MIPS_CP2DR25,
MIPS_CP2DR26, MIPS_CP2DR27,
MIPS_CP2DR28, MIPS_CP2DR29,
MIPS_CP2DR30, MIPS_CP2DR31,
MIPS_CP2CR0, MIPS_CP2CR1,
MIPS_CP2CR2, MIPS_CP2CR3,
MIPS_CP2CR4, MIPS_CP2CR5,
MIPS_CP2CR6, MIPS_CP2CR7,
MIPS_CP2CR8, MIPS_CP2CR9,
MIPS_CP2CR10, MIPS_CP2CR11,
MIPS_CP2CR12, MIPS_CP2CR13,
MIPS_CP2CR14, MIPS_CP2CR15,
MIPS_CP2CR16, MIPS_CP2CR17,
MIPS_CP2CR18, MIPS_CP2CR19,
MIPS_CP2CR20, MIPS_CP2CR21,
MIPS_CP2CR22, MIPS_CP2CR23,
MIPS_CP2CR24, MIPS_CP2CR25,
MIPS_CP2CR26, MIPS_CP2CR27,
MIPS_CP2CR28, MIPS_CP2CR29,
MIPS_CP2CR30, MIPS_CP2CR31
};
#define MIPS_INT_NONE ( -1 )
#define MIPS_IRQ0 ( 0 )
#define MIPS_IRQ1 ( 1 )
#define MIPS_IRQ2 ( 2 )
#define MIPS_IRQ3 ( 3 )
#define MIPS_IRQ4 ( 4 )
#define MIPS_IRQ5 ( 5 )
#define MIPS_BYTE_EXTEND( a ) ( (INT32)(INT8)a )
#define MIPS_WORD_EXTEND( a ) ( (INT32)(INT16)a )
#define INS_OP( op ) ( ( op >> 26 ) & 63 )
#define INS_RS( op ) ( ( op >> 21 ) & 31 )
#define INS_RT( op ) ( ( op >> 16 ) & 31 )
#define INS_IMMEDIATE( op ) ( op & 0xffff )
#define INS_TARGET( op ) ( op & 0x3ffffff )
#define INS_RD( op ) ( ( op >> 11 ) & 31 )
#define INS_SHAMT( op ) ( ( op >> 6 ) & 31 )
#define INS_FUNCT( op ) ( op & 63 )
#define INS_CODE( op ) ( ( op >> 6 ) & 0xfffff )
#define INS_CO( op ) ( ( op >> 25 ) & 1 )
#define INS_COFUN( op ) ( op & 0x1ffffff )
#define INS_CF( op ) ( op & 63 )
#define GTE_OP( op ) ( ( op >> 20 ) & 31 )
#define GTE_SF( op ) ( ( op >> 19 ) & 1 )
#define GTE_MX( op ) ( ( op >> 17 ) & 3 )
#define GTE_V( op ) ( ( op >> 15 ) & 3 )
#define GTE_CV( op ) ( ( op >> 13 ) & 3 )
#define GTE_CD( op ) ( ( op >> 11 ) & 3 ) /* not used */
#define GTE_LM( op ) ( ( op >> 10 ) & 1 )
#define GTE_CT( op ) ( ( op >> 6 ) & 15 ) /* not used */
#define GTE_FUNCT( op ) ( op & 63 )
#define OP_SPECIAL ( 0 )
#define OP_REGIMM ( 1 )
#define OP_J ( 2 )
#define OP_JAL ( 3 )
#define OP_BEQ ( 4 )
#define OP_BNE ( 5 )
#define OP_BLEZ ( 6 )
#define OP_BGTZ ( 7 )
#define OP_ADDI ( 8 )
#define OP_ADDIU ( 9 )
#define OP_SLTI ( 10 )
#define OP_SLTIU ( 11 )
#define OP_ANDI ( 12 )
#define OP_ORI ( 13 )
#define OP_XORI ( 14 )
#define OP_LUI ( 15 )
#define OP_COP0 ( 16 )
#define OP_COP1 ( 17 )
#define OP_COP2 ( 18 )
#define OP_LB ( 32 )
#define OP_LH ( 33 )
#define OP_LWL ( 34 )
#define OP_LW ( 35 )
#define OP_LBU ( 36 )
#define OP_LHU ( 37 )
#define OP_LWR ( 38 )
#define OP_SB ( 40 )
#define OP_SH ( 41 )
#define OP_SWL ( 42 )
#define OP_SW ( 43 )
#define OP_SWR ( 46 )
#define OP_LWC1 ( 49 )
#define OP_LWC2 ( 50 )
#define OP_SWC1 ( 57 )
#define OP_SWC2 ( 58 )
/* OP_SPECIAL */
#define FUNCT_SLL ( 0 )
#define FUNCT_SRL ( 2 )
#define FUNCT_SRA ( 3 )
#define FUNCT_SLLV ( 4 )
#define FUNCT_SRLV ( 6 )
#define FUNCT_SRAV ( 7 )
#define FUNCT_JR ( 8 )
#define FUNCT_JALR ( 9 )
#define FUNCT_HLECALL ( 11 )
#define FUNCT_SYSCALL ( 12 )
#define FUNCT_BREAK ( 13 )
#define FUNCT_MFHI ( 16 )
#define FUNCT_MTHI ( 17 )
#define FUNCT_MFLO ( 18 )
#define FUNCT_MTLO ( 19 )
#define FUNCT_MULT ( 24 )
#define FUNCT_MULTU ( 25 )
#define FUNCT_DIV ( 26 )
#define FUNCT_DIVU ( 27 )
#define FUNCT_ADD ( 32 )
#define FUNCT_ADDU ( 33 )
#define FUNCT_SUB ( 34 )
#define FUNCT_SUBU ( 35 )
#define FUNCT_AND ( 36 )
#define FUNCT_OR ( 37 )
#define FUNCT_XOR ( 38 )
#define FUNCT_NOR ( 39 )
#define FUNCT_SLT ( 42 )
#define FUNCT_SLTU ( 43 )
/* OP_REGIMM */
#define RT_BLTZ ( 0 )
#define RT_BGEZ ( 1 )
#define RT_BLTZAL ( 16 )
#define RT_BGEZAL ( 17 )
/* OP_COP0/OP_COP1/OP_COP2 */
#define RS_MFC ( 0 )
#define RS_CFC ( 2 )
#define RS_MTC ( 4 )
#define RS_CTC ( 6 )
#define RS_BC ( 8 )
/* RS_BC */
#define RT_BCF ( 0 )
#define RT_BCT ( 1 )
/* OP_COP0 */
#define CF_RFE ( 16 )
#ifdef MAME_DEBUG
extern unsigned DasmMIPS(char *buff, unsigned _pc);
#endif
#if (HAS_PSXCPU)
extern void psxcpu_get_info(UINT32 state, union cpuinfo *info);
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,446 +0,0 @@
/*
Audio Overload SDK - QSF file engine
Copyright (c) 2007, R. Belmont and Richard Bannister.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//
// eng_qsf.c
// by R. Belmont
//
/*
The program section of a QSF file, once decompressed, contains a series of
data blocks of the form:
3 bytes - ASCII section name tag
4 bytes - Starting offset (LSB-first)
4 bytes - Length (N) (LSB-first)
N bytes - Data
The data is then loaded to the given starting offset in the section described
by the ASCII tag.
The following sections are defined:
"KEY" - Kabuki decryption key. This section should be 11 bytes and contain
the following:
4 bytes - swap_key1 (MSB-first)
4 bytes - swap_key2 (MSB-first)
2 bytes - addr_key (MSB-first)
1 bytes - xor_key
"Z80" - Z80 program ROM.
"SMP" - QSound sample ROM.
If the KEY section isn't given or both swap_keys are zero, then it is assumed
that no encryption is used.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ao.h"
#include "qsound.h"
#include "z80.h"
#include "corlett.h"
#define DEBUG_LOADER (0)
// timer rate is 285 Hz
static int32 samples_per_tick = 44100/285;
static int32 samples_to_next_tick = 44100/285;
static corlett_t *c = NULL;
static char qsfby[256];
static uint32 skey1, skey2;
static uint16 akey;
static uint8 xkey;
static int32 uses_kabuki = 0;
static char *Z80ROM, *QSamples;
static char RAM[0x1000], RAM2[0x1000];
static int32 cur_bank;
static struct QSound_interface qsintf =
{
QSOUND_CLOCK,
NULL
};
extern void cps1_decode(unsigned char *rom, int swap_key1,int swap_key2,int addr_key,int xor_key);
static void qsf_walktags(uint8 *buffer, uint8 *end)
{
uint8 *cbuf = buffer;
uint32 offset, length;
while (cbuf < end)
{
#if DEBUG_LOADER
printf("cbuf: %08x end: %08x\n", (uint32)cbuf, (uint32)end);
#endif
offset = cbuf[3] | cbuf[4]<<8 | cbuf[5]<<16 | cbuf[6]<<24;
length = cbuf[7] | cbuf[8]<<8 | cbuf[9]<<16 | cbuf[10]<<24;
#if DEBUG_LOADER
printf("Tag: %c%c%c @ %08x, length %08x\n", cbuf[0], cbuf[1], cbuf[2], offset, length);
#endif
switch (cbuf[0])
{
case 'Z':
memcpy(&Z80ROM[offset], &cbuf[11], length);
break;
case 'S':
memcpy(&QSamples[offset], &cbuf[11], length);
break;
case 'K':
skey1 = cbuf[11]<<24 | cbuf[12]<<16 | cbuf[13]<<8 | cbuf[14];
skey2 = cbuf[15]<<24 | cbuf[16]<<16 | cbuf[17]<<8 | cbuf[18];
akey = cbuf[19]<<8 | cbuf[20];
xkey = cbuf[20];
break;
default:
printf("ERROR: Unknown QSF tag!\n");
break;
}
cbuf += 11;
cbuf += length;
}
}
static int32 qsf_irq_cb(int param)
{
return 0x000000ff; // RST_38
}
int32 qsf_start(uint8 *buffer, uint32 length)
{
uint8 *file, *lib_decoded, *lib_raw_file;
uint64 file_len, lib_len, lib_raw_length;
corlett_t *lib;
z80_init();
Z80ROM = malloc(512*1024);
QSamples = malloc(8*1024*1024);
skey1 = skey2 = 0;
akey = 0;
xkey = 0;
cur_bank = 0;
memset(RAM, 0, 0x1000);
memset(RAM2, 0, 0x1000);
// Decode the current QSF
if (corlett_decode(buffer, length, &file, &file_len, &c) != AO_SUCCESS)
{
return AO_FAIL;
}
// Get the library file
if (c->lib[0] != 0)
{
uint64 tmp_length;
#if DEBUG_LOADER
printf("Loading library: %s\n", c->lib);
#endif
if (ao_get_lib(c->lib, &lib_raw_file, &tmp_length) != AO_SUCCESS)
{
return AO_FAIL;
}
lib_raw_length = tmp_length;
if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS)
{
free(lib_raw_file);
return AO_FAIL;
}
// Free up raw file
free(lib_raw_file);
// use the contents
qsf_walktags(lib_decoded, lib_decoded+lib_len);
// Dispose the corlett structure for the lib - we don't use it
free(lib);
free(lib_decoded);
}
// now patch the file into RAM OVER the libraries
qsf_walktags(file, file+file_len);
free(file);
if ((skey1 != 0) && (skey2 != 0))
{
#if DEBUG_LOADER
printf("Decoding Kabuki: skey1 %08x skey2 %08x akey %04x xkey %02x\n", skey1, skey2, akey, xkey);
#endif
uses_kabuki = 1;
cps1_decode((unsigned char *)Z80ROM, skey1, skey2, akey, xkey);
}
// set qsfby tag
strcpy(qsfby, "n/a");
if (c)
{
int i;
for (i = 0; i < MAX_UNKNOWN_TAGS; i++)
{
if (!strcasecmp(c->tag_name[i], "qsfby"))
{
strcpy(qsfby, c->tag_data[i]);
}
}
}
z80_reset(NULL);
z80_set_irq_callback(qsf_irq_cb);
qsintf.sample_rom = QSamples;
qsound_sh_start(&qsintf);
return AO_SUCCESS;
}
static void timer_tick(void)
{
z80_set_irq_line(0, ASSERT_LINE);
z80_set_irq_line(0, CLEAR_LINE);
}
int32 qsf_gen(int16 *buffer, uint32 samples)
{
int16 output[44100/30], output2[44100/30];
int16 *stereo[2];
int16 *outp = buffer;
int32 i, opos, tickinc, loops;
// our largest possible step is samples_per_tick or samples, whichever is smaller
if (samples_to_next_tick > samples)
{
tickinc = samples;
}
else
{
tickinc = samples_to_next_tick;
}
loops = samples / tickinc;
opos = 0;
for (i = 0; i < loops; i++)
{
z80_execute((8000000/44100)*tickinc);
stereo[0] = &output[opos];
stereo[1] = &output2[opos];
qsound_update(0, stereo, tickinc);
opos += tickinc;
samples_to_next_tick -= tickinc;
if (samples_to_next_tick <= 0)
{
timer_tick();
samples_to_next_tick = samples_per_tick;
}
}
// are there "leftovers"?
if (opos < samples)
{
z80_execute((8000000/44100)*(samples-opos));
stereo[0] = &output[opos];
stereo[1] = &output2[opos];
qsound_update(0, stereo, (samples-opos));
samples_to_next_tick -= (samples-opos);
if (samples_to_next_tick <= 0)
{
timer_tick();
samples_to_next_tick = samples_per_tick;
}
}
for (i = 0; i < samples; i++)
{
*outp++ = output[i];
*outp++ = output2[i];
}
return AO_SUCCESS;
}
int32 qsf_stop(void)
{
z80_exit();
free(Z80ROM);
free(QSamples);
free(c);
return AO_SUCCESS;
}
int32 qsf_command(int32 command, int32 parameter)
{
switch (command)
{
case COMMAND_RESTART:
return AO_SUCCESS;
}
return AO_FAIL;
}
int32 qsf_fill_info(ao_display_info *info)
{
if (c == NULL)
return AO_FAIL;
strcpy(info->title[1], "Name: ");
sprintf(info->info[1], "%s", c->inf_title);
strcpy(info->title[2], "Game: ");
sprintf(info->info[2], "%s", c->inf_game);
strcpy(info->title[3], "Artist: ");
sprintf(info->info[3], "%s", c->inf_artist);
strcpy(info->title[4], "Copyright: ");
sprintf(info->info[4], "%s", c->inf_copy);
strcpy(info->title[5], "Year: ");
sprintf(info->info[5], "%s", c->inf_year);
strcpy(info->title[6], "Length: ");
sprintf(info->info[6], "%s", c->inf_length);
strcpy(info->title[7], "Fade: ");
sprintf(info->info[7], "%s", c->inf_fade);
strcpy(info->title[8], "Ripper: ");
sprintf(info->info[8], "%s", qsfby);
return AO_SUCCESS;
}
uint8 qsf_memory_read(uint16 addr)
{
if (addr < 0x8000)
{
return Z80ROM[addr];
}
else if (addr < 0xc000)
{
return Z80ROM[(addr - 0x8000) + cur_bank];
}
else if (addr <= 0xcfff)
{
return RAM[addr - 0xc000];
}
else if (addr == 0xd007)
{
return qsound_status_r();
}
else if (addr >= 0xf000)
{
return RAM2[addr-0xf000];
}
}
uint8 qsf_memory_readop(uint16 addr)
{
if (!uses_kabuki)
{
return qsf_memory_read(addr);
}
if (addr < 0x8000)
{
return Z80ROM[addr + (256*1024)];
}
return qsf_memory_read(addr);
}
uint8 qsf_memory_readport(uint16 addr)
{
return Z80ROM[0x11];
}
void qsf_memory_write(uint16 addr, uint8 byte)
{
if (addr >= 0xc000 && addr <= 0xcfff)
{
RAM[addr-0xc000] = byte;
return;
}
else if (addr == 0xd000)
{
qsound_data_h_w(byte);
return;
}
else if (addr == 0xd001)
{
qsound_data_l_w(byte);
return;
}
else if (addr == 0xd002)
{
qsound_cmd_w(byte);
return;
}
else if (addr == 0xd003)
{
cur_bank = (0x8000 + (byte & 0xf) * 0x4000);
if (cur_bank > (256*1024))
{
cur_bank = 0;
}
// printf("Z80 bank to %x (%x)\n", cur_bank, byte);
return;
}
else if (addr >= 0xf000)
{
RAM2[addr-0xf000] = byte;
return;
}
}
void qsf_memory_writeport(uint16 addr, uint8 byte)
{
printf("Unk port %x @ %x\n", byte, addr);
}

View file

@ -1,156 +0,0 @@
/***************************************************************************
"Kabuki" Z80 encryption
The "Kabuki" is a custom Z80 module which runs encrypted code. The encryption
key is stored in some battery-backed RAM, therefore the chip has the annoying
habit of stopping working every few years, when the battery dies.
Check at the bottom of this text to see a list of all the known games which
use this chip.
How it works:
The base operation is a bit swap which affects couples of adjacent bits.
Each of the 4 couples may or may not be swapped, depending on the address of
the byte and on whether it is an opcode or data.
The decryption consists of these steps:
- bitswap
- ROL
- bitswap
- XOR with a key
- ROL
- bitswap
- ROL
- bitswap
To know how to apply the bit swap, take the address of the byte to decode and:
- if the byte is an opcode, add addr_key to the address
- if the byte is data, XOR the address with 1FC0, add 1, and then add addr_key
You'll get a 16-bit word. The first two bitswaps depend on bits 0-7 of that
word, while the second two on bits 8-15. When a bit in the word is 1, swap the
two bits, oherwise don't. The exact couple of bits affected depends on the
game and is identified in this file with two keys: swap_key1 and swap_key2
(which are just permutations of the numbers 0-7, not full 32-bit integers).
Key space size:
- swap_key1 8! = 40320
- swap_key2 8! = 40320
- addr_key 2^16 = 65536
- xor_key 2^8 = 256
- total 2.7274 * 10^16
Weaknesses:
- 0x00 and 0xff, having all the bits set to the same value, are not affected
by bit permutations after the XOR. Therefore, their encryption is the same
regardless of the high 8 bits of the address, and of the value of
swap_key2. If there is a long stream of 0x00 or 0xff in the original data,
this can be used to find by brute force all the candidates for swap_key1,
xor_key, and for the low 8 bits of addr_key. This is a serious weakness
which dramatically reduces the security of the encryption.
- A 0x00 is always encrypted as a byte with as many 1s as xor_key; a 0xff is
always encrypted as a byte with as many 0s as xor_key has 1s. So you just
need to know one 0x00 or 0xff in the unencrypted data to know how many 1s
there are in xor_key.
- Once you have restricted the range for swap_key1 and you know the number of
1s in the xor_key, you can easily use known plaintext attacks and brute
force to find the remaining keys. Long strings like THIS GAME IS FOR USE IN
and ABCDEFGHIJKLMNOPQRSTUVWXYZ can be found by comparing the number of 1s
in the clear and encrypted data, taking xor_key into account. When you have
found where the string is, use brute force to reduce the key space.
Known games:
swap_key1 swap_key2 addr_key xor_key
Mahjong Gakuen 2 Gakuen-chou no Fukushuu 76543210 01234567 aa55 a5
Poker Ladies " " " " "" ""
Dokaben " " " " "" ""
Dokaben 2 unknown
Pang / Buster Bros / Pomping World 01234567 76543210 6548 24
Capcom Baseball " " " " "" ""
Capcom World 04152637 40516273 5751 43
Adventure Quiz 2 Hatena ? no Dai-Bouken 45670123 45670123 5751 43
Super Pang 45670123 45670123 5852 43
Super Buster Bros 45670123 45670123 2130 12
Super Marukin-Ban 54321076 54321076 4854 4f
Quiz Tonosama no Yabou 12345670 12345670 1111 11
Ashita Tenki ni Naare unknown
Quiz Sangokushi 23456701 23456701 1828 18
Block Block 02461357 64207531 0002 01
Warriors of Fate 01234567 54163072 5151 51
Cadillacs and Dinosaurs 76543210 24601357 4343 43
Punisher 67452103 75316024 2222 22
Slam Masters 54321076 65432107 3131 19
***************************************************************************/
#include "cpuintrf.h"
static int bitswap1(int src,int key,int sel)
{
if (sel & (1 << ((key >> 0) & 7)))
src = (src & 0xfc) | ((src & 0x01) << 1) | ((src & 0x02) >> 1);
if (sel & (1 << ((key >> 4) & 7)))
src = (src & 0xf3) | ((src & 0x04) << 1) | ((src & 0x08) >> 1);
if (sel & (1 << ((key >> 8) & 7)))
src = (src & 0xcf) | ((src & 0x10) << 1) | ((src & 0x20) >> 1);
if (sel & (1 << ((key >>12) & 7)))
src = (src & 0x3f) | ((src & 0x40) << 1) | ((src & 0x80) >> 1);
return src;
}
static int bitswap2(int src,int key,int sel)
{
if (sel & (1 << ((key >>12) & 7)))
src = (src & 0xfc) | ((src & 0x01) << 1) | ((src & 0x02) >> 1);
if (sel & (1 << ((key >> 8) & 7)))
src = (src & 0xf3) | ((src & 0x04) << 1) | ((src & 0x08) >> 1);
if (sel & (1 << ((key >> 4) & 7)))
src = (src & 0xcf) | ((src & 0x10) << 1) | ((src & 0x20) >> 1);
if (sel & (1 << ((key >> 0) & 7)))
src = (src & 0x3f) | ((src & 0x40) << 1) | ((src & 0x80) >> 1);
return src;
}
static int bytedecode(int src,int swap_key1,int swap_key2,int xor_key,int sel)
{
src = bitswap1(src,swap_key1 & 0xffff,sel & 0xff);
src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7);
src = bitswap2(src,swap_key1 >> 16,sel & 0xff);
src ^= xor_key;
src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7);
src = bitswap2(src,swap_key2 & 0xffff,sel >> 8);
src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7);
src = bitswap1(src,swap_key2 >> 16,sel >> 8);
return src;
}
static void kabuki_decode(unsigned char *src,unsigned char *dest_op,unsigned char *dest_data,
int base_addr,int length,int swap_key1,int swap_key2,int addr_key,int xor_key)
{
int A;
int sel;
for (A = 0; A < length; A++)
{
/* decode opcodes */
sel = (A + base_addr) + addr_key;
dest_op[A] = bytedecode(src[A],swap_key1,swap_key2,xor_key,sel);
/* decode data */
sel = ((A + base_addr) ^ 0x1fc0) + addr_key + 1;
dest_data[A] = bytedecode(src[A],swap_key1,swap_key2,xor_key,sel);
}
}
void cps1_decode(unsigned char *rom, int swap_key1,int swap_key2,int addr_key,int xor_key)
{
int diff = (512*1024)/2;
kabuki_decode(rom, rom+diff, rom, 0x0000, 0x8000, swap_key1, swap_key2, addr_key, xor_key);
}

View file

@ -1,525 +0,0 @@
/***************************************************************************
Capcom System QSound(tm)
========================
Driver by Paul Leaman (paul@vortexcomputing.demon.co.uk)
and Miguel Angel Horna (mahorna@teleline.es)
A 16 channel stereo sample player.
QSpace position is simulated by panning the sound in the stereo space.
Register
0 xxbb xx = unknown bb = start high address
1 ssss ssss = sample start address
2 pitch
3 unknown (always 0x8000)
4 loop offset from end address
5 end
6 master channel volume
7 not used
8 Balance (left=0x0110 centre=0x0120 right=0x0130)
9 unknown (most fixed samples use 0 for this register)
Many thanks to CAB (the author of Amuse), without whom this probably would
never have been finished.
If anybody has some information about this hardware, please send it to me
to mahorna@teleline.es or 432937@cepsz.unizar.es.
http://teleline.terra.es/personal/mahorna
***************************************************************************/
#include <math.h>
#include "cpuintrf.h"
#include "qsound.h"
/*
Two Q sound drivers:
DRIVER1 Based on the Amuse source
DRIVER2 Miguel Angel Horna (mahorna@teleline.es)
*/
#define QSOUND_DRIVER1 1
/*
I don't know whether this system uses 8 bit or 16 bit samples.
If it uses 16 bit samples then the sample ROM loading macros need
to be modified to work with non-intel machines.
*/
#define QSOUND_8BIT_SAMPLES 1
/*
Debug defines
*/
#define LOG_WAVE 0
#define LOG_QSOUND 0
/* Typedefs & defines */
#define QSOUND_DRIVER2 !QSOUND_DRIVER1
#if QSOUND_8BIT_SAMPLES
/* 8 bit source ROM samples */
typedef signed char QSOUND_SRC_SAMPLE;
#define LENGTH_DIV 1
#else
/* 8 bit source ROM samples */
typedef signed short QSOUND_SRC_SAMPLE;
#define LENGTH_DIV 2
#endif
#define QSOUND_CLOCKDIV 166 /* Clock divider */
#define QSOUND_CHANNELS 16
typedef INT16 QSOUND_SAMPLE;
struct QSOUND_CHANNEL
{
int bank; /* bank (x16) */
int address; /* start address */
int pitch; /* pitch */
int reg3; /* unknown (always 0x8000) */
int loop; /* loop address */
int end; /* end address */
int vol; /* master volume */
int pan; /* Pan value */
int reg9; /* unknown */
/* Work variables */
int key; /* Key on / key off */
#if QSOUND_DRIVER1
int lvol; /* left volume */
int rvol; /* right volume */
int lastdt; /* last sample value */
int offset; /* current offset counter */
#else
QSOUND_SRC_SAMPLE *buffer;
int factor; /*step factor (fixed point 8-bit)*/
int mixl,mixr; /*mixing factor (fixed point)*/
int cursor; /*current sample position (fixed point)*/
int lpos; /*last cursor pos*/
int lastsaml; /*last left sample (to avoid any calculation)*/
int lastsamr; /*last right sample*/
#endif
};
/* Private variables */
static struct QSound_interface *intf; /* Interface */
static int qsound_stream; /* Audio stream */
static struct QSOUND_CHANNEL qsound_channel[QSOUND_CHANNELS];
static int qsound_data; /* register latch data */
QSOUND_SRC_SAMPLE *qsound_sample_rom; /* Q sound sample ROM */
#if QSOUND_DRIVER1
static int qsound_pan_table[33]; /* Pan volume table */
static float qsound_frq_ratio; /* Frequency ratio */
#endif
#if LOG_WAVE
static FILE *fpRawDataL;
static FILE *fpRawDataR;
#endif
/* Function prototypes */
void qsound_update( int num, INT16 **buffer, int length );
void qsound_set_command(int data, int value);
#if QSOUND_DRIVER2
void setchannel(int channel,signed short *buffer,int length,int vol,int pan);
void setchloop(int channel,int loops,int loope);
void stopchan(int channel);
void calcula_mix(int channel);
#endif
int qsound_sh_start( struct QSound_interface *qsintf )
{
int i;
intf = qsintf;
qsound_sample_rom = (QSOUND_SRC_SAMPLE *)intf->sample_rom;
memset(qsound_channel, 0, sizeof(qsound_channel));
#if QSOUND_DRIVER1
qsound_frq_ratio = ((float)intf->clock / (float)QSOUND_CLOCKDIV) /
(float) 44100;
qsound_frq_ratio *= 16.0;
/* Create pan table */
for (i=0; i<33; i++)
{
qsound_pan_table[i]=(int)((256/sqrt(32)) * sqrt(i));
}
#else
i=0;
#endif
#if LOG_QSOUND
logerror("Pan table\n");
for (i=0; i<33; i++)
logerror("%02x ", qsound_pan_table[i]);
#endif
#if 0
{
/* Allocate stream */
#define CHANNELS ( 2 )
char buf[CHANNELS][40];
const char *name[CHANNELS];
int vol[2];
name[0] = buf[0];
name[1] = buf[1];
sprintf( buf[0], "%s L", sound_name(msound) );
sprintf( buf[1], "%s R", sound_name(msound) );
vol[0]=MIXER(intf->mixing_level[0], MIXER_PAN_LEFT);
vol[1]=MIXER(intf->mixing_level[1], MIXER_PAN_RIGHT);
qsound_stream = stream_init_multi(
CHANNELS,
name,
vol,
Machine->sample_rate,
0,
qsound_update );
}
#endif
#if LOG_WAVE
fpRawDataR=fopen("qsoundr.raw", "w+b");
fpRawDataL=fopen("qsoundl.raw", "w+b");
if (!fpRawDataR || !fpRawDataL)
{
return 1;
}
#endif
return 0;
}
void qsound_sh_stop (void)
{
#if LOG_WAVE
if (fpRawDataR)
{
fclose(fpRawDataR);
}
if (fpRawDataL)
{
fclose(fpRawDataL);
}
#endif
}
void qsound_data_h_w(int data)
{
qsound_data=(qsound_data&0xff)|(data<<8);
}
void qsound_data_l_w(int data)
{
qsound_data=(qsound_data&0xff00)|data;
}
void qsound_cmd_w(int data)
{
// printf("QS: cmd %x, data %x\n", data, qsound_data);
qsound_set_command(data, qsound_data);
}
int qsound_status_r(void)
{
/* Port ready bit (0x80 if ready) */
return 0x80;
}
void qsound_set_command(int data, int value)
{
int ch=0,reg=0;
if (data < 0x80)
{
ch=data>>3;
reg=data & 0x07;
}
else
{
if (data < 0x90)
{
ch=data-0x80;
reg=8;
}
else
{
if (data >= 0xba && data < 0xca)
{
ch=data-0xba;
reg=9;
}
else
{
/* Unknown registers */
ch=99;
reg=99;
}
}
}
switch (reg)
{
case 0: /* Bank */
ch=(ch+1)&0x0f; /* strange ... */
qsound_channel[ch].bank=(value&0x7f)<<16;
qsound_channel[ch].bank /= LENGTH_DIV;
#ifdef MAME_DEBUG
if (!value & 0x8000)
{
char baf[40];
sprintf(baf,"Register3=%04x",value);
usrintf_showmessage(baf);
}
#endif
break;
case 1: /* start */
// printf("QS: key on ch %02d\n", ch);
qsound_channel[ch].address=value;
qsound_channel[ch].address/=LENGTH_DIV;
break;
case 2: /* pitch */
#if QSOUND_DRIVER1
qsound_channel[ch].pitch=(long)
((float)value * qsound_frq_ratio );
qsound_channel[ch].pitch/=LENGTH_DIV;
#else
qsound_channel[ch].factor=((float) (value*(6/LENGTH_DIV)) /
(float) Machine->sample_rate)*256.0;
#endif
if (!value)
{
/* Key off */
// printf("QS: key off ch %02d\n", ch);
qsound_channel[ch].key=0;
}
break;
case 3: /* unknown */
qsound_channel[ch].reg3=value;
#ifdef MAME_DEBUG
if (value != 0x8000)
{
char baf[40];
sprintf(baf,"Register3=%04x",value);
usrintf_showmessage(baf);
}
#endif
break;
case 4: /* loop offset */
qsound_channel[ch].loop=value/LENGTH_DIV;
break;
case 5: /* end */
qsound_channel[ch].end=value/LENGTH_DIV;
break;
case 6: /* master volume */
if (value==0)
{
/* Key off */
qsound_channel[ch].key=0;
}
else if (qsound_channel[ch].key==0)
{
/* Key on */
qsound_channel[ch].key=1;
#if QSOUND_DRIVER1
qsound_channel[ch].offset=0;
qsound_channel[ch].lastdt=0;
#else
qsound_channel[ch].cursor=qsound_channel[ch].address <<8 ;
qsound_channel[ch].buffer=qsound_sample_rom+
qsound_channel[ch].bank;
#endif
}
qsound_channel[ch].vol=value;
#if QSOUND_DRIVER2
calcula_mix(ch);
#endif
break;
case 7: /* unused */
#ifdef MAME_DEBUG
{
char baf[40];
sprintf(baf,"UNUSED QSOUND REG 7=%04x",value);
usrintf_showmessage(baf);
}
#endif
break;
case 8:
{
#if QSOUND_DRIVER1
int pandata=(value-0x10)&0x3f;
if (pandata > 32)
{
pandata=32;
}
qsound_channel[ch].rvol=qsound_pan_table[pandata];
qsound_channel[ch].lvol=qsound_pan_table[32-pandata];
#endif
qsound_channel[ch].pan = value;
#if QSOUND_DRIVER2
calcula_mix(ch);
#endif
}
break;
case 9:
qsound_channel[ch].reg9=value;
/*
#ifdef MAME_DEBUG
{
char baf[40];
sprintf(baf,"QSOUND REG 9=%04x",value);
usrintf_showmessage(baf);
}
#endif
*/
break;
}
#if LOG_QSOUND
logerror("QSOUND WRITE %02x CH%02d-R%02d =%04x\n", data, ch, reg, value);
#endif
}
#if QSOUND_DRIVER1
/* Driver 1 - based on the Amuse source */
void qsound_update( int num, INT16 **buffer, int length )
{
int i,j;
int rvol, lvol, count;
struct QSOUND_CHANNEL *pC=&qsound_channel[0];
QSOUND_SRC_SAMPLE * pST;
QSOUND_SAMPLE *datap[2];
datap[0] = buffer[0];
datap[1] = buffer[1];
memset( datap[0], 0x00, length * sizeof(QSOUND_SAMPLE) );
memset( datap[1], 0x00, length * sizeof(QSOUND_SAMPLE) );
for (i=0; i<QSOUND_CHANNELS; i++)
{
if (pC->key)
{
QSOUND_SAMPLE *pOutL=datap[0];
QSOUND_SAMPLE *pOutR=datap[1];
pST=qsound_sample_rom+pC->bank;
rvol=(pC->rvol*pC->vol)>>(8*LENGTH_DIV);
lvol=(pC->lvol*pC->vol)>>(8*LENGTH_DIV);
for (j=length-1; j>=0; j--)
{
count=(pC->offset)>>16;
pC->offset &= 0xffff;
if (count)
{
pC->address += count;
if (pC->address >= pC->end)
{
if (!pC->loop)
{
/* Reached the end of a non-looped sample */
pC->key=0;
break;
}
/* Reached the end, restart the loop */
pC->address = (pC->end - pC->loop) & 0xffff;
}
pC->lastdt = pST[pC->address];
}
(*pOutL) += ((pC->lastdt * lvol) >> 6);
(*pOutR) += ((pC->lastdt * rvol) >> 6);
pOutL++;
pOutR++;
pC->offset += pC->pitch;
}
}
pC++;
}
#if LOG_WAVE
fwrite(datap[0], length*sizeof(QSOUND_SAMPLE), 1, fpRawDataL);
fwrite(datap[1], length*sizeof(QSOUND_SAMPLE), 1, fpRawDataR);
#endif
}
#else
/* ----------------------------------------------------------------
QSound Sample Mixer (Slow)
Miguel Angel Horna mahorna@teleline.es
------------------------------------------------------------------ */
void calcula_mix(int channel)
{
int factl,factr;
struct QSOUND_CHANNEL *pC=&qsound_channel[channel];
int vol=pC->vol>>5;
int pan=((pC->pan&0xFF)-0x10)<<3;
pC->mixl=vol;
pC->mixr=vol;
factr=pan;
factl=255-factr;
pC->mixl=(pC->mixl * factl)>>8;
pC->mixr=(pC->mixr * factr)>>8;
#if QSOUND_8BIT_SAMPLES
pC->mixl<<=8;
pC->mixr<<=8;
#endif
}
void qsound_update(int num,void **buffer,int length)
{
int i,j;
QSOUND_SAMPLE *bufL,*bufR, sample;
struct QSOUND_CHANNEL *pC=qsound_channel;
memset( buffer[0], 0x00, length * sizeof(QSOUND_SAMPLE) );
memset( buffer[1], 0x00, length * sizeof(QSOUND_SAMPLE) );
for(j=0;j<QSOUND_CHANNELS;++j)
{
bufL=(QSOUND_SAMPLE *) buffer[0];
bufR=(QSOUND_SAMPLE *) buffer[1];
if(pC->key)
{
for(i=0;i<length;++i)
{
int pos=pC->cursor>>8;
if(pos!=pC->lpos) /*next sample*/
{
sample=pC->buffer[pos];
pC->lastsaml=(sample*pC->mixl)>>8;
pC->lastsamr=(sample*pC->mixr)>>8;
pC->lpos=pos;
}
(*bufL++)+=pC->lastsaml;
(*bufR++)+=pC->lastsamr;
pC->cursor+=pC->factor;
if(pC->loop && (pC->cursor>>8) > pC->end)
{
pC->cursor=(pC->end-pC->loop)<<8;
}
else if((pC->cursor>>8) > pC->end)
pC->key=0;
}
}
pC++;
}
}
#endif
/**************** end of file ****************/

View file

@ -1,27 +0,0 @@
/*********************************************************
Capcom Q-Sound system
*********************************************************/
#ifndef __QSOUND_H__
#define __QSOUND_H__
#define QSOUND_CLOCK 4000000 /* default 4MHz clock */
struct QSound_interface
{
int clock; /* clock */
char *sample_rom; /* sample data */
};
int qsound_sh_start( struct QSound_interface *qsintf );
void qsound_sh_stop( void );
void qsound_data_h_w(int data);
void qsound_data_l_w(int data);
void qsound_cmd_w(int data);
int qsound_status_r(void);
void qsound_update( int num, INT16 **buffer, int length );
#endif /* __QSOUND_H__ */

File diff suppressed because it is too large Load diff

View file

@ -1,46 +0,0 @@
#ifndef Z80_H
#define Z80_H
#include "cpuintrf.h"
#include "osd_cpu.h"
enum {
Z80_PC=1, Z80_SP, Z80_AF, Z80_BC, Z80_DE, Z80_HL,
Z80_IX, Z80_IY, Z80_AF2, Z80_BC2, Z80_DE2, Z80_HL2,
Z80_R, Z80_I, Z80_IM, Z80_IFF1, Z80_IFF2, Z80_HALT,
Z80_NMI_STATE, Z80_IRQ_STATE, Z80_DC0, Z80_DC1, Z80_DC2, Z80_DC3
};
enum {
Z80_TABLE_op,
Z80_TABLE_cb,
Z80_TABLE_ed,
Z80_TABLE_xy,
Z80_TABLE_xycb,
Z80_TABLE_ex /* cycles counts for taken jr/jp/call and interrupt latency (rst opcodes) */
};
extern int z80_ICount; /* T-state count */
extern void z80_init(void);
extern void z80_reset (void *param);
extern void z80_exit (void);
extern int z80_execute(int cycles);
extern void z80_burn(int cycles);
extern unsigned z80_get_context (void *dst);
extern void z80_set_context (void *src);
extern const void *z80_get_cycle_table (int which);
extern void z80_set_cycle_table (int which, void *new_tbl);
extern unsigned z80_get_reg (int regnum);
extern void z80_set_reg (int regnum, unsigned val);
extern void z80_set_irq_line(int irqline, int state);
extern void z80_set_irq_callback(int (*irq_callback)(int));
extern const char *z80_info(void *context, int regnum);
extern unsigned z80_dasm(char *buffer, unsigned pc);
#ifdef MAME_DEBUG
extern unsigned DasmZ80(char *buffer, unsigned pc);
#endif
#endif

View file

@ -1,597 +0,0 @@
/*****************************************************************************
*
* z80dasm.c
* Portable Z80 disassembler
*
* Copyright (C) 1998 Juergen Buchmueller, all rights reserved.
*
* - This source code is released as freeware for non-commercial purposes.
* - You are free to use and redistribute this code in modified or
* unmodified form, provided you list me in the credits.
* - If you modify this source code, you must add a notice to each modified
* source file that it has been changed. If you're a nice person, you
* will clearly mark each change too. :)
* - If you wish to use this for commercial purposes, please contact me at
* pullmoll@t-online.de
* - The author of this copywritten work reserves the right to change the
* terms of its usage and license at any time, including retroactively
* - This entire notice must remain in the source code.
*
*****************************************************************************/
#include <stdio.h>
#include <string.h>
#ifdef MAME_DEBUG
#include "driver.h"
#include "mamedbg.h"
#include "z80.h"
enum e_mnemonics {
zADC ,zADD ,zAND ,zBIT ,zCALL ,zCCF ,zCP ,zCPD ,
zCPDR ,zCPI ,zCPIR ,zCPL ,zDAA ,zDB ,zDEC ,zDI ,
zDJNZ ,zEI ,zEX ,zEXX ,zHLT ,zIM ,zIN ,zINC ,
zIND ,zINDR ,zINI ,zINIR ,zJP ,zJR ,zLD ,zLDD ,
zLDDR ,zLDI ,zLDIR ,zNEG ,zNOP ,zOR ,zOTDR ,zOTIR ,
zOUT ,zOUTD ,zOUTI ,zPOP ,zPUSH ,zRES ,zRET ,zRETI ,
zRETN ,zRL ,zRLA ,zRLC ,zRLCA ,zRLD ,zRR ,zRRA ,
zRRC ,zRRCA ,zRRD ,zRST ,zSBC ,zSCF ,zSET ,zSLA ,
zSLL ,zSRA ,zSRL ,zSUB ,zXOR
};
static const char *s_mnemonic[] = {
"adc", "add", "and", "bit", "call","ccf", "cp", "cpd",
"cpdr","cpi", "cpir","cpl", "daa", "db", "dec", "di",
"djnz","ei", "ex", "exx", "halt","im", "in", "inc",
"ind", "indr","ini", "inir","jp", "jr", "ld", "ldd",
"lddr","ldi", "ldir","neg", "nop", "or", "otdr","otir",
"out", "outd","outi","pop", "push","res", "ret", "reti",
"retn","rl", "rla", "rlc", "rlca","rld", "rr", "rra",
"rrc", "rrca","rrd", "rst", "sbc", "scf", "set", "sla",
"sll", "sra", "srl", "sub", "xor "
};
typedef struct {
UINT8 access;
UINT8 mnemonic;
const char *arguments;
} z80dasm;
#define _0 EA_NONE
#define _JP EA_ABS_PC
#define _JR EA_REL_PC
#define _RM EA_MEM_RD
#define _WM EA_MEM_WR
#define _RW EA_MEM_RDWR
#define _RP EA_PORT_RD
#define _WP EA_PORT_WR
static z80dasm mnemonic_xx_cb[256]= {
{_RW,zRLC,"b=Y"}, {_RW,zRLC,"c=Y"}, {_RW,zRLC,"d=Y"}, {_RW,zRLC,"e=Y"},
{_RW,zRLC,"h=Y"}, {_RW,zRLC,"l=Y"}, {_RW,zRLC,"Y"}, {_RW,zRLC,"a=Y"},
{_RW,zRRC,"b=Y"}, {_RW,zRRC,"c=Y"}, {_RW,zRRC,"d=Y"}, {_RW,zRRC,"e=Y"},
{_RW,zRRC,"h=Y"}, {_RW,zRRC,"l=Y"}, {_RW,zRRC,"Y"}, {_RW,zRRC,"a=Y"},
{_RW,zRL,"b=Y"}, {_RW,zRL,"c=Y"}, {_RW,zRL,"d=Y"}, {_RW,zRL,"e=Y"},
{_RW,zRL,"h=Y"}, {_RW,zRL,"l=Y"}, {_RW,zRL,"Y"}, {_RW,zRL,"a=Y"},
{_RW,zRR,"b=Y"}, {_RW,zRR,"c=Y"}, {_RW,zRR,"d=Y"}, {_RW,zRR,"e=Y"},
{_RW,zRR,"h=Y"}, {_RW,zRR,"l=Y"}, {_RW,zRR,"Y"}, {_RW,zRR,"a=Y"},
{_RW,zSLA,"b=Y"}, {_RW,zSLA,"c=Y"}, {_RW,zSLA,"d=Y"}, {_RW,zSLA,"e=Y"},
{_RW,zSLA,"h=Y"}, {_RW,zSLA,"l=Y"}, {_RW,zSLA,"Y"}, {_RW,zSLA,"a=Y"},
{_RW,zSRA,"b=Y"}, {_RW,zSRA,"c=Y"}, {_RW,zSRA,"d=Y"}, {_RW,zSRA,"e=Y"},
{_RW,zSRA,"h=Y"}, {_RW,zSRA,"l=Y"}, {_RW,zSRA,"Y"}, {_RW,zSRA,"a=Y"},
{_RW,zSLL,"b=Y"}, {_RW,zSLL,"c=Y"}, {_RW,zSLL,"d=Y"}, {_RW,zSLL,"e=Y"},
{_RW,zSLL,"h=Y"}, {_RW,zSLL,"l=Y"}, {_RW,zSLL,"Y"}, {_RW,zSLL,"a=Y"},
{_RW,zSRL,"b=Y"}, {_RW,zSRL,"c=Y"}, {_RW,zSRL,"d=Y"}, {_RW,zSRL,"e=Y"},
{_RW,zSRL,"h=Y"}, {_RW,zSRL,"l=Y"}, {_RW,zSRL,"Y"}, {_RW,zSRL,"a=Y"},
{_RM,zBIT,"b=0,Y"}, {_RM,zBIT,"c=0,Y"}, {_RM,zBIT,"d=0,Y"}, {_RM,zBIT,"e=0,Y"},
{_RM,zBIT,"h=0,Y"}, {_RM,zBIT,"l=0,Y"}, {_RM,zBIT,"0,Y"}, {_RM,zBIT,"a=0,Y"},
{_RM,zBIT,"b=1,Y"}, {_RM,zBIT,"c=1,Y"}, {_RM,zBIT,"d=1,Y"}, {_RM,zBIT,"e=1,Y"},
{_RM,zBIT,"h=1,Y"}, {_RM,zBIT,"l=1,Y"}, {_RM,zBIT,"1,Y"}, {_RM,zBIT,"a=1,Y"},
{_RM,zBIT,"b=2,Y"}, {_RM,zBIT,"c=2,Y"}, {_RM,zBIT,"d=2,Y"}, {_RM,zBIT,"e=2,Y"},
{_RM,zBIT,"h=2,Y"}, {_RM,zBIT,"l=2,Y"}, {_RM,zBIT,"2,Y"}, {_RM,zBIT,"a=2,Y"},
{_RM,zBIT,"b=3,Y"}, {_RM,zBIT,"c=3,Y"}, {_RM,zBIT,"d=3,Y"}, {_RM,zBIT,"e=3,Y"},
{_RM,zBIT,"h=3,Y"}, {_RM,zBIT,"l=3,Y"}, {_RM,zBIT,"3,Y"}, {_RM,zBIT,"a=3,Y"},
{_RM,zBIT,"b=4,Y"}, {_RM,zBIT,"c=4,Y"}, {_RM,zBIT,"d=4,Y"}, {_RM,zBIT,"e=4,Y"},
{_RM,zBIT,"h=4,Y"}, {_RM,zBIT,"l=4,Y"}, {_RM,zBIT,"4,Y"}, {_RM,zBIT,"a=4,Y"},
{_RM,zBIT,"b=5,Y"}, {_RM,zBIT,"c=5,Y"}, {_RM,zBIT,"d=5,Y"}, {_RM,zBIT,"e=5,Y"},
{_RM,zBIT,"h=5,Y"}, {_RM,zBIT,"l=5,Y"}, {_RM,zBIT,"5,Y"}, {_RM,zBIT,"a=5,Y"},
{_RM,zBIT,"b=6,Y"}, {_RM,zBIT,"c=6,Y"}, {_RM,zBIT,"d=6,Y"}, {_RM,zBIT,"e=6,Y"},
{_RM,zBIT,"h=6,Y"}, {_RM,zBIT,"l=6,Y"}, {_RM,zBIT,"6,Y"}, {_RM,zBIT,"a=6,Y"},
{_RM,zBIT,"b=7,Y"}, {_RM,zBIT,"c=7,Y"}, {_RM,zBIT,"d=7,Y"}, {_RM,zBIT,"e=7,Y"},
{_RM,zBIT,"h=7,Y"}, {_RM,zBIT,"l=7,Y"}, {_RM,zBIT,"7,Y"}, {_RM,zBIT,"a=7,Y"},
{_WM,zRES,"b=0,Y"}, {_WM,zRES,"c=0,Y"}, {_WM,zRES,"d=0,Y"}, {_WM,zRES,"e=0,Y"},
{_WM,zRES,"h=0,Y"}, {_WM,zRES,"l=0,Y"}, {_WM,zRES,"0,Y"}, {_WM,zRES,"a=0,Y"},
{_WM,zRES,"b=1,Y"}, {_WM,zRES,"c=1,Y"}, {_WM,zRES,"d=1,Y"}, {_WM,zRES,"e=1,Y"},
{_WM,zRES,"h=1,Y"}, {_WM,zRES,"l=1,Y"}, {_WM,zRES,"1,Y"}, {_WM,zRES,"a=1,Y"},
{_WM,zRES,"b=2,Y"}, {_WM,zRES,"c=2,Y"}, {_WM,zRES,"d=2,Y"}, {_WM,zRES,"e=2,Y"},
{_WM,zRES,"h=2,Y"}, {_WM,zRES,"l=2,Y"}, {_WM,zRES,"2,Y"}, {_WM,zRES,"a=2,Y"},
{_WM,zRES,"b=3,Y"}, {_WM,zRES,"c=3,Y"}, {_WM,zRES,"d=3,Y"}, {_WM,zRES,"e=3,Y"},
{_WM,zRES,"h=3,Y"}, {_WM,zRES,"l=3,Y"}, {_WM,zRES,"3,Y"}, {_WM,zRES,"a=3,Y"},
{_WM,zRES,"b=4,Y"}, {_WM,zRES,"c=4,Y"}, {_WM,zRES,"d=4,Y"}, {_WM,zRES,"e=4,Y"},
{_WM,zRES,"h=4,Y"}, {_WM,zRES,"l=4,Y"}, {_WM,zRES,"4,Y"}, {_WM,zRES,"a=4,Y"},
{_WM,zRES,"b=5,Y"}, {_WM,zRES,"c=5,Y"}, {_WM,zRES,"d=5,Y"}, {_WM,zRES,"e=5,Y"},
{_WM,zRES,"h=5,Y"}, {_WM,zRES,"l=5,Y"}, {_WM,zRES,"5,Y"}, {_WM,zRES,"a=5,Y"},
{_WM,zRES,"b=6,Y"}, {_WM,zRES,"c=6,Y"}, {_WM,zRES,"d=6,Y"}, {_WM,zRES,"e=6,Y"},
{_WM,zRES,"h=6,Y"}, {_WM,zRES,"l=6,Y"}, {_WM,zRES,"6,Y"}, {_WM,zRES,"a=6,Y"},
{_WM,zRES,"b=7,Y"}, {_WM,zRES,"c=7,Y"}, {_WM,zRES,"d=7,Y"}, {_WM,zRES,"e=7,Y"},
{_WM,zRES,"h=7,Y"}, {_WM,zRES,"l=7,Y"}, {_WM,zRES,"7,Y"}, {_WM,zRES,"a=7,Y"},
{_WM,zSET,"b=0,Y"}, {_WM,zSET,"c=0,Y"}, {_WM,zSET,"d=0,Y"}, {_WM,zSET,"e=0,Y"},
{_WM,zSET,"h=0,Y"}, {_WM,zSET,"l=0,Y"}, {_WM,zSET,"0,Y"}, {_WM,zSET,"a=0,Y"},
{_WM,zSET,"b=1,Y"}, {_WM,zSET,"c=1,Y"}, {_WM,zSET,"d=1,Y"}, {_WM,zSET,"e=1,Y"},
{_WM,zSET,"h=1,Y"}, {_WM,zSET,"l=1,Y"}, {_WM,zSET,"1,Y"}, {_WM,zSET,"a=1,Y"},
{_WM,zSET,"b=2,Y"}, {_WM,zSET,"c=2,Y"}, {_WM,zSET,"d=2,Y"}, {_WM,zSET,"e=2,Y"},
{_WM,zSET,"h=2,Y"}, {_WM,zSET,"l=2,Y"}, {_WM,zSET,"2,Y"}, {_WM,zSET,"a=2,Y"},
{_WM,zSET,"b=3,Y"}, {_WM,zSET,"c=3,Y"}, {_WM,zSET,"d=3,Y"}, {_WM,zSET,"e=3,Y"},
{_WM,zSET,"h=3,Y"}, {_WM,zSET,"l=3,Y"}, {_WM,zSET,"3,Y"}, {_WM,zSET,"a=3,Y"},
{_WM,zSET,"b=4,Y"}, {_WM,zSET,"c=4,Y"}, {_WM,zSET,"d=4,Y"}, {_WM,zSET,"e=4,Y"},
{_WM,zSET,"h=4,Y"}, {_WM,zSET,"l=4,Y"}, {_WM,zSET,"4,Y"}, {_WM,zSET,"a=4,Y"},
{_WM,zSET,"b=5,Y"}, {_WM,zSET,"c=5,Y"}, {_WM,zSET,"d=5,Y"}, {_WM,zSET,"e=5,Y"},
{_WM,zSET,"h=5,Y"}, {_WM,zSET,"l=5,Y"}, {_WM,zSET,"5,Y"}, {_WM,zSET,"a=5,Y"},
{_WM,zSET,"b=6,Y"}, {_WM,zSET,"c=6,Y"}, {_WM,zSET,"d=6,Y"}, {_WM,zSET,"e=6,Y"},
{_WM,zSET,"h=6,Y"}, {_WM,zSET,"l=6,Y"}, {_WM,zSET,"6,Y"}, {_WM,zSET,"a=6,Y"},
{_WM,zSET,"b=7,Y"}, {_WM,zSET,"c=7,Y"}, {_WM,zSET,"d=7,Y"}, {_WM,zSET,"e=7,Y"},
{_WM,zSET,"h=7,Y"}, {_WM,zSET,"l=7,Y"}, {_WM,zSET,"7,Y"}, {_WM,zSET,"a=7,Y"}
};
static z80dasm mnemonic_cb[256] = {
{_0, zRLC,"b"}, {_0, zRLC,"c"}, {_0, zRLC,"d"}, {_0, zRLC,"e"},
{_0, zRLC,"h"}, {_0, zRLC,"l"}, {_RW,zRLC,"(hl)"}, {_0, zRLC,"a"},
{_0, zRRC,"b"}, {_0, zRRC,"c"}, {_0, zRRC,"d"}, {_0, zRRC,"e"},
{_0, zRRC,"h"}, {_0, zRRC,"l"}, {_RW,zRRC,"(hl)"}, {_0, zRRC,"a"},
{_0, zRL,"b"}, {_0, zRL,"c"}, {_0, zRL,"d"}, {_0, zRL,"e"},
{_0, zRL,"h"}, {_0, zRL,"l"}, {_RW,zRL,"(hl)"}, {_0, zRL,"a"},
{_0, zRR,"b"}, {_0, zRR,"c"}, {_0, zRR,"d"}, {_0, zRR,"e"},
{_0, zRR,"h"}, {_0, zRR,"l"}, {_RW,zRR,"(hl)"}, {_0, zRR,"a"},
{_0, zSLA,"b"}, {_0, zSLA,"c"}, {_0, zSLA,"d"}, {_0, zSLA,"e"},
{_0, zSLA,"h"}, {_0, zSLA,"l"}, {_RW,zSLA,"(hl)"}, {_0, zSLA,"a"},
{_0, zSRA,"b"}, {_0, zSRA,"c"}, {_0, zSRA,"d"}, {_0, zSRA,"e"},
{_0, zSRA,"h"}, {_0, zSRA,"l"}, {_RW,zSRA,"(hl)"}, {_0, zSRA,"a"},
{_0, zSLL,"b"}, {_0, zSLL,"c"}, {_0, zSLL,"d"}, {_0, zSLL,"e"},
{_0, zSLL,"h"}, {_0, zSLL,"l"}, {_RW,zSLL,"(hl)"}, {_0, zSLL,"a"},
{_0, zSRL,"b"}, {_0, zSRL,"c"}, {_0, zSRL,"d"}, {_0, zSRL,"e"},
{_0, zSRL,"h"}, {_0, zSRL,"l"}, {_RW,zSRL,"(hl)"}, {_0, zSRL,"a"},
{_0, zBIT,"0,b"}, {_0, zBIT,"0,c"}, {_0, zBIT,"0,d"}, {_0, zBIT,"0,e"},
{_0, zBIT,"0,h"}, {_0, zBIT,"0,l"}, {_RM,zBIT,"0,(hl)"},{_0, zBIT,"0,a"},
{_0, zBIT,"1,b"}, {_0, zBIT,"1,c"}, {_0, zBIT,"1,d"}, {_0, zBIT,"1,e"},
{_0, zBIT,"1,h"}, {_0, zBIT,"1,l"}, {_RM,zBIT,"1,(hl)"},{_0, zBIT,"1,a"},
{_0, zBIT,"2,b"}, {_0, zBIT,"2,c"}, {_0, zBIT,"2,d"}, {_0, zBIT,"2,e"},
{_0, zBIT,"2,h"}, {_0, zBIT,"2,l"}, {_RM,zBIT,"2,(hl)"},{_0, zBIT,"2,a"},
{_0, zBIT,"3,b"}, {_0, zBIT,"3,c"}, {_0, zBIT,"3,d"}, {_0, zBIT,"3,e"},
{_0, zBIT,"3,h"}, {_0, zBIT,"3,l"}, {_RM,zBIT,"3,(hl)"},{_0, zBIT,"3,a"},
{_0, zBIT,"4,b"}, {_0, zBIT,"4,c"}, {_0, zBIT,"4,d"}, {_0, zBIT,"4,e"},
{_0, zBIT,"4,h"}, {_0, zBIT,"4,l"}, {_RM,zBIT,"4,(hl)"},{_0, zBIT,"4,a"},
{_0, zBIT,"5,b"}, {_0, zBIT,"5,c"}, {_0, zBIT,"5,d"}, {_0, zBIT,"5,e"},
{_0, zBIT,"5,h"}, {_0, zBIT,"5,l"}, {_RM,zBIT,"5,(hl)"},{_0, zBIT,"5,a"},
{_0, zBIT,"6,b"}, {_0, zBIT,"6,c"}, {_0, zBIT,"6,d"}, {_0, zBIT,"6,e"},
{_0, zBIT,"6,h"}, {_0, zBIT,"6,l"}, {_RM,zBIT,"6,(hl)"},{_0, zBIT,"6,a"},
{_0, zBIT,"7,b"}, {_0, zBIT,"7,c"}, {_0, zBIT,"7,d"}, {_0, zBIT,"7,e"},
{_0, zBIT,"7,h"}, {_0, zBIT,"7,l"}, {_RM,zBIT,"7,(hl)"},{_0, zBIT,"7,a"},
{_0, zRES,"0,b"}, {_0, zRES,"0,c"}, {_0, zRES,"0,d"}, {_0, zRES,"0,e"},
{_0, zRES,"0,h"}, {_0, zRES,"0,l"}, {_WM,zRES,"0,(hl)"},{_0, zRES,"0,a"},
{_0, zRES,"1,b"}, {_0, zRES,"1,c"}, {_0, zRES,"1,d"}, {_0, zRES,"1,e"},
{_0, zRES,"1,h"}, {_0, zRES,"1,l"}, {_WM,zRES,"1,(hl)"},{_0, zRES,"1,a"},
{_0, zRES,"2,b"}, {_0, zRES,"2,c"}, {_0, zRES,"2,d"}, {_0, zRES,"2,e"},
{_0, zRES,"2,h"}, {_0, zRES,"2,l"}, {_WM,zRES,"2,(hl)"},{_0, zRES,"2,a"},
{_0, zRES,"3,b"}, {_0, zRES,"3,c"}, {_0, zRES,"3,d"}, {_0, zRES,"3,e"},
{_0, zRES,"3,h"}, {_0, zRES,"3,l"}, {_WM,zRES,"3,(hl)"},{_0, zRES,"3,a"},
{_0, zRES,"4,b"}, {_0, zRES,"4,c"}, {_0, zRES,"4,d"}, {_0, zRES,"4,e"},
{_0, zRES,"4,h"}, {_0, zRES,"4,l"}, {_WM,zRES,"4,(hl)"},{_0, zRES,"4,a"},
{_0, zRES,"5,b"}, {_0, zRES,"5,c"}, {_0, zRES,"5,d"}, {_0, zRES,"5,e"},
{_0, zRES,"5,h"}, {_0, zRES,"5,l"}, {_WM,zRES,"5,(hl)"},{_0, zRES,"5,a"},
{_0, zRES,"6,b"}, {_0, zRES,"6,c"}, {_0, zRES,"6,d"}, {_0, zRES,"6,e"},
{_0, zRES,"6,h"}, {_0, zRES,"6,l"}, {_WM,zRES,"6,(hl)"},{_0, zRES,"6,a"},
{_0, zRES,"7,b"}, {_0, zRES,"7,c"}, {_0, zRES,"7,d"}, {_0, zRES,"7,e"},
{_0, zRES,"7,h"}, {_0, zRES,"7,l"}, {_WM,zRES,"7,(hl)"},{_0, zRES,"7,a"},
{_0, zSET,"0,b"}, {_0, zSET,"0,c"}, {_0, zSET,"0,d"}, {_0, zSET,"0,e"},
{_0, zSET,"0,h"}, {_0, zSET,"0,l"}, {_WM,zSET,"0,(hl)"},{_0, zSET,"0,a"},
{_0, zSET,"1,b"}, {_0, zSET,"1,c"}, {_0, zSET,"1,d"}, {_0, zSET,"1,e"},
{_0, zSET,"1,h"}, {_0, zSET,"1,l"}, {_WM,zSET,"1,(hl)"},{_0, zSET,"1,a"},
{_0, zSET,"2,b"}, {_0, zSET,"2,c"}, {_0, zSET,"2,d"}, {_0, zSET,"2,e"},
{_0, zSET,"2,h"}, {_0, zSET,"2,l"}, {_WM,zSET,"2,(hl)"},{_0, zSET,"2,a"},
{_0, zSET,"3,b"}, {_0, zSET,"3,c"}, {_0, zSET,"3,d"}, {_0, zSET,"3,e"},
{_0, zSET,"3,h"}, {_0, zSET,"3,l"}, {_WM,zSET,"3,(hl)"},{_0, zSET,"3,a"},
{_0, zSET,"4,b"}, {_0, zSET,"4,c"}, {_0, zSET,"4,d"}, {_0, zSET,"4,e"},
{_0, zSET,"4,h"}, {_0, zSET,"4,l"}, {_WM,zSET,"4,(hl)"},{_0, zSET,"4,a"},
{_0, zSET,"5,b"}, {_0, zSET,"5,c"}, {_0, zSET,"5,d"}, {_0, zSET,"5,e"},
{_0, zSET,"5,h"}, {_0, zSET,"5,l"}, {_WM,zSET,"5,(hl)"},{_0, zSET,"5,a"},
{_0, zSET,"6,b"}, {_0, zSET,"6,c"}, {_0, zSET,"6,d"}, {_0, zSET,"6,e"},
{_0, zSET,"6,h"}, {_0, zSET,"6,l"}, {_WM,zSET,"6,(hl)"},{_0, zSET,"6,a"},
{_0, zSET,"7,b"}, {_0, zSET,"7,c"}, {_0, zSET,"7,d"}, {_0, zSET,"7,e"},
{_0, zSET,"7,h"}, {_0, zSET,"7,l"}, {_WM,zSET,"7,(hl)"},{_0, zSET,"7,a"}
};
static z80dasm mnemonic_ed[256]= {
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_RP,zIN,"b,(c)"}, {_WP,zOUT,"(c),b"}, {_0, zSBC,"hl,bc"}, {_WM,zLD,"(W),bc"},
{_0, zNEG,0}, {_0, zRETN,0}, {_0, zIM,"0"}, {_0, zLD,"i,a"},
{_RP,zIN,"c,(c)"}, {_WP,zOUT,"(c),c"}, {_0, zADC,"hl,bc"}, {_RM,zLD,"bc,(W)"},
{_0, zNEG,"*"}, {_0, zRETI,0}, {_0, zIM,"0"}, {_0, zLD,"r,a"},
{_RP,zIN,"d,(c)"}, {_WP,zOUT,"(c),d"}, {_0, zSBC,"hl,de"}, {_WM,zLD,"(W),de"},
{_0, zNEG,"*"}, {_0, zRETN,0}, {_0, zIM,"1"}, {_0, zLD,"a,i"},
{_RP,zIN,"e,(c)"}, {_WP,zOUT,"(c),e"}, {_0, zADC,"hl,de"}, {_RM,zLD,"de,(W)"},
{_0, zNEG,"*"}, {_0, zRETI,0}, {_0, zIM,"2"}, {_0, zLD,"a,r"},
{_RP,zIN,"h,(c)"}, {_WP,zOUT,"(c),h"}, {_0, zSBC,"hl,hl"}, {_WM,zLD,"(W),hl"},
{_0, zNEG,"*"}, {_0, zRETN,0}, {_0, zIM,"0"}, {_RW,zRRD,"(hl)"},
{_RP,zIN,"l,(c)"}, {_WP,zOUT,"(c),l"}, {_0, zADC,"hl,hl"}, {_RM,zLD,"hl,(W)"},
{_0, zNEG,"*"}, {_0, zRETI,0}, {_0, zIM,"0"}, {_RW,zRLD,"(hl)"},
{_RP,zIN,"0,(c)"}, {_WP,zOUT,"(c),0"}, {_0, zSBC,"hl,sp"}, {_WM,zLD,"(W),sp"},
{_0, zNEG,"*"}, {_0, zRETN,0}, {_0, zIM,"1"}, {_0, zDB,"?"},
{_RP,zIN,"a,(c)"}, {_WP,zOUT,"(c),a"}, {_0, zADC,"hl,sp"}, {_RM,zLD,"sp,(W)"},
{_0, zNEG,"*"}, {_0, zRETI,0}, {_0, zIM,"2"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_RW,zLDI,0}, {_RM,zCPI,0}, {_RP,zINI,0}, {_WP,zOUTI,0},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_RW,zLDD,0}, {_RM,zCPD,0}, {_RP,zIND,0}, {_WP,zOUTD,0},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_RW,zLDIR,0}, {_RM,zCPIR,0}, {_RP,zINIR,0}, {_WP,zOTIR,0},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_RW,zLDDR,0}, {_RM,zCPDR,0}, {_RP,zINDR,0}, {_WP,zOTDR,0},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}
};
static z80dasm mnemonic_xx[256]= {
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zADD,"I,bc"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zADD,"I,de"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zLD,"I,N"}, {_WM,zLD,"(W),I"}, {_0, zINC,"I"},
{_0, zINC,"Ih"}, {_0, zDEC,"Ih"}, {_0, zLD,"Ih,B"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zADD,"I,I"}, {_RM,zLD,"I,(W)"}, {_0, zDEC,"I"},
{_0, zINC,"Il"}, {_0, zDEC,"Il"}, {_0, zLD,"Il,B"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_RW,zINC,"X"}, {_RW,zDEC,"X"}, {_WM,zLD,"X,B"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zADD,"I,sp"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zLD,"b,Ih"}, {_0, zLD,"b,Il"}, {_RM,zLD,"b,X"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zLD,"c,Ih"}, {_0, zLD,"c,Il"}, {_RM,zLD,"c,X"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zLD,"d,Ih"}, {_0, zLD,"d,Il"}, {_RM,zLD,"d,X"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zLD,"e,Ih"}, {_0, zLD,"e,Il"}, {_RM,zLD,"e,X"}, {_0, zDB,"?"},
{_0, zLD,"Ih,b"}, {_0, zLD,"Ih,c"}, {_0, zLD,"Ih,d"}, {_0, zLD,"Ih,e"},
{_0, zLD,"Ih,Ih"}, {_0, zLD,"Ih,Il"}, {_RM,zLD,"h,X"}, {_0, zLD,"Ih,a"},
{_0, zLD,"Il,b"}, {_0, zLD,"Il,c"}, {_0, zLD,"Il,d"}, {_0, zLD,"Il,e"},
{_0, zLD,"Il,Ih"}, {_0, zLD,"Il,Il"}, {_RM,zLD,"l,X"}, {_0, zLD,"Il,a"},
{_WM,zLD,"X,b"}, {_WM,zLD,"X,c"}, {_WM,zLD,"X,d"}, {_WM,zLD,"X,e"},
{_WM,zLD,"X,h"}, {_WM,zLD,"X,l"}, {_0, zDB,"?"}, {_WM,zLD,"X,a"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zLD,"a,Ih"}, {_0, zLD,"a,Il"}, {_RM,zLD,"a,X"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zADD,"a,Ih"}, {_0, zADD,"a,Il"}, {_RM,zADD,"a,X"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zADC,"a,Ih"}, {_0, zADC,"a,Il"}, {_RM,zADC,"a,X"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zSUB,"Ih"}, {_0, zSUB,"Il"}, {_RM,zSUB,"X"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zSBC,"a,Ih"}, {_0, zSBC,"a,Il"}, {_RM,zSBC,"a,X"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zAND,"Ih"}, {_0, zAND,"Il"}, {_RM,zAND,"X"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zXOR,"Ih"}, {_0, zXOR,"Il"}, {_RM,zXOR,"X"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zOR,"Ih"}, {_0, zOR,"Il"}, {_RM,zOR,"X"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zCP,"Ih"}, {_0, zCP,"Il"}, {_RM,zCP,"X"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"cb"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zPOP,"I"}, {_0, zDB,"?"}, {_RW,zEX,"(sp),I"},
{_0, zDB,"?"}, {_0, zPUSH,"I"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_JP,zJP,"(I)"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zLD,"sp,I"}, {_0, zDB,"?"}, {_0, zDB,"?"},
{_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}, {_0, zDB,"?"}
};
static z80dasm mnemonic_main[256]= {
{_0, zNOP,0}, {_0, zLD,"bc,N"}, {_WM,zLD,"(bc),a"}, {_0, zINC,"bc"},
{_0, zINC,"b"}, {_0, zDEC,"b"}, {_0, zLD,"b,B"}, {_0, zRLCA,0},
{_0, zEX,"af,af'"}, {_0, zADD,"hl,bc"}, {_RM,zLD,"a,(bc)"}, {_0, zDEC,"bc"},
{_0, zINC,"c"}, {_0, zDEC,"c"}, {_0, zLD,"c,B"}, {_0, zRRCA,0},
{_JR,zDJNZ,"O"}, {_0, zLD,"de,N"}, {_WM,zLD,"(de),a"}, {_0, zINC,"de"},
{_0, zINC,"d"}, {_0, zDEC,"d"}, {_0, zLD,"d,B"}, {_0, zRLA,0},
{_JR,zJR,"O"}, {_0, zADD,"hl,de"}, {_RM,zLD,"a,(de)"}, {_0, zDEC,"de"},
{_0, zINC,"e"}, {_0, zDEC,"e"}, {_0, zLD,"e,B"}, {_0, zRRA,0},
{_JR,zJR,"nz,O"}, {_0, zLD,"hl,N"}, {_WM,zLD,"(W),hl"}, {_0, zINC,"hl"},
{_0, zINC,"h"}, {_0, zDEC,"h"}, {_0, zLD,"h,B"}, {_0, zDAA,0},
{_JR,zJR,"z,O"}, {_0, zADD,"hl,hl"}, {_RM,zLD,"hl,(W)"}, {_0, zDEC,"hl"},
{_0, zINC,"l"}, {_0, zDEC,"l"}, {_0, zLD,"l,B"}, {_0, zCPL,0},
{_JR,zJR,"nc,O"}, {_0, zLD,"sp,N"}, {_WM,zLD,"(W),a"}, {_0, zINC,"sp"},
{_RW,zINC,"(hl)"}, {_RW,zDEC,"(hl)"}, {_WM,zLD,"(hl),B"}, {_0, zSCF,0},
{_JR,zJR,"c,O"}, {_0, zADD,"hl,sp"}, {_RM,zLD,"a,(W)"}, {_0, zDEC,"sp"},
{_0, zINC,"a"}, {_0, zDEC,"a"}, {_0, zLD,"a,B"}, {_0, zCCF,0},
{_0, zLD,"b,b"}, {_0, zLD,"b,c"}, {_0, zLD,"b,d"}, {_0, zLD,"b,e"},
{_0, zLD,"b,h"}, {_0, zLD,"b,l"}, {_RM,zLD,"b,(hl)"}, {_0, zLD,"b,a"},
{_0, zLD,"c,b"}, {_0, zLD,"c,c"}, {_0, zLD,"c,d"}, {_0, zLD,"c,e"},
{_0, zLD,"c,h"}, {_0, zLD,"c,l"}, {_RM,zLD,"c,(hl)"}, {_0, zLD,"c,a"},
{_0, zLD,"d,b"}, {_0, zLD,"d,c"}, {_0, zLD,"d,d"}, {_0, zLD,"d,e"},
{_0, zLD,"d,h"}, {_0, zLD,"d,l"}, {_RM,zLD,"d,(hl)"}, {_0, zLD,"d,a"},
{_0, zLD,"e,b"}, {_0, zLD,"e,c"}, {_0, zLD,"e,d"}, {_0, zLD,"e,e"},
{_0, zLD,"e,h"}, {_0, zLD,"e,l"}, {_RM,zLD,"e,(hl)"}, {_0, zLD,"e,a"},
{_0, zLD,"h,b"}, {_0, zLD,"h,c"}, {_0, zLD,"h,d"}, {_0, zLD,"h,e"},
{_0, zLD,"h,h"}, {_0, zLD,"h,l"}, {_RM,zLD,"h,(hl)"}, {_0, zLD,"h,a"},
{_0, zLD,"l,b"}, {_0, zLD,"l,c"}, {_0, zLD,"l,d"}, {_0, zLD,"l,e"},
{_0, zLD,"l,h"}, {_0, zLD,"l,l"}, {_RM,zLD,"l,(hl)"}, {_0, zLD,"l,a"},
{_WM,zLD,"(hl),b"}, {_WM,zLD,"(hl),c"}, {_WM,zLD,"(hl),d"}, {_WM,zLD,"(hl),e"},
{_WM,zLD,"(hl),h"}, {_WM,zLD,"(hl),l"}, {_0, zHLT,0}, {_WM,zLD,"(hl),a"},
{_0, zLD,"a,b"}, {_0, zLD,"a,c"}, {_0, zLD,"a,d"}, {_0, zLD,"a,e"},
{_0, zLD,"a,h"}, {_0, zLD,"a,l"}, {_RM,zLD,"a,(hl)"}, {_0, zLD,"a,a"},
{_0, zADD,"a,b"}, {_0, zADD,"a,c"}, {_0, zADD,"a,d"}, {_0, zADD,"a,e"},
{_0, zADD,"a,h"}, {_0, zADD,"a,l"}, {_RM,zADD,"a,(hl)"},{_0, zADD,"a,a"},
{_0, zADC,"a,b"}, {_0, zADC,"a,c"}, {_0, zADC,"a,d"}, {_0, zADC,"a,e"},
{_0, zADC,"a,h"}, {_0, zADC,"a,l"}, {_RM,zADC,"a,(hl)"},{_0, zADC,"a,a"},
{_0, zSUB,"b"}, {_0, zSUB,"c"}, {_0, zSUB,"d"}, {_0, zSUB,"e"},
{_0, zSUB,"h"}, {_0, zSUB,"l"}, {_RM,zSUB,"(hl)"}, {_0, zSUB,"a"},
{_0, zSBC,"a,b"}, {_0, zSBC,"a,c"}, {_0, zSBC,"a,d"}, {_0, zSBC,"a,e"},
{_0, zSBC,"a,h"}, {_0, zSBC,"a,l"}, {_RM,zSBC,"a,(hl)"},{_0, zSBC,"a,a"},
{_0, zAND,"b"}, {_0, zAND,"c"}, {_0, zAND,"d"}, {_0, zAND,"e"},
{_0, zAND,"h"}, {_0, zAND,"l"}, {_RM,zAND,"(hl)"}, {_0, zAND,"a"},
{_0, zXOR,"b"}, {_0, zXOR,"c"}, {_0, zXOR,"d"}, {_0, zXOR,"e"},
{_0, zXOR,"h"}, {_0, zXOR,"l"}, {_RM,zXOR,"(hl)"}, {_0, zXOR,"a"},
{_0, zOR,"b"}, {_0, zOR,"c"}, {_0, zOR,"d"}, {_0, zOR,"e"},
{_0, zOR,"h"}, {_0, zOR,"l"}, {_RM,zOR,"(hl)"}, {_0, zOR,"a"},
{_0, zCP,"b"}, {_0, zCP,"c"}, {_0, zCP,"d"}, {_0, zCP,"e"},
{_0, zCP,"h"}, {_0, zCP,"l"}, {_RM,zCP,"(hl)"}, {_0, zCP,"a"},
{_0, zRET,"nz"}, {_0, zPOP,"bc"}, {_JP,zJP,"nz,A"}, {_JP,zJP,"A"},
{_JP,zCALL,"nz,A"}, {_0, zPUSH,"bc"}, {_0, zADD,"a,B"}, {_JP,zRST,"V"},
{_0, zRET,"z"}, {_0, zRET,0}, {_JP,zJP,"z,A"}, {_0, zDB,"cb"},
{_JP,zCALL,"z,A"}, {_JP,zCALL,"A"}, {_0, zADC,"a,B"}, {_JP,zRST,"V"},
{_0, zRET,"nc"}, {_0, zPOP,"de"}, {_JP,zJP,"nc,A"}, {_WP,zOUT,"(P),a"},
{_JP,zCALL,"nc,A"}, {_0, zPUSH,"de"}, {_0, zSUB,"B"}, {_JP,zRST,"V"},
{_0, zRET,"c"}, {_0, zEXX,0}, {_JP,zJP,"c,A"}, {_RP,zIN,"a,(P)"},
{_JP,zCALL,"c,A"}, {_0, zDB,"dd"}, {_0, zSBC,"a,B"}, {_JP,zRST,"V"},
{_0, zRET,"po"}, {_0, zPOP,"hl"}, {_JP,zJP,"po,A"}, {_RW,zEX,"(sp),hl"},
{_JP,zCALL,"po,A"}, {_0, zPUSH,"hl"}, {_0, zAND,"B"}, {_JP,zRST,"V"},
{_0, zRET,"pe"}, {_JP,zJP,"(hl)"}, {_JP,zJP,"pe,A"}, {_0, zEX,"de,hl"},
{_JP,zCALL,"pe,A"}, {_0, zDB,"ed"}, {_0, zXOR,"B"}, {_JP,zRST,"V"},
{_0, zRET,"p"}, {_0, zPOP,"af"}, {_JP,zJP,"p,A"}, {_0, zDI,0},
{_JP,zCALL,"p,A"}, {_0, zPUSH,"af"}, {_0, zOR,"B"}, {_JP,zRST,"V"},
{_0, zRET,"m"}, {_0, zLD,"sp,hl"}, {_JP,zJP,"m,A"}, {_0, zEI,0},
{_JP,zCALL,"m,A"}, {_0, zDB,"fd"}, {_0, zCP,"B"}, {_JP,zRST,"V"}
};
static char sign(INT8 offset)
{
return (offset < 0)? '-':'+';
}
static int offs(INT8 offset)
{
if (offset < 0) return -offset;
return offset;
}
/****************************************************************************
* Disassemble opcode at PC and return number of bytes it takes
****************************************************************************/
unsigned DasmZ80( char *buffer, unsigned pc )
{
z80dasm *d;
const char *symbol, *src;
const char *ixy;
char *dst;
unsigned PC = pc;
INT8 offset = 0;
UINT8 op, op1;
UINT16 ea = 0, xy = 0;
ixy = "oops!!";
dst = buffer;
symbol = NULL;
op = cpu_readop( pc++ );
op1 = 0; /* keep GCC happy */
switch (op)
{
case 0xcb:
op = cpu_readop(pc++);
d = &mnemonic_cb[op];
break;
case 0xed:
op1 = cpu_readop(pc++);
d = &mnemonic_ed[op1];
break;
case 0xdd:
ixy = "ix";
op1 = cpu_readop(pc++);
if( op1 == 0xcb )
{
offset = (INT8) cpu_readop_arg(pc++);
op1 = cpu_readop_arg(pc++); /* fourth byte from OP_RAM! */
xy = z80_get_reg( Z80_IX );
ea = (xy + offset) & 0xffff;
d = &mnemonic_xx_cb[op1];
}
else d = &mnemonic_xx[op1];
break;
case 0xfd:
ixy = "iy";
op1 = cpu_readop(pc++);
if( op1 == 0xcb )
{
offset = (INT8) cpu_readop_arg(pc++);
op1 = cpu_readop_arg(pc++); /* fourth byte from OP_RAM! */
xy = z80_get_reg( Z80_IY );
ea = (ea + offset) & 0xffff;
d = &mnemonic_xx_cb[op1];
}
else d = &mnemonic_xx[op1];
break;
default:
d = &mnemonic_main[op];
break;
}
if( d->arguments )
{
dst += sprintf(dst, "%-4s ", s_mnemonic[d->mnemonic]);
src = d->arguments;
while( *src )
{
switch( *src )
{
case '?': /* illegal opcode */
dst += sprintf( dst, "$%02x,$%02x", op, op1);
break;
case 'A':
ea = cpu_readop_arg(pc) + ( cpu_readop_arg((pc+1)&0xffff) << 8);
pc += 2;
symbol = set_ea_info(0, ea, EA_UINT16, d->access);
dst += sprintf( dst, "%s", symbol );
break;
case 'B': /* Byte op arg */
ea = cpu_readop_arg( pc++ );
symbol = set_ea_info(1, ea, EA_UINT8, EA_VALUE);
dst += sprintf( dst, "%s", symbol );
break;
case '(': /* Memory byte at (HL) */
*dst++ = *src;
if( !strncmp( src, "(bc)", 4) )
{
ea = z80_get_reg( Z80_BC );
set_ea_info(0, ea, EA_UINT8, d->access);
}
else
if( !strncmp( src, "(de)", 4) )
{
ea = z80_get_reg( Z80_DE );
set_ea_info(0, ea, EA_UINT8, d->access);
}
else
if( !strncmp( src, "(hl)", 4) )
{
ea = z80_get_reg( Z80_HL );
if( d->access == EA_ABS_PC )
set_ea_info(0, ea, EA_DEFAULT, EA_ABS_PC);
else
set_ea_info(0, ea, EA_UINT8, d->access);
}
else
if( !strncmp( src, "(sp)", 4) )
{
ea = z80_get_reg( Z80_SP );
set_ea_info(0, ea, EA_UINT16, d->access);
}
else
if( !strncmp( src, "(P)", 3) )
{
ea = (z80_get_reg( Z80_AF ) & 0xff00) | cpu_readop_arg( pc );
set_ea_info(0, ea, EA_UINT16, d->access);
}
else
if( !strncmp( src, "(c)", 3) )
{
ea = z80_get_reg( Z80_BC );
set_ea_info(0, ea, EA_UINT16, d->access);
}
else
if( !strncmp( src, "(I)", 3) )
{
ea = xy;
set_ea_info(0, ea, EA_DEFAULT, d->access);
}
break;
case 'N': /* Immediate 16 bit */
ea = cpu_readop_arg(pc) + ( cpu_readop_arg((pc+1)&0xffff) << 8 );
pc += 2;
symbol = set_ea_info(1, ea, EA_UINT16, EA_VALUE );
dst += sprintf( dst, "%s", symbol );
break;
case 'O': /* Offset relative to PC */
offset = (INT8) cpu_readop_arg(pc++);
symbol = set_ea_info(0, PC, offset + 2, d->access);
dst += sprintf( dst, "%s", symbol );
break;
case 'P': /* Port number */
ea = cpu_readop_arg( pc++ );
dst += sprintf( dst, "$%02X", ea );
break;
case 'V': /* Restart vector */
ea = op & 0x38;
symbol = set_ea_info(0, ea, EA_UINT8, d->access);
dst += sprintf( dst, "%s", symbol );
break;
case 'W': /* Memory address word */
ea = cpu_readop_arg(pc) + ( cpu_readop_arg((pc+1)&0xffff) << 8);
pc += 2;
symbol = set_ea_info(0, ea, EA_UINT16, d->access);
dst += sprintf( dst, "%s", symbol );
break;
case 'X':
offset = (INT8) cpu_readop_arg(pc++);
ea = (xy + offset) & 0xffff;
case 'Y':
symbol = set_ea_info(0, ea, EA_UINT8, d->access);
dst += sprintf( dst,"(%s%c$%02x)", ixy, sign(offset), offs(offset) );
break;
case 'I':
dst += sprintf( dst, "%s", ixy);
break;
default:
*dst++ = *src;
}
src++;
}
*dst = '\0';
}
else
{
dst += sprintf(dst, "%s", s_mnemonic[d->mnemonic]);
}
return pc - PC;
}
#endif

View file

@ -1,2 +0,0 @@
extern int DasmZ80(char *buffer, int PC);

View file

@ -1,323 +0,0 @@
/*
Audio Overload SDK - SSF file format engine
Copyright (c) 2007 R. Belmont and Richard Bannister.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
Sega driver commands:
00 - NOP
01 - SEQUENCE_START
02 - SEQUENCE_STOP
03 - SEQUENCE_PAUSE
04 - SEQUENCE_CONTINUE
05 - SEQUENCE_VOLUME
06 - SEQUENCE_ALLSTOP
07 - SEQUENCE_TEMPO
08 - SEQUENCE_MAP
09 - HOST_MIDI
0A - VOLUME_ANALYZE_START
0B - VOLUME_ANALYZE_STOP
0C - DSP CLEAR
0D - ALL OFF
0E - SEQUENCE PAN
0F - N/A
10 - SOUND INITIALIZE
11 - Yamaha 3D check (8C)
12 - QSound check (8B)
13 - Yamaha 3D init (8D)
80 - CD level
81 - CD pan
82 - MASTER VOLUME
83 - EFFECT_CHANGE
84 - NOP
85 - PCM stream play start
86 - PCM stream play end
87 - MIXER_CHANGE
88 - Mixer parameter change
89 - Hardware check
8A - PCM parameter change
8B - QSound check
8C - Yamaha 3D check
8D - Yamaha 3D init
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ao.h"
#include "eng_protos.h"
#include "corlett.h"
#include "sat_hw.h"
#include "scsp.h"
#define DEBUG_LOADER (0)
static corlett_t *c = NULL;
static char psfby[256];
static uint32 decaybegin, decayend, total_samples;
void *scsp_start(const void *config);
void SCSP_Update(void *param, INT16 **inputs, INT16 **buf, int samples);
int32 ssf_start(uint8 *buffer, uint32 length)
{
uint8 *file, *lib_decoded, *lib_raw_file;
uint32 offset, plength, lengthMS, fadeMS;
uint64 file_len, lib_len, lib_raw_length;
corlett_t *lib;
char *libfile;
int i;
// clear Saturn work RAM before we start scribbling in it
memset(sat_ram, 0, 512*1024);
// Decode the current SSF
if (corlett_decode(buffer, length, &file, &file_len, &c) != AO_SUCCESS)
{
return AO_FAIL;
}
#if DEBUG_LOADER
printf("%d bytes decoded\n", file_len);
#endif
// Get the library file, if any
for (i=0; i<9; i++)
{
libfile = i ? c->libaux[i-1] : c->lib;
if (libfile[0] != 0)
{
uint64 tmp_length;
#if DEBUG_LOADER
printf("Loading library: %s\n", c->lib);
#endif
if (ao_get_lib(libfile, &lib_raw_file, &tmp_length) != AO_SUCCESS)
{
return AO_FAIL;
}
lib_raw_length = tmp_length;
if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS)
{
free(lib_raw_file);
return AO_FAIL;
}
// Free up raw file
free(lib_raw_file);
// patch the file into ram
offset = lib_decoded[0] | lib_decoded[1]<<8 | lib_decoded[2]<<16 | lib_decoded[3]<<24;
// guard against invalid data
if ((offset + (lib_len-4)) > 0x7ffff)
{
lib_len = 0x80000-offset+4;
}
memcpy(&sat_ram[offset], lib_decoded+4, lib_len-4);
// Dispose the corlett structure for the lib - we don't use it
free(lib);
free(lib_decoded);
}
}
// now patch the file into RAM over the libraries
offset = file[3]<<24 | file[2]<<16 | file[1]<<8 | file[0];
// guard against invalid data
if ((offset + (file_len-4)) > 0x7ffff)
{
file_len = 0x80000-offset+4;
}
memcpy(&sat_ram[offset], file+4, file_len-4);
free(file);
// Finally, set psfby tag
strcpy(psfby, "n/a");
if (c)
{
for (i = 0; i < MAX_UNKNOWN_TAGS; i++)
{
if (!strcasecmp(c->tag_name[i], "psfby"))
strcpy(psfby, c->tag_data[i]);
}
}
#if DEBUG_LOADER && 1
{
FILE *f;
f = fopen("satram.bin", "wb");
fwrite(sat_ram, 512*1024, 1, f);
fclose(f);
}
#endif
// now flip everything (this makes sense because he's using starscream)
for (i = 0; i < 512*1024; i+=2)
{
uint8 temp;
temp = sat_ram[i];
sat_ram[i] = sat_ram[i+1];
sat_ram[i+1] = temp;
}
sat_hw_init();
// now figure out the time in samples for the length/fade
lengthMS = psfTimeToMS(c->inf_length);
fadeMS = psfTimeToMS(c->inf_fade);
total_samples = 0;
if (lengthMS == 0)
{
lengthMS = ~0;
}
if (lengthMS == ~0)
{
decaybegin = lengthMS;
}
else
{
lengthMS = (lengthMS * 441) / 10;
fadeMS = (fadeMS * 441) / 10;
decaybegin = lengthMS;
decayend = lengthMS + fadeMS;
}
return AO_SUCCESS;
}
int32 ssf_gen(int16 *buffer, uint32 samples)
{
int i;
int16 output[44100/30], output2[44100/30];
int16 *stereo[2];
int16 *outp = buffer;
int opos;
opos = 0;
for (i = 0; i < samples; i++)
{
m68k_execute((11300000/60)/735);
stereo[0] = &output[opos];
stereo[1] = &output2[opos];
SCSP_Update(NULL, NULL, stereo, 1);
opos++;
}
for (i = 0; i < samples; i++)
{
// process the fade tags
if (total_samples >= decaybegin)
{
if (total_samples >= decayend)
{
// song is done here, call out as necessary to make your player stop
output[i] = 0;
output2[i] = 0;
}
else
{
int32 fader = 256 - (256*(total_samples - decaybegin)/(decayend-decaybegin));
output[i] = (output[i] * fader)>>8;
output2[i] = (output2[i] * fader)>>8;
total_samples++;
}
}
else
{
total_samples++;
}
*outp++ = output[i];
*outp++ = output2[i];
}
return AO_SUCCESS;
}
int32 ssf_stop(void)
{
scsp_stop();
free(c);
return AO_SUCCESS;
}
int32 ssf_command(int32 command, int32 parameter)
{
switch (command)
{
case COMMAND_RESTART:
return AO_SUCCESS;
}
return AO_FAIL;
}
int32 ssf_fill_info(ao_display_info *info)
{
if (c == NULL)
return AO_FAIL;
strcpy(info->title[1], "Name: ");
sprintf(info->info[1], "%s", c->inf_title);
strcpy(info->title[2], "Game: ");
sprintf(info->info[2], "%s", c->inf_game);
strcpy(info->title[3], "Artist: ");
sprintf(info->info[3], "%s", c->inf_artist);
strcpy(info->title[4], "Copyright: ");
sprintf(info->info[4], "%s", c->inf_copy);
strcpy(info->title[5], "Year: ");
sprintf(info->info[5], "%s", c->inf_year);
strcpy(info->title[6], "Length: ");
sprintf(info->info[6], "%s", c->inf_length);
strcpy(info->title[7], "Fade: ");
sprintf(info->info[7], "%s", c->inf_fade);
strcpy(info->title[8], "Ripper: ");
sprintf(info->info[8], "%s", psfby);
return AO_SUCCESS;
}

View file

@ -1,343 +0,0 @@
#ifndef M68K__HEADER
#define M68K__HEADER
/* ======================================================================== */
/* ========================= LICENSING & COPYRIGHT ======================== */
/* ======================================================================== */
/*
* MUSASHI
* Version 3.3
*
* A portable Motorola M680x0 processor emulation engine.
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
*
* This code may be freely used for non-commercial purposes as long as this
* copyright notice remains unaltered in the source code and any binary files
* containing this code in compiled form.
*
* All other lisencing terms must be negotiated with the author
* (Karl Stenerud).
*
* The latest version of this code can be obtained at:
* http://kstenerud.cjb.net
*/
/* ======================================================================== */
/* ============================ GENERAL DEFINES =========================== */
/* ======================================================================== */
/* There are 7 levels of interrupt to the 68K.
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
*/
#define M68K_IRQ_NONE 0
#define M68K_IRQ_1 1
#define M68K_IRQ_2 2
#define M68K_IRQ_3 3
#define M68K_IRQ_4 4
#define M68K_IRQ_5 5
#define M68K_IRQ_6 6
#define M68K_IRQ_7 7
/* Special interrupt acknowledge values.
* Use these as special returns from the interrupt acknowledge callback
* (specified later in this header).
*/
/* Causes an interrupt autovector (0x18 + interrupt level) to be taken.
* This happens in a real 68K if VPA or AVEC is asserted during an interrupt
* acknowledge cycle instead of DTACK.
*/
#define M68K_INT_ACK_AUTOVECTOR 0xffffffff
/* Causes the spurious interrupt vector (0x18) to be taken
* This happens in a real 68K if BERR is asserted during the interrupt
* acknowledge cycle (i.e. no devices responded to the acknowledge).
*/
#define M68K_INT_ACK_SPURIOUS 0xfffffffe
/* CPU types for use in m68k_set_cpu_type() */
enum
{
M68K_CPU_TYPE_INVALID,
M68K_CPU_TYPE_68000,
M68K_CPU_TYPE_68010,
M68K_CPU_TYPE_68EC020,
M68K_CPU_TYPE_68020,
M68K_CPU_TYPE_68030, /* Supported by disassembler ONLY */
M68K_CPU_TYPE_68040 /* Supported by disassembler ONLY */
};
/* Registers used by m68k_get_reg() and m68k_set_reg() */
typedef enum
{
/* Real registers */
M68K_REG_D0, /* Data registers */
M68K_REG_D1,
M68K_REG_D2,
M68K_REG_D3,
M68K_REG_D4,
M68K_REG_D5,
M68K_REG_D6,
M68K_REG_D7,
M68K_REG_A0, /* Address registers */
M68K_REG_A1,
M68K_REG_A2,
M68K_REG_A3,
M68K_REG_A4,
M68K_REG_A5,
M68K_REG_A6,
M68K_REG_A7,
M68K_REG_PC, /* Program Counter */
M68K_REG_SR, /* Status Register */
M68K_REG_SP, /* The current Stack Pointer (located in A7) */
M68K_REG_USP, /* User Stack Pointer */
M68K_REG_ISP, /* Interrupt Stack Pointer */
M68K_REG_MSP, /* Master Stack Pointer */
M68K_REG_SFC, /* Source Function Code */
M68K_REG_DFC, /* Destination Function Code */
M68K_REG_VBR, /* Vector Base Register */
M68K_REG_CACR, /* Cache Control Register */
M68K_REG_CAAR, /* Cache Address Register */
/* Assumed registers */
/* These are cheat registers which emulate the 1-longword prefetch
* present in the 68000 and 68010.
*/
M68K_REG_PREF_ADDR, /* Last prefetch address */
M68K_REG_PREF_DATA, /* Last prefetch data */
/* Convenience registers */
M68K_REG_PPC, /* Previous value in the program counter */
M68K_REG_IR, /* Instruction register */
M68K_REG_CPU_TYPE /* Type of CPU being run */
} m68k_register_t;
/* ======================================================================== */
/* ====================== FUNCTIONS CALLED BY THE CPU ===================== */
/* ======================================================================== */
/* You will have to implement these functions */
/* read/write functions called by the CPU to access memory.
* while values used are 32 bits, only the appropriate number
* of bits are relevant (i.e. in write_memory_8, only the lower 8 bits
* of value should be written to memory).
*
* NOTE: I have separated the immediate and PC-relative memory fetches
* from the other memory fetches because some systems require
* differentiation between PROGRAM and DATA fetches (usually
* for security setups such as encryption).
* This separation can either be achieved by setting
* M68K_SEPARATE_READS in m68kconf.h and defining
* the read functions, or by setting M68K_EMULATE_FC and
* making a function code callback function.
* Using the callback offers better emulation coverage
* because you can also monitor whether the CPU is in SYSTEM or
* USER mode, but it is also slower.
*/
/* Read from anywhere */
unsigned int m68k_read_memory_8(unsigned int address);
unsigned int m68k_read_memory_16(unsigned int address);
unsigned int m68k_read_memory_32(unsigned int address);
/* Read data immediately following the PC */
//INLINE unsigned int m68k_read_immediate_16(unsigned int address);
//INLINE unsigned int m68k_read_immediate_32(unsigned int address);
/* Read data relative to the PC */
//INLINE unsigned int m68k_read_pcrelative_8(unsigned int address);
//INLINE unsigned int m68k_read_pcrelative_16(unsigned int address);
//INLINE unsigned int m68k_read_pcrelative_32(unsigned int address);
/* Memory access for the disassembler */
unsigned int m68k_read_disassembler_8 (unsigned int address);
unsigned int m68k_read_disassembler_16 (unsigned int address);
unsigned int m68k_read_disassembler_32 (unsigned int address);
/* Write to anywhere */
void m68k_write_memory_8(unsigned int address, unsigned int value);
void m68k_write_memory_16(unsigned int address, unsigned int value);
void m68k_write_memory_32(unsigned int address, unsigned int value);
/* Special call to simulate undocumented 68k behavior when move.l with a
* predecrement destination mode is executed.
* To simulate real 68k behavior, first write the high word to
* [address+2], and then write the low word to [address].
*
* Enable this functionality with M68K_SIMULATE_PD_WRITES in m68kconf.h.
*/
//INLINE void m68k_write_memory_32_pd(unsigned int address, unsigned int value);
/* ======================================================================== */
/* ============================== CALLBACKS =============================== */
/* ======================================================================== */
/* These functions allow you to set callbacks to the host when specific events
* occur. Note that you must enable the corresponding value in m68kconf.h
* in order for these to do anything useful.
* Note: I have defined default callbacks which are used if you have enabled
* the corresponding #define in m68kconf.h but either haven't assigned a
* callback or have assigned a callback of NULL.
*/
/* Set the callback for an interrupt acknowledge.
* You must enable M68K_EMULATE_INT_ACK in m68kconf.h.
* The CPU will call the callback with the interrupt level being acknowledged.
* The host program must return either a vector from 0x02-0xff, or one of the
* special interrupt acknowledge values specified earlier in this header.
* If this is not implemented, the CPU will always assume an autovectored
* interrupt, and will automatically clear the interrupt request when it
* services the interrupt.
* Default behavior: return M68K_INT_ACK_AUTOVECTOR.
*/
void m68k_set_int_ack_callback(int (*callback)(int int_level));
/* Set the callback for a breakpoint acknowledge (68010+).
* You must enable M68K_EMULATE_BKPT_ACK in m68kconf.h.
* The CPU will call the callback with whatever was in the data field of the
* BKPT instruction for 68020+, or 0 for 68010.
* Default behavior: do nothing.
*/
void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data));
/* Set the callback for the RESET instruction.
* You must enable M68K_EMULATE_RESET in m68kconf.h.
* The CPU calls this callback every time it encounters a RESET instruction.
* Default behavior: do nothing.
*/
void m68k_set_reset_instr_callback(void (*callback)(void));
/* Set the callback for informing of a large PC change.
* You must enable M68K_MONITOR_PC in m68kconf.h.
* The CPU calls this callback with the new PC value every time the PC changes
* by a large value (currently set for changes by longwords).
* Default behavior: do nothing.
*/
void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc));
/* Set the callback for CPU function code changes.
* You must enable M68K_EMULATE_FC in m68kconf.h.
* The CPU calls this callback with the function code before every memory
* access to set the CPU's function code according to what kind of memory
* access it is (supervisor/user, program/data and such).
* Default behavior: do nothing.
*/
void m68k_set_fc_callback(void (*callback)(unsigned int new_fc));
/* Set a callback for the instruction cycle of the CPU.
* You must enable M68K_INSTRUCTION_HOOK in m68kconf.h.
* The CPU calls this callback just before fetching the opcode in the
* instruction cycle.
* Default behavior: do nothing.
*/
void m68k_set_instr_hook_callback(void (*callback)(void));
/* ======================================================================== */
/* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */
/* ======================================================================== */
/* Use this function to set the CPU type you want to emulate.
* Currently supported types are: M68K_CPU_TYPE_68000, M68K_CPU_TYPE_68010,
* M68K_CPU_TYPE_EC020, and M68K_CPU_TYPE_68020.
*/
void m68k_set_cpu_type(unsigned int cpu_type);
/* Do whatever initialisations the core requires. Should be called
* at least once at init time.
*/
void m68k_init(void);
/* Pulse the RESET pin on the CPU.
* You *MUST* reset the CPU at least once to initialize the emulation
* Note: If you didn't call m68k_set_cpu_type() before resetting
* the CPU for the first time, the CPU will be set to
* M68K_CPU_TYPE_68000.
*/
void m68k_pulse_reset(void);
/* execute num_cycles worth of instructions. returns number of cycles used */
int m68k_execute(int num_cycles);
/* These functions let you read/write/modify the number of cycles left to run
* while m68k_execute() is running.
* These are useful if the 68k accesses a memory-mapped port on another device
* that requires immediate processing by another CPU.
*/
int m68k_cycles_run(void); /* Number of cycles run so far */
int m68k_cycles_remaining(void); /* Number of cycles left */
void m68k_modify_timeslice(int cycles); /* Modify cycles left */
void m68k_end_timeslice(void); /* End timeslice now */
/* Set the IPL0-IPL2 pins on the CPU (IRQ).
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
* Setting IRQ to 0 will clear an interrupt request.
*/
void m68k_set_irq(unsigned int int_level);
/* Halt the CPU as if you pulsed the HALT pin. */
void m68k_pulse_halt(void);
/* Context switching to allow multiple CPUs */
/* Get the size of the cpu context in bytes */
unsigned int m68k_context_size(void);
/* Get a cpu context */
unsigned int m68k_get_context(void* dst);
/* set the current cpu context */
void m68k_set_context(void* dst);
/* Register the CPU state information */
void m68k_state_register(const char *type);
/* Peek at the internals of a CPU context. This can either be a context
* retrieved using m68k_get_context() or the currently running context.
* If context is NULL, the currently running CPU context will be used.
*/
unsigned int m68k_get_reg(void* context, m68k_register_t reg);
/* Poke values into the internals of the currently running CPU context */
void m68k_set_reg(m68k_register_t reg, unsigned int value);
/* Check if an instruction is valid for the specified CPU type */
unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type);
/* Disassemble 1 instruction using the epecified CPU type at pc. Stores
* disassembly in str_buff and returns the size of the instruction in bytes.
*/
unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type);
/* ======================================================================== */
/* ============================= CONFIGURATION ============================ */
/* ======================================================================== */
/* Import the configuration for this build */
#include "m68kconf.h"
/* ======================================================================== */
/* ============================== END OF FILE ============================= */
/* ======================================================================== */
#endif /* M68K__HEADER */

File diff suppressed because it is too large Load diff

View file

@ -1,181 +0,0 @@
/* ======================================================================== */
/* ========================= LICENSING & COPYRIGHT ======================== */
/* ======================================================================== */
/*
* MUSASHI
* Version 3.3
*
* A portable Motorola M680x0 processor emulation engine.
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
*
* This code may be freely used for non-commercial purposes as long as this
* copyright notice remains unaltered in the source code and any binary files
* containing this code in compiled form.
*
* All other lisencing terms must be negotiated with the author
* (Karl Stenerud).
*
* The latest version of this code can be obtained at:
* http://kstenerud.cjb.net
*/
#ifndef M68KCONF__HEADER
#define M68KCONF__HEADER
/* Configuration switches.
* Use OPT_SPECIFY_HANDLER for configuration options that allow callbacks.
* OPT_SPECIFY_HANDLER causes the core to link directly to the function
* or macro you specify, rather than using callback functions whose pointer
* must be passed in using m68k_set_xxx_callback().
*/
#define OPT_OFF 0
#define OPT_ON 1
#define OPT_SPECIFY_HANDLER 2
/* ======================================================================== */
/* ============================== MAME STUFF ============================== */
/* ======================================================================== */
/* If you're compiling this for MAME, only change M68K_COMPILE_FOR_MAME
* to OPT_ON and use m68kmame.h to configure the 68k core.
*/
#ifndef M68K_COMPILE_FOR_MAME
#define M68K_COMPILE_FOR_MAME OPT_OFF
#endif /* M68K_COMPILE_FOR_MAME */
#if M68K_COMPILE_FOR_MAME == OPT_ON
#include "m68kmame.h"
#else
/* ======================================================================== */
/* ============================= CONFIGURATION ============================ */
/* ======================================================================== */
/* Turn ON if you want to use the following M68K variants */
#define M68K_EMULATE_010 OPT_OFF
#define M68K_EMULATE_EC020 OPT_OFF
#define M68K_EMULATE_020 OPT_OFF
/* If ON, the CPU will call m68k_read_immediate_xx() for immediate addressing
* and m68k_read_pcrelative_xx() for PC-relative addressing.
* If off, all read requests from the CPU will be redirected to m68k_read_xx()
*/
#define M68K_SEPARATE_READS OPT_OFF
/* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a
* predecrement destination EA mode instead of m68k_write_32().
* To simulate real 68k behavior, m68k_write_32_pd() must first write the high
* word to [address+2], and then write the low word to [address].
*/
#define M68K_SIMULATE_PD_WRITES OPT_OFF
/* If ON, CPU will call the interrupt acknowledge callback when it services an
* interrupt.
* If off, all interrupts will be autovectored and all interrupt requests will
* auto-clear when the interrupt is serviced.
*/
#define M68K_EMULATE_INT_ACK OPT_ON
#define M68K_INT_ACK_CALLBACK(A) your_int_ack_handler_function(A)
/* If ON, CPU will call the breakpoint acknowledge callback when it encounters
* a breakpoint instruction and it is running a 68010+.
*/
#define M68K_EMULATE_BKPT_ACK OPT_OFF
#define M68K_BKPT_ACK_CALLBACK() your_bkpt_ack_handler_function()
/* If ON, the CPU will monitor the trace flags and take trace exceptions
*/
#define M68K_EMULATE_TRACE OPT_OFF
/* If ON, CPU will call the output reset callback when it encounters a reset
* instruction.
*/
#define M68K_EMULATE_RESET OPT_OFF
#define M68K_RESET_CALLBACK() your_reset_handler_function()
/* If ON, CPU will call the set fc callback on every memory access to
* differentiate between user/supervisor, program/data access like a real
* 68000 would. This should be enabled and the callback should be set if you
* want to properly emulate the m68010 or higher. (moves uses function codes
* to read/write data from different address spaces)
*/
#define M68K_EMULATE_FC OPT_OFF
#define M68K_SET_FC_CALLBACK(A) your_set_fc_handler_function(A)
/* If ON, CPU will call the pc changed callback when it changes the PC by a
* large value. This allows host programs to be nicer when it comes to
* fetching immediate data and instructions on a banked memory system.
*/
#define M68K_MONITOR_PC OPT_OFF
#define M68K_SET_PC_CALLBACK(A) your_pc_changed_handler_function(A)
/* If ON, CPU will call the instruction hook callback before every
* instruction.
*/
#define M68K_INSTRUCTION_HOOK OPT_OFF
#define M68K_INSTRUCTION_CALLBACK() your_instruction_hook_function()
/* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */
#define M68K_EMULATE_PREFETCH OPT_ON
/* If ON, the CPU will generate address error exceptions if it tries to
* access a word or longword at an odd address.
* NOTE: Do not enable this! It is not working!
*/
#define M68K_EMULATE_ADDRESS_ERROR OPT_OFF
/* Turn ON to enable logging of illegal instruction calls.
* M68K_LOG_FILEHANDLE must be #defined to a stdio file stream.
* Turn on M68K_LOG_1010_1111 to log all 1010 and 1111 calls.
*/
#define M68K_LOG_ENABLE OPT_OFF
#define M68K_LOG_1010_1111 OPT_OFF
#define M68K_LOG_FILEHANDLE some_file_handle
/* ----------------------------- COMPATIBILITY ---------------------------- */
/* The following options set optimizations that violate the current ANSI
* standard, but will be compliant under the forthcoming C9X standard.
*/
/* If ON, the enulation core will use 64-bit integers to speed up some
* operations.
*/
#define M68K_USE_64_BIT OPT_OFF
/* Set to your compiler's static inline keyword to enable it, or
* set it to blank to disable it.
* If you define INLINE in the makefile, it will override this value.
* NOTE: not enabling inline functions will SEVERELY slow down emulation.
*/
#ifndef INLINE
#define INLINE static __inline__
#endif /* INLINE */
#endif /* M68K_COMPILE_FOR_MAME */
/* ======================================================================== */
/* ============================== END OF FILE ============================= */
/* ======================================================================== */
#endif /* M68KCONF__HEADER */

File diff suppressed because it is too large Load diff

View file

@ -1,172 +0,0 @@
#ifndef M68KMAME__HEADER
#define M68KMAME__HEADER
/* ======================================================================== */
/* ============================== MAME STUFF ============================== */
/* ======================================================================== */
#include "cpuintrf.h"
#include "memory.h"
#include "mamedbg.h"
#include "m68000.h"
extern int m68ki_remaining_cycles;
/* Configuration switches (see m68kconf.h for explanation) */
#define M68K_SEPARATE_READS OPT_ON
#define M68K_SIMULATE_PD_WRITES OPT_ON
#define M68K_EMULATE_INT_ACK OPT_ON
#define M68K_INT_ACK_CALLBACK(A)
#define M68K_EMULATE_BKPT_ACK OPT_OFF
#define M68K_BKPT_ACK_CALLBACK()
#define M68K_EMULATE_TRACE OPT_OFF
#define M68K_EMULATE_RESET OPT_ON
#define M68K_RESET_CALLBACK()
#define M68K_EMULATE_FC OPT_OFF
#define M68K_SET_FC_CALLBACK(A)
#define M68K_MONITOR_PC OPT_SPECIFY_HANDLER
#define M68K_SET_PC_CALLBACK(A) (*m68k_memory_intf.changepc)(A)
#define M68K_INSTRUCTION_HOOK OPT_SPECIFY_HANDLER
#define M68K_INSTRUCTION_CALLBACK() CALL_MAME_DEBUG
#define M68K_EMULATE_PREFETCH OPT_ON
#define M68K_LOG_ENABLE OPT_OFF
#define M68K_LOG_1010_1111 OPT_OFF
#define M68K_LOG_FILEHANDLE errorlog
#define M68K_EMULATE_ADDRESS_ERROR OPT_OFF
#define M68K_USE_64_BIT OPT_OFF
extern struct m68k_memory_interface m68k_memory_intf;
#define m68k_read_memory_8(address) (*m68k_memory_intf.read8)(address)
#define m68k_read_memory_16(address) (*m68k_memory_intf.read16)(address)
#define m68k_read_memory_32(address) (*m68k_memory_intf.read32)(address)
INLINE unsigned int m68k_read_immediate_16(unsigned int address)
{
return cpu_readop16((address) ^ m68k_memory_intf.opcode_xor);
}
INLINE unsigned int m68k_read_immediate_32(unsigned int address)
{
return ((m68k_read_immediate_16(address) << 16) | m68k_read_immediate_16((address)+2));
}
INLINE unsigned int m68k_read_pcrelative_8(unsigned int address)
{
if (address >= encrypted_opcode_start[cpu_getactivecpu()] &&
address < encrypted_opcode_end[cpu_getactivecpu()])
return ((m68k_read_immediate_16(address&~1)>>(8*(1-(address & 1))))&0xff);
else
return m68k_read_memory_8(address);
}
INLINE unsigned int m68k_read_pcrelative_16(unsigned int address)
{
if (address >= encrypted_opcode_start[cpu_getactivecpu()] &&
address < encrypted_opcode_end[cpu_getactivecpu()])
return m68k_read_immediate_16(address);
else
return m68k_read_memory_16(address);
}
INLINE unsigned int m68k_read_pcrelative_32(unsigned int address)
{
if (address >= encrypted_opcode_start[cpu_getactivecpu()] &&
address < encrypted_opcode_end[cpu_getactivecpu()])
return m68k_read_immediate_32(address);
else
return m68k_read_memory_32(address);
}
#define m68k_read_disassembler_16(address) m68k_read_immediate_16(address)
#define m68k_read_disassembler_32(address) m68k_read_immediate_32(address)
#define m68k_write_memory_8(address, value) (*m68k_memory_intf.write8)(address, value)
#define m68k_write_memory_16(address, value) (*m68k_memory_intf.write16)(address, value)
#define m68k_write_memory_32(address, value) (*m68k_memory_intf.write32)(address, value)
/* Special call to simulate undocumented 68k behavior when move.l with a
* predecrement destination mode is executed.
* A real 68k first writes the high word to [address+2], and then writes the
* low word to [address].
*/
INLINE void m68k_write_memory_32_pd(unsigned int address, unsigned int value)
{
(*m68k_memory_intf.write16)(address+2, value>>16);
(*m68k_memory_intf.write16)(address, value&0xffff);
}
#ifdef A68K0
#define M68K_EMULATE_010 OPT_OFF
#else
// The PPC 68k core defines A68K0 internal to itself to avoid recompiling
// all of MAME when you want to disable it. The downside is that the C and x86
// cores can't agree on the same name for the icount variable, so we force the
// issue with a Mac-specific hack.
#ifdef macintosh
extern int m68k_ICount;
#else
#define m68ki_remaining_cycles m68k_ICount
#endif
/* M68K Variants */
#if HAS_M68010
#define M68K_EMULATE_010 OPT_ON
#else
#define M68K_EMULATE_010 OPT_OFF
#endif
#endif // A68K0
#ifdef A68K2
#define M68K_EMULATE_EC020 OPT_OFF
#define M68K_EMULATE_020 OPT_OFF
#else
// The PPC 68k core defines A68K2 internal to itself to avoid recompiling
// all of MAME when you want to disable it. The downside is that the C and x86
// cores can't agree on the same name for the icount variable, so we force the
// issue with a Mac-specific hack.
#ifdef macintosh
extern int M68020_ICount;
#else
#define m68ki_remaining_cycles m68k_ICount
#endif
#undef M68K_EMULATE_010
#define M68K_EMULATE_010 OPT_ON
#if HAS_M68EC020
#define M68K_EMULATE_EC020 OPT_ON
#else
#define M68K_EMULATE_EC020 OPT_OFF
#endif
#if HAS_M68020
#define M68K_EMULATE_020 OPT_ON
#else
#define M68K_EMULATE_020 OPT_OFF
#endif
#endif // A68K2
/* ======================================================================== */
/* ============================== END OF FILE ============================= */
/* ======================================================================== */
#endif /* M68KMAME__HEADER */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,170 +0,0 @@
/*
sat_hw.c - Saturn sound hardware glue/emulation/whatever
supported: main RAM (512 KB)
SCSP + timers
MC68000 CPU
Copyright (c) 2007, R. Belmont and Richard Bannister.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include "ao.h"
#include "scsp.h"
#include "sat_hw.h"
#include "m68k.h"
uint8 sat_ram[512*1024];
static void scsp_irq(int irq)
{
if (irq > 0)
{
m68k_set_irq(irq);
}
}
#define MIXER_PAN_LEFT 1
#define MIXER_PAN_RIGHT 2
#define MIXER(level,pan) ((level & 0xff) | ((pan & 0x03) << 8))
#define YM3012_VOL(LVol,LPan,RVol,RPan) (MIXER(LVol,LPan)|(MIXER(RVol,RPan) << 16))
static struct SCSPinterface scsp_interface =
{
1,
{ sat_ram, },
{ YM3012_VOL(100, MIXER_PAN_LEFT, 100, MIXER_PAN_RIGHT) },
{ scsp_irq, },
};
void sat_hw_init(void)
{
m68k_init();
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
m68k_pulse_reset();
scsp_interface.region[0] = sat_ram;
scsp_start(&scsp_interface);
}
/* M68k memory handlers */
unsigned int m68k_read_memory_8(unsigned int address)
{
if (address < (512*1024))
return sat_ram[address^1];
if (address >= 0x100000 && address < 0x100c00)
{
int foo = SCSP_0_r((address - 0x100000)/2, 0);
if (address & 1)
return foo & 0xff;
else
return foo>>8;
}
printf("R8 @ %x\n", address);
return 0;
}
unsigned int m68k_read_memory_16(unsigned int address)
{
if (address < (512*1024))
{
return mem_readword_swap((unsigned short *)(sat_ram+address));
}
if (address >= 0x100000 && address < 0x100c00)
return SCSP_0_r((address-0x100000)/2, 0);
printf("R16 @ %x\n", address);
return 0;
}
unsigned int m68k_read_memory_32(unsigned int address)
{
if (address < 0x80000)
{
return sat_ram[address+2] | sat_ram[address+3]<<8 | sat_ram[address]<<16 | sat_ram[address+1]<<24;
}
printf("R32 @ %x\n", address);
return 0;
}
void m68k_write_memory_8(unsigned int address, unsigned int data)
{
if (address < 0x80000)
{
sat_ram[address^1] = data;
return;
}
if (address >= 0x100000 && address < 0x100c00)
{
address -= 0x100000;
if (address & 1)
SCSP_0_w(address>>1, data, 0xff00);
else
SCSP_0_w(address>>1, data<<8, 0x00ff);
return;
}
}
void m68k_write_memory_16(unsigned int address, unsigned int data)
{
if (address < 0x80000)
{
sat_ram[address+1] = (data>>8)&0xff;
sat_ram[address] = data&0xff;
return;
}
if (address >= 0x100000 && address < 0x100c00)
{
SCSP_0_w((address-0x100000)>>1, data, 0x0000);
return;
}
}
void m68k_write_memory_32(unsigned int address, unsigned int data)
{
if (address < 0x80000)
{
sat_ram[address+1] = (data>>24)&0xff;
sat_ram[address] = (data>>16)&0xff;
sat_ram[address+3] = (data>>8)&0xff;
sat_ram[address+2] = data&0xff;
return;
}
if (address >= 0x100000 && address < 0x100c00)
{
address -= 0x100000;
SCSP_0_w(address>>1, data>>16, 0x0000);
SCSP_0_w((address>>1)+1, data&0xffff, 0x0000);
return;
}
}

View file

@ -1,35 +0,0 @@
#ifndef _SAT_HW_H_
#define _SAT_HW_H_
extern uint8 sat_ram[512*1024];
void sat_hw_init(void);
#if !LSB_FIRST
static unsigned short INLINE mem_readword_swap(unsigned short *addr)
{
return ((*addr&0x00ff)<<8)|((*addr&0xff00)>>8);
}
static void INLINE mem_writeword_swap(unsigned short *addr, unsigned short value)
{
*addr = ((value&0x00ff)<<8)|((value&0xff00)>>8);
}
#else // big endian
static unsigned short INLINE mem_readword_swap(unsigned short *addr)
{
unsigned long retval;
retval = *addr;
return retval;
}
static void INLINE mem_writeword_swap(unsigned short *addr, unsigned short value)
{
*addr = value;
}
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,45 +0,0 @@
/*
SCSP (YMF292-F) header
*/
#ifndef _SCSP_H_
#define _SCSP_H_
#define MAX_SCSP (2)
#define COMBINE_DATA(varptr) (*(varptr) = (*(varptr) & mem_mask) | (data & ~mem_mask))
// convert AO types
typedef int8 data8_t;
typedef int16 data16_t;
typedef int32 data32_t;
typedef int offs_t;
struct SCSPinterface
{
int num;
void *region[MAX_SCSP];
int mixing_level[MAX_SCSP]; /* volume */
void (*irq_callback[MAX_SCSP])(int state); /* irq callback */
};
void *scsp_start(const void *config);
void scsp_stop(void);
void SCSP_Update(void *param, INT16 **inputs, INT16 **buf, int samples);
#define READ16_HANDLER(name) data16_t name(offs_t offset, data16_t mem_mask)
#define WRITE16_HANDLER(name) void name(offs_t offset, data16_t data, data16_t mem_mask)
// SCSP register access
READ16_HANDLER( SCSP_0_r );
WRITE16_HANDLER( SCSP_0_w );
READ16_HANDLER( SCSP_1_r );
WRITE16_HANDLER( SCSP_1_w );
// MIDI I/O access (used for comms on Model 2/3)
WRITE16_HANDLER( SCSP_MidiIn );
READ16_HANDLER( SCSP_MidiOutR );
#endif

View file

@ -1,349 +0,0 @@
#include <assert.h>
#include <math.h>
#include "ao.h"
#include "cpuintrf.h"
#include "scsp.h"
#include "scspdsp.h"
static UINT16 PACK(INT32 val)
{
UINT32 temp;
int sign,exponent,k;
sign = (val >> 23) & 0x1;
temp = (val ^ (val << 1)) & 0xFFFFFF;
exponent = 0;
for (k=0; k<12; k++)
{
if (temp & 0x800000)
break;
temp <<= 1;
exponent += 1;
}
if (exponent < 12)
val = (val << exponent) & 0x3FFFFF;
else
val <<= 11;
val >>= 11;
val |= sign << 15;
val |= exponent << 11;
return (UINT16)val;
}
static INT32 UNPACK(UINT16 val)
{
int sign,exponent,mantissa;
INT32 uval;
sign = (val >> 15) & 0x1;
exponent = (val >> 11) & 0xF;
mantissa = val & 0x7FF;
uval = mantissa << 11;
if (exponent > 11)
exponent = 11;
else
uval |= (sign ^ 1) << 22;
uval |= sign << 23;
uval <<= 8;
uval >>= 8;
uval >>= exponent;
return uval;
}
void SCSPDSP_Init(struct _SCSPDSP *DSP)
{
memset(DSP,0,sizeof(struct _SCSPDSP));
DSP->RBL=0x8000;
DSP->Stopped=1;
}
void SCSPDSP_Step(struct _SCSPDSP *DSP)
{
INT32 ACC=0; //26 bit
INT32 SHIFTED=0; //24 bit
INT32 X=0; //24 bit
INT32 Y=0; //13 bit
INT32 B=0; //26 bit
INT32 INPUTS=0; //24 bit
INT32 MEMVAL=0;
INT32 FRC_REG=0; //13 bit
INT32 Y_REG=0; //24 bit
UINT32 ADDR=0;
UINT32 ADRS_REG=0; //13 bit
int step;
if(DSP->Stopped)
return;
memset(DSP->EFREG,0,2*16);
#if 0
int dump=0;
FILE *f=NULL;
if(dump)
f=fopen("dsp.txt","wt");
#endif
for(step=0;step</*128*/DSP->LastStep;++step)
{
UINT16 *IPtr=DSP->MPRO+step*4;
// if(IPtr[0]==0 && IPtr[1]==0 && IPtr[2]==0 && IPtr[3]==0)
// break;
UINT32 TRA=(IPtr[0]>>8)&0x7F;
UINT32 TWT=(IPtr[0]>>7)&0x01;
UINT32 TWA=(IPtr[0]>>0)&0x7F;
UINT32 XSEL=(IPtr[1]>>15)&0x01;
UINT32 YSEL=(IPtr[1]>>13)&0x03;
UINT32 IRA=(IPtr[1]>>6)&0x3F;
UINT32 IWT=(IPtr[1]>>5)&0x01;
UINT32 IWA=(IPtr[1]>>0)&0x1F;
UINT32 TABLE=(IPtr[2]>>15)&0x01;
UINT32 MWT=(IPtr[2]>>14)&0x01;
UINT32 MRD=(IPtr[2]>>13)&0x01;
UINT32 EWT=(IPtr[2]>>12)&0x01;
UINT32 EWA=(IPtr[2]>>8)&0x0F;
UINT32 ADRL=(IPtr[2]>>7)&0x01;
UINT32 FRCL=(IPtr[2]>>6)&0x01;
UINT32 SHIFT=(IPtr[2]>>4)&0x03;
UINT32 YRL=(IPtr[2]>>3)&0x01;
UINT32 NEGB=(IPtr[2]>>2)&0x01;
UINT32 ZERO=(IPtr[2]>>1)&0x01;
UINT32 BSEL=(IPtr[2]>>0)&0x01;
UINT32 NOFL=(IPtr[3]>>15)&1; //????
UINT32 COEF=(IPtr[3]>>9)&0x3f;
UINT32 MASA=(IPtr[3]>>2)&0x1f; //???
UINT32 ADREB=(IPtr[3]>>1)&0x1;
UINT32 NXADR=(IPtr[3]>>0)&0x1;
INT64 v;
//operations are done at 24 bit precision
#if 0
if(MASA)
int a=1;
if(NOFL)
int a=1;
// int dump=0;
if(f)
{
#define DUMP(v) fprintf(f," " #v ": %04X",v);
fprintf(f,"%d: ",step);
DUMP(ACC);
DUMP(SHIFTED);
DUMP(X);
DUMP(Y);
DUMP(B);
DUMP(INPUTS);
DUMP(MEMVAL);
DUMP(FRC_REG);
DUMP(Y_REG);
DUMP(ADDR);
DUMP(ADRS_REG);
fprintf(f,"\n");
}
#endif
//INPUTS RW
assert(IRA<0x32);
if(IRA<=0x1f)
INPUTS=DSP->MEMS[IRA];
else if(IRA<=0x2F)
INPUTS=DSP->MIXS[IRA-0x20]<<4; //MIXS is 20 bit
else if(IRA<=0x31)
INPUTS=0;
INPUTS<<=8;
INPUTS>>=8;
//if(INPUTS&0x00800000)
// INPUTS|=0xFF000000;
if(IWT)
{
DSP->MEMS[IWA]=MEMVAL; //MEMVAL was selected in previous MRD
if(IRA==IWA)
INPUTS=MEMVAL;
}
//Operand sel
//B
if(!ZERO)
{
if(BSEL)
B=ACC;
else
{
B=DSP->TEMP[(TRA+DSP->DEC)&0x7F];
B<<=8;
B>>=8;
//if(B&0x00800000)
// B|=0xFF000000; //Sign extend
}
if(NEGB)
B=0-B;
}
else
B=0;
//X
if(XSEL)
X=INPUTS;
else
{
X=DSP->TEMP[(TRA+DSP->DEC)&0x7F];
X<<=8;
X>>=8;
//if(X&0x00800000)
// X|=0xFF000000;
}
//Y
if(YSEL==0)
Y=FRC_REG;
else if(YSEL==1)
Y=DSP->COEF[COEF]>>3; //COEF is 16 bits
else if(YSEL==2)
Y=(Y_REG>>11)&0x1FFF;
else if(YSEL==3)
Y=(Y_REG>>4)&0x0FFF;
if(YRL)
Y_REG=INPUTS;
//Shifter
if(SHIFT==0)
{
SHIFTED=ACC;
if(SHIFTED>0x007FFFFF)
SHIFTED=0x007FFFFF;
if(SHIFTED<(-0x00800000))
SHIFTED=-0x00800000;
}
else if(SHIFT==1)
{
SHIFTED=ACC*2;
if(SHIFTED>0x007FFFFF)
SHIFTED=0x007FFFFF;
if(SHIFTED<(-0x00800000))
SHIFTED=-0x00800000;
}
else if(SHIFT==2)
{
SHIFTED=ACC*2;
SHIFTED<<=8;
SHIFTED>>=8;
//SHIFTED&=0x00FFFFFF;
//if(SHIFTED&0x00800000)
// SHIFTED|=0xFF000000;
}
else if(SHIFT==3)
{
SHIFTED=ACC;
SHIFTED<<=8;
SHIFTED>>=8;
//SHIFTED&=0x00FFFFFF;
//if(SHIFTED&0x00800000)
// SHIFTED|=0xFF000000;
}
//ACCUM
Y<<=19;
Y>>=19;
//if(Y&0x1000)
// Y|=0xFFFFF000;
v=(((INT64) X*(INT64) Y)>>12);
ACC=(int) v+B;
if(TWT)
DSP->TEMP[(TWA+DSP->DEC)&0x7F]=SHIFTED;
if(FRCL)
{
if(SHIFT==3)
FRC_REG=SHIFTED&0x0FFF;
else
FRC_REG=(SHIFTED>>11)&0x1FFF;
}
if(MRD || MWT)
//if(0)
{
ADDR=DSP->MADRS[MASA];
if(!TABLE)
ADDR+=DSP->DEC;
if(ADREB)
ADDR+=ADRS_REG&0x0FFF;
if(NXADR)
ADDR++;
if(!TABLE)
ADDR&=DSP->RBL-1;
else
ADDR&=0xFFFF;
//ADDR<<=1;
//ADDR+=DSP->RBP<<13;
//MEMVAL=DSP->SCSPRAM[ADDR>>1];
ADDR+=DSP->RBP<<12;
if(MRD && (step&1)) //memory only allowed on odd? DoA inserts NOPs on even
{
if(NOFL)
MEMVAL=DSP->SCSPRAM[ADDR]<<8;
else
MEMVAL=UNPACK(DSP->SCSPRAM[ADDR]);
}
if(MWT && (step&1))
{
if(NOFL)
DSP->SCSPRAM[ADDR]=SHIFTED>>8;
else
DSP->SCSPRAM[ADDR]=PACK(SHIFTED);
}
}
if(ADRL)
{
if(SHIFT==3)
ADRS_REG=(SHIFTED>>12)&0xFFF;
else
ADRS_REG=(INPUTS>>16);
}
if(EWT)
DSP->EFREG[EWA]+=SHIFTED>>8;
}
--DSP->DEC;
memset(DSP->MIXS,0,4*16);
// if(f)
// fclose(f);
}
void SCSPDSP_SetSample(struct _SCSPDSP *DSP,INT32 sample,int SEL,int MXL)
{
//DSP->MIXS[SEL]+=sample<<(MXL+1)/*7*/;
DSP->MIXS[SEL]+=sample;
// if(MXL)
// int a=1;
}
void SCSPDSP_Start(struct _SCSPDSP *DSP)
{
int i;
DSP->Stopped=0;
for(i=127;i>=0;--i)
{
UINT16 *IPtr=DSP->MPRO+i*4;
if(IPtr[0]!=0 || IPtr[1]!=0 || IPtr[2]!=0 || IPtr[3]!=0)
break;
}
DSP->LastStep=i+1;
}

View file

@ -1,37 +0,0 @@
#ifndef SCSPDSP_H
#define SCSPDSP_H
//the DSP Context
struct _SCSPDSP
{
//Config
UINT16 *SCSPRAM;
UINT32 SCSPRAM_LENGTH;
UINT32 RBP; //Ring buf pointer
UINT32 RBL; //Delay ram (Ring buffer) size in words
//context
INT16 COEF[64]; //16 bit signed
UINT16 MADRS[32]; //offsets (in words), 16 bit
UINT16 MPRO[128*4]; //128 steps 64 bit
INT32 TEMP[128]; //TEMP regs,24 bit signed
INT32 MEMS[32]; //MEMS regs,24 bit signed
UINT32 DEC;
//input
INT32 MIXS[16]; //MIXS, 24 bit signed
INT16 EXTS[2]; //External inputs (CDDA) 16 bit signed
//output
INT16 EFREG[16]; //EFREG, 16 bit signed
int Stopped;
int LastStep;
};
void SCSPDSP_Init(struct _SCSPDSP *DSP);
void SCSPDSP_SetSample(struct _SCSPDSP *DSP, INT32 sample, INT32 SEL, INT32 MXL);
void SCSPDSP_Step(struct _SCSPDSP *DSP);
void SCSPDSP_Start(struct _SCSPDSP *DSP);
#endif

View file

@ -1,157 +0,0 @@
/*
SCSP LFO handling
Part of the SCSP (YMF292-F) emulator package.
(not compiled directly, #included from scsp.c)
By ElSemi
MAME/M1 conversion and cleanup by R. Belmont
*/
#define LFO_SHIFT 8
struct _LFO
{
unsigned short phase;
UINT32 phase_step;
int *table;
int *scale;
};
#define LFIX(v) ((unsigned int) ((float) (1<<LFO_SHIFT)*(v)))
//Convert DB to multiply amplitude
#define DB(v) LFIX(pow(10.0,v/20.0))
//Convert cents to step increment
#define CENTS(v) LFIX(pow(2.0,v/1200.0))
static int PLFO_TRI[256],PLFO_SQR[256],PLFO_SAW[256],PLFO_NOI[256];
static int ALFO_TRI[256],ALFO_SQR[256],ALFO_SAW[256],ALFO_NOI[256];
static float LFOFreq[32]={0.17,0.19,0.23,0.27,0.34,0.39,0.45,0.55,0.68,0.78,0.92,1.10,1.39,1.60,1.87,2.27,
2.87,3.31,3.92,4.79,6.15,7.18,8.60,10.8,14.4,17.2,21.5,28.7,43.1,57.4,86.1,172.3};
static float ASCALE[8]={0.0,0.4,0.8,1.5,3.0,6.0,12.0,24.0};
static float PSCALE[8]={0.0,7.0,13.5,27.0,55.0,112.0,230.0,494};
static int PSCALES[8][256];
static int ASCALES[8][256];
void LFO_Init(void)
{
int i,s;
for(i=0;i<256;++i)
{
int a,p;
// float TL;
//Saw
a=255-i;
if(i<128)
p=i;
else
p=i-256;
ALFO_SAW[i]=a;
PLFO_SAW[i]=p;
//Square
if(i<128)
{
a=255;
p=127;
}
else
{
a=0;
p=-128;
}
ALFO_SQR[i]=a;
PLFO_SQR[i]=p;
//Tri
if(i<128)
a=255-(i*2);
else
a=(i*2)-256;
if(i<64)
p=i*2;
else if(i<128)
p=255-i*2;
else if(i<192)
p=256-i*2;
else
p=i*2-511;
ALFO_TRI[i]=a;
PLFO_TRI[i]=p;
//noise
//a=lfo_noise[i];
a=rand()&0xff;
p=128-a;
ALFO_NOI[i]=a;
PLFO_NOI[i]=p;
}
for(s=0;s<8;++s)
{
float limit=PSCALE[s];
for(i=-128;i<128;++i)
{
PSCALES[s][i+128]=CENTS(((limit*(float) i)/128.0));
}
limit=-ASCALE[s];
for(i=0;i<256;++i)
{
ASCALES[s][i]=DB(((limit*(float) i)/256.0));
}
}
}
static signed int INLINE PLFO_Step(struct _LFO *LFO)
{
int p;
LFO->phase+=LFO->phase_step;
#if LFO_SHIFT!=8
LFO->phase&=(1<<(LFO_SHIFT+8))-1;
#endif
p=LFO->table[LFO->phase>>LFO_SHIFT];
p=LFO->scale[p+128];
return p<<(SHIFT-LFO_SHIFT);
}
static signed int INLINE ALFO_Step(struct _LFO *LFO)
{
int p;
LFO->phase+=LFO->phase_step;
#if LFO_SHIFT!=8
LFO->phase&=(1<<(LFO_SHIFT+8))-1;
#endif
p=LFO->table[LFO->phase>>LFO_SHIFT];
p=LFO->scale[p];
return p<<(SHIFT-LFO_SHIFT);
}
void LFO_ComputeStep(struct _LFO *LFO,UINT32 LFOF,UINT32 LFOWS,UINT32 LFOS,int ALFO)
{
float step=(float) LFOFreq[LFOF]*256.0/(float)44100.0;
LFO->phase_step=(unsigned int) ((float) (1<<LFO_SHIFT)*step);
if(ALFO)
{
switch(LFOWS)
{
case 0: LFO->table=ALFO_SAW; break;
case 1: LFO->table=ALFO_SQR; break;
case 2: LFO->table=ALFO_TRI; break;
case 3: LFO->table=ALFO_NOI; break;
}
LFO->scale=ASCALES[LFOS];
}
else
{
switch(LFOWS)
{
case 0: LFO->table=PLFO_SAW; break;
case 1: LFO->table=PLFO_SQR; break;
case 2: LFO->table=PLFO_TRI; break;
case 3: LFO->table=PLFO_NOI; break;
}
LFO->scale=PSCALES[LFOS];
}
}

View file

@ -1,98 +0,0 @@
/*
Audio Overload SDK
Copyright (c) 2007, R. Belmont and Richard Bannister.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ao.h"
// local variables
void (*m1sdr_Callback)(unsigned long dwNumSamples, signed short *data);
int nDSoundSegLen = 0;
static INT16 samples[44100*2];
static FILE *fout = NULL;
// set # of samples per update
void m1sdr_SetSamplesPerTick(UINT32 spf)
{
}
// m1sdr_Update - timer callback routine: runs sequencer and mixes sound
void m1sdr_Update(void)
{
if (m1sdr_Callback)
{
printf("Requesting %i\n", nDSoundSegLen);
m1sdr_Callback(nDSoundSegLen, (INT16 *)samples);
}
}
// checks the play position to see if we should trigger another update
void m1sdr_TimeCheck(void)
{
m1sdr_Update();
fwrite(samples, nDSoundSegLen*4, 1, fout);
}
// m1sdr_Init - inits the output device and our global state
INT16 m1sdr_Init(int sample_rate)
{
nDSoundSegLen = 350; // ;sample_rate/60;
memset(samples, 0, 44100*4); // zero out samples
m1sdr_Callback = NULL;
fout = fopen("output.raw", "wb");
}
void m1sdr_Exit(void)
{
fclose(fout);
}
void m1sdr_SetCallback(void *fn)
{
if (fn == (void *)NULL)
{
printf("ERROR: NULL CALLBACK!\n");
}
// printf("m1sdr_SetCallback: aok!\n");
m1sdr_Callback = (void (*)(unsigned long, signed short *))fn;
}
void m1sdr_PlayStart(void)
{
}

View file

@ -1,236 +0,0 @@
Here is a list of the licenses each file in this package are under, and their text.
The upshot is this: if you create anything from this SDK and include any MAME licensed components
(which are an integral part of each engine supplied) you must distribute the source code to your
derivative program.
=====================================================================================
BSD license:
Copyright (c) 2007-2009, R. Belmont and Richard Bannister.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=====================================================================================
MAME license:
Copyright (c) 1997-2008, Nicola Salmoria and the MAME team
All rights reserved.
Redistribution and use of this code or any derivative works are permitted provided that the following conditions are met:
* Redistributions may not be sold, nor may they be used in a commercial product or activity.
* Redistributions that are modified from the original source must include the complete source code, including the source code for all components used by a binary built from the modified sources. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
* Redistributions must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=====================================================================================
GPL license:
Too long to include here.
See eng_psf/peops/License.txt or eng_psf/peops2/License.txt for the complete text.
While legally combining GPL with BSD and MAME licensed software is unclear, Pete Bernert
will probably be OK with anything you do as long as you distribute the source for your
AOSDK based creations.
=====================================================================================
ZLIB license:
/* zlib.h -- interface of the 'zlib' general purpose compression library
version 1.2.2, October 3rd, 2004
Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jean-loup Gailly jloup@gzip.org
Mark Adler madler@alumni.caltech.edu
*/
=====================================================================================
List of files and their licenses:
ao.h BSD
corlett.c BSD
corlett.h BSD
cpuintrf.h BSD
dsnd.c BSD
eng_protos.h BSD
main.c BSD
Makefile BSD
mem.h BSD
osd_cpu.h MAME
oss.c BSD
oss.h BSD
eng_dsf:
aica.c MAME
aica.h MAME
aicadsp.c MAME
aicadsp.h MAME
aicalfo.c MAME
arm7.c MAME
arm7.h MAME
arm7i.c MAME
arm7i.h MAME
arm7memil.c MAME
eng_dsf.c BSD
dc_hw.c BSD
dc_hw.h BSD
eng_qsf:
eng_qsf.c BSD
kabuki.c MAME
qsound.c MAME
qsound.h MAME
z80.c MAME
z80dasm.c MAME
z80dasm.h MAME
z80.h MAME
eng_ssf:
eng_ssf.c BSD
m68kconf.h MAME
m68kcpu.c MAME
m68kcpu.h MAME
m68k.h MAME
m68k_in.c MAME
m68kmake.c MAME
m68kmame.h MAME
m68kopac.c MAME
m68kopdm.c MAME
m68kopnz.c MAME
m68kops.c MAME
m68kops.h MAME
sat_hw.c BSD
sat_hw.h BSD
scsp.c MAME
scspdsp.c MAME
scspdsp.h MAME
scsp.h MAME
scsplfo.c MAME
eng_psf:
eng_psf2.c BSD
eng_psf.c BSD
eng_spu.c BSD
psx_hw.c BSD
psx.c MAME
psx.h MAME
cpuintrf.h MAME
mamemem.h MAME
eng_psf/peops:
adsr.c GPL
adsr.h GPL
dma.c GPL
dma.h GPL
externals.h GPL
gauss_i.h GPL
registers.c GPL
registers.h GPL
regs.h GPL
reverb.c GPL
spu.c GPL
spu.h GPL
stdafx.h GPL
eng_psf/peops2:
adsr.c GPL
adsr.h GPL
dma.c GPL
dma.h GPL
externals.h GPL
gauss_i.h GPL
psemuxa.h GPL
registers.c GPL
registers.h GPL
regs.h GPL
reverb.c GPL
reverb.h GPL
spu.c GPL
spu.h GPL
stdafx.h GPL
xa.c GPL
zlib:
adler32.c ZLIB
compress.c ZLIB
crc32.c ZLIB
crc32.h ZLIB
crypt.h ZLIB
deflate.c ZLIB
deflate.h ZLIB
gzio.c ZLIB
infback.c ZLIB
inffast.c ZLIB
inffast.h ZLIB
inffixed.h ZLIB
inflate.c ZLIB
inflate.h ZLIB
inftrees.c ZLIB
inftrees.h ZLIB
ioapi.c ZLIB
ioapi.h ZLIB
trees.c ZLIB
trees.h ZLIB
uncompr.c ZLIB
unzip.c ZLIB
unzip.h ZLIB
zconf.h ZLIB
zlib.h ZLIB
zutil.c ZLIB
zutil.h ZLIB

View file

@ -1,195 +0,0 @@
/*
Audio Overload SDK - main driver. for demonstration only, not user friendly!
Copyright (c) 2007-2009 R. Belmont and Richard Bannister.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ao.h"
#include "eng_protos.h"
/* file types */
static uint32 type;
static struct
{
uint32 sig;
char *name;
int32 (*start)(uint8 *, uint32);
int32 (*gen)(int16 *, uint32);
int32 (*stop)(void);
int32 (*command)(int32, int32);
uint32 rate;
int32 (*fillinfo)(ao_display_info *);
} types[] = {
{ 0x50534641, "Capcom QSound (.qsf)", qsf_start, qsf_gen, qsf_stop, qsf_command, 60, qsf_fill_info },
{ 0x50534611, "Sega Saturn (.ssf)", ssf_start, ssf_gen, ssf_stop, ssf_command, 60, ssf_fill_info },
{ 0x50534601, "Sony PlayStation (.psf)", psf_start, psf_gen, psf_stop, psf_command, 60, psf_fill_info },
{ 0x53505500, "Sony PlayStation (.spu)", spu_start, spu_gen, spu_stop, spu_command, 60, spu_fill_info },
{ 0x50534602, "Sony PlayStation 2 (.psf2)", psf2_start, psf2_gen, psf2_stop, psf2_command, 60, psf2_fill_info },
{ 0x50534612, "Sega Dreamcast (.dsf)", dsf_start, dsf_gen, dsf_stop, dsf_command, 60, dsf_fill_info },
{ 0xffffffff, "", NULL, NULL, NULL, NULL, 0, NULL }
};
/* redirect stubs to interface the Z80 core to the QSF engine */
uint8 memory_read(uint16 addr)
{
return qsf_memory_read(addr);
}
uint8 memory_readop(uint16 addr)
{
return memory_read(addr);
}
uint8 memory_readport(uint16 addr)
{
return qsf_memory_readport(addr);
}
void memory_write(uint16 addr, uint8 byte)
{
qsf_memory_write(addr, byte);
}
void memory_writeport(uint16 addr, uint8 byte)
{
qsf_memory_writeport(addr, byte);
}
static int (*ao_get_lib_callback)(char *filename, uint8 **buffer, uint64 *length) = NULL;
// ao_get_lib: called to load secondary files
int ao_get_lib(char *filename, uint8 **buffer, uint64 *length)
{
return (*ao_get_lib_callback)(filename, buffer, length);
}
void ao_set_get_lib_callback(int (*callback)(char *filename, uint8 **buffer, uint64 *length)) {
ao_get_lib_callback = callback;
}
/*
int main(int argv, char *argc[])
{
FILE *file;
uint8 *buffer;
uint32 size, filesig;
printf("AOSDK test program v1.0 by R. Belmont [AOSDK release 1.4.8]\nCopyright (c) 2007-2009 R. Belmont and Richard Bannister - please read license.txt for license details\n\n");
// check if an argument was given
if (argv < 2)
{
printf("Error: must specify a filename!\n");
return -1;
}
file = fopen(argc[1], "rb");
if (!file)
{
printf("ERROR: could not open file %s\n", argc[1]);
return -1;
}
// get the length of the file by seeking to the end then reading the current position
fseek(file, 0, SEEK_END);
size = ftell(file);
// reset the pointer
fseek(file, 0, SEEK_SET);
buffer = malloc(size);
if (!buffer)
{
fclose(file);
printf("ERROR: could not allocate %d bytes of memory\n", size);
return -1;
}
// read the file
fread(buffer, size, 1, file);
fclose(file);
// now try to identify the file
type = 0;
filesig = buffer[0]<<24 | buffer[1]<<16 | buffer[2]<<8 | buffer[3];
while (types[type].sig != 0xffffffff)
{
if (filesig == types[type].sig)
{
break;
}
else
{
type++;
}
}
// now did we identify it above or just fall through?
if (types[type].sig != 0xffffffff)
{
printf("File identified as %s\n", types[type].name);
}
else
{
printf("ERROR: File is unknown, signature bytes are %02x %02x %02x %02x\n", buffer[0], buffer[1], buffer[2], buffer[3]);
free(buffer);
return -1;
}
if ((*types[type].start)(buffer, size) != AO_SUCCESS)
{
free(buffer);
printf("ERROR: Engine rejected file!\n");
return -1;
}
m1sdr_Init(44100);
m1sdr_SetCallback(do_frame);
m1sdr_PlayStart();
printf("\n\nPlaying. Press CTRL-C to stop.\n");
while (1)
{
m1sdr_TimeCheck();
}
free(buffer);
return 1;
}
*/
// stub for MAME stuff
int change_pc(int foo)
{
}

View file

@ -1,220 +0,0 @@
/*
Audio Overload SDK - main driver. for demonstration only, not user friendly!
Copyright (c) 2007-2009 R. Belmont and Richard Bannister.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ao.h"
#include "eng_protos.h"
/* file types */
static uint32 type;
static struct
{
uint32 sig;
char *name;
int32 (*start)(uint8 *, uint32);
int32 (*gen)(int16 *, uint32);
int32 (*stop)(void);
int32 (*command)(int32, int32);
uint32 rate;
int32 (*fillinfo)(ao_display_info *);
} types[] = {
{ 0x50534641, "Capcom QSound (.qsf)", qsf_start, qsf_gen, qsf_stop, qsf_command, 60, qsf_fill_info },
{ 0x50534611, "Sega Saturn (.ssf)", ssf_start, ssf_gen, ssf_stop, ssf_command, 60, ssf_fill_info },
{ 0x50534601, "Sony PlayStation (.psf)", psf_start, psf_gen, psf_stop, psf_command, 60, psf_fill_info },
{ 0x53505500, "Sony PlayStation (.spu)", spu_start, spu_gen, spu_stop, spu_command, 60, spu_fill_info },
{ 0x50534602, "Sony PlayStation 2 (.psf2)", psf2_start, psf2_gen, psf2_stop, psf2_command, 60, psf2_fill_info },
{ 0x50534612, "Sega Dreamcast (.dsf)", dsf_start, dsf_gen, dsf_stop, dsf_command, 60, dsf_fill_info },
{ 0xffffffff, "", NULL, NULL, NULL, NULL, 0, NULL }
};
/* redirect stubs to interface the Z80 core to the QSF engine */
uint8 memory_read(uint16 addr)
{
return qsf_memory_read(addr);
}
uint8 memory_readop(uint16 addr)
{
return memory_read(addr);
}
uint8 memory_readport(uint16 addr)
{
return qsf_memory_readport(addr);
}
void memory_write(uint16 addr, uint8 byte)
{
qsf_memory_write(addr, byte);
}
void memory_writeport(uint16 addr, uint8 byte)
{
qsf_memory_writeport(addr, byte);
}
/* ao_get_lib: called to load secondary files */
int ao_get_lib(char *filename, uint8 **buffer, uint64 *length)
{
uint8 *filebuf;
uint32 size;
FILE *auxfile;
auxfile = fopen(filename, "rb");
if (!auxfile)
{
printf("Unable to find auxiliary file %s\n", filename);
return AO_FAIL;
}
fseek(auxfile, 0, SEEK_END);
size = ftell(auxfile);
fseek(auxfile, 0, SEEK_SET);
filebuf = malloc(size);
if (!filebuf)
{
fclose(auxfile);
printf("ERROR: could not allocate %d bytes of memory\n", size);
return AO_FAIL;
}
fread(filebuf, size, 1, auxfile);
fclose(auxfile);
*buffer = filebuf;
*length = (uint64)size;
return AO_SUCCESS;
}
static void do_frame(uint32 size, int16 *buffer)
{
(*types[type].gen)(buffer, size);
}
int main(int argv, char *argc[])
{
FILE *file;
uint8 *buffer;
uint32 size, filesig;
printf("AOSDK test program v1.0 by R. Belmont [AOSDK release 1.4.8]\nCopyright (c) 2007-2009 R. Belmont and Richard Bannister - please read license.txt for license details\n\n");
// check if an argument was given
if (argv < 2)
{
printf("Error: must specify a filename!\n");
return -1;
}
file = fopen(argc[1], "rb");
if (!file)
{
printf("ERROR: could not open file %s\n", argc[1]);
return -1;
}
// get the length of the file by seeking to the end then reading the current position
fseek(file, 0, SEEK_END);
size = ftell(file);
// reset the pointer
fseek(file, 0, SEEK_SET);
buffer = malloc(size);
if (!buffer)
{
fclose(file);
printf("ERROR: could not allocate %d bytes of memory\n", size);
return -1;
}
// read the file
fread(buffer, size, 1, file);
fclose(file);
// now try to identify the file
type = 0;
filesig = buffer[0]<<24 | buffer[1]<<16 | buffer[2]<<8 | buffer[3];
while (types[type].sig != 0xffffffff)
{
if (filesig == types[type].sig)
{
break;
}
else
{
type++;
}
}
// now did we identify it above or just fall through?
if (types[type].sig != 0xffffffff)
{
printf("File identified as %s\n", types[type].name);
}
else
{
printf("ERROR: File is unknown, signature bytes are %02x %02x %02x %02x\n", buffer[0], buffer[1], buffer[2], buffer[3]);
free(buffer);
return -1;
}
if ((*types[type].start)(buffer, size) != AO_SUCCESS)
{
free(buffer);
printf("ERROR: Engine rejected file!\n");
return -1;
}
m1sdr_Init(44100);
m1sdr_SetCallback(do_frame);
m1sdr_PlayStart();
printf("\n\nPlaying. Press CTRL-C to stop.\n");
while (1)
{
m1sdr_TimeCheck();
}
free(buffer);
return 1;
}
// stub for MAME stuff
int change_pc(int foo)
{
}

View file

@ -1,22 +0,0 @@
//
// Audio Overload
// Emulated music player
//
// (C) 2000-2008 Richard F. Bannister
//
// mem.h
uint8 memory_read(uint16 addr);
uint8 memory_readop(uint16 addr);
uint8 memory_readport(uint16 addr);
void memory_write(uint16 addr, uint8 byte);
void memory_writeport(uint16 addr, uint8 byte);
uint8 dc_read8(uint32 addr);
uint16 dc_read16(uint32 addr);
uint32 dc_read32(uint32 addr);
void dc_write8(uint32 addr, uint8 byte);
void dc_write16(uint32 addr, uint16 word);
void dc_write32(uint32 addr, uint32 dword);

View file

@ -1,70 +0,0 @@
/*******************************************************************************
* *
* Define size independent data types and operations. *
* *
* The following types must be supported by all platforms: *
* *
* UINT8 - Unsigned 8-bit Integer INT8 - Signed 8-bit integer *
* UINT16 - Unsigned 16-bit Integer INT16 - Signed 16-bit integer *
* UINT32 - Unsigned 32-bit Integer INT32 - Signed 32-bit integer *
* UINT64 - Unsigned 64-bit Integer INT64 - Signed 64-bit integer *
* *
* *
* The macro names for the artithmatic operations are composed as follows: *
* *
* XXX_R_A_B, where XXX - 3 letter operation code (ADD, SUB, etc.) *
* R - The type of the result *
* A - The type of operand 1 *
* B - The type of operand 2 (if binary operation) *
* *
* Each type is one of: U8,8,U16,16,U32,32,U64,64 *
* *
*******************************************************************************/
#ifndef OSD_CPU_H
#define OSD_CPU_H
#include "ao.h"
/* Combine two 32-bit integers into a 64-bit integer */
#define COMBINE_64_32_32(A,B) ((((UINT64)(A))<<32) | (UINT32)(B))
#define COMBINE_U64_U32_U32(A,B) COMBINE_64_32_32(A,B)
/* Return upper 32 bits of a 64-bit integer */
#define HI32_32_64(A) (((UINT64)(A)) >> 32)
#define HI32_U32_U64(A) HI32_32_64(A)
/* Return lower 32 bits of a 64-bit integer */
#define LO32_32_64(A) ((A) & 0xffffffff)
#define LO32_U32_U64(A) LO32_32_64(A)
#define DIV_64_64_32(A,B) ((A)/(B))
#define DIV_U64_U64_U32(A,B) ((A)/(UINT32)(B))
#define MOD_32_64_32(A,B) ((A)%(B))
#define MOD_U32_U64_U32(A,B) ((A)%(UINT32)(B))
#define MUL_64_32_32(A,B) ((A)*(INT64)(B))
#define MUL_U64_U32_U32(A,B) ((A)*(UINT64)(UINT32)(B))
/******************************************************************************
* Union of UINT8, UINT16 and UINT32 in native endianess of the target
* This is used to access bytes and words in a machine independent manner.
* The upper bytes h2 and h3 normally contain zero (16 bit CPU cores)
* thus PAIR.d can be used to pass arguments to the memory system
* which expects 'int' really.
******************************************************************************/
typedef union {
#if LSB_FIRST
struct { UINT8 l,h,h2,h3; } b;
struct { UINT16 l,h; } w;
#else
struct { UINT8 h3,h2,h,l; } b;
struct { UINT16 h,l; } w;
#endif
UINT32 d;
} PAIR;
#endif /* defined OSD_CPU_H */

View file

@ -1,290 +0,0 @@
/*
Audio Overload SDK
Copyright (c) 2007, R. Belmont and Richard Bannister.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include "ao.h"
#include "oss.h"
#define LOG_WAVE (0)
#define VALGRIND (0)
#define NUM_FRAGS_BROKEN (8)
#define NUM_FRAGS_NORMAL (4)
static INT32 num_frags;
#define OSS_FRAGMENT (0x000D | (num_frags<<16)); // 16k fragments (2 * 2^14).
// local variables
void (*m1sdr_Callback)(unsigned long dwNumSamples, signed short *data);
unsigned long cbUserData;
static int hw_present;
static INT32 is_broken_driver;
int nDSoundSegLen = 0;
int oss_nw = 0;
int audiofd;
#if LOG_WAVE
FILE *logfil;
#endif
static int playtime = 0;
static INT16 samples[44100*2];
// set # of samples per update
void m1sdr_SetSamplesPerTick(UINT32 spf)
{
nDSoundSegLen = spf;
}
// m1sdr_Update - timer callback routine: runs sequencer and mixes sound
void m1sdr_Update(void)
{
if (!hw_present) return;
if (m1sdr_Callback)
{
m1sdr_Callback(nDSoundSegLen, (INT16 *)samples);
}
}
// checks the play position to see if we should trigger another update
void m1sdr_TimeCheck(void)
{
#if VALGRIND
m1sdr_Update();
#else
audio_buf_info info;
ioctl(audiofd, SNDCTL_DSP_GETOSPACE, &info);
if (oss_nw)
{
int err;
m1sdr_Update();
playtime++;
// output the generated samples
err = write(audiofd, samples, nDSoundSegLen * 4);
if (err == -1)
{
perror("write\n");
}
#if LOG_WAVE
fwrite(samples, nDSoundSegLen*4, 1, logfil);
#endif
}
else
{
while (info.bytes >= (nDSoundSegLen * 4))
{
m1sdr_Update();
playtime++;
// output the generated samples
write(audiofd, samples, nDSoundSegLen * 4);
#if LOG_WAVE
fwrite(samples, nDSoundSegLen*4, 1, logfil);
#endif
ioctl(audiofd, SNDCTL_DSP_GETOSPACE, &info);
}
}
usleep(50);
#endif
}
// m1sdr_Init - inits the output device and our global state
INT16 m1sdr_Init(int sample_rate)
{
int format, stereo, rate, fsize;
hw_present = 0;
nDSoundSegLen = sample_rate / 60;
memset(samples, 0, 44100*4); // zero out samples
m1sdr_Callback = NULL;
audiofd = open("/dev/dsp", O_WRONLY, 0);
if (audiofd == -1)
{
perror("/dev/dsp");
audiofd = open("/dev/dsp1", O_WRONLY, 0);
if (audiofd == -1)
{
perror("/dev/dsp1");
return(0);
}
}
// reset things
ioctl(audiofd, SNDCTL_DSP_RESET, 0);
is_broken_driver = 0;
num_frags = NUM_FRAGS_NORMAL;
// set the buffer size we want
fsize = OSS_FRAGMENT;
if (ioctl(audiofd, SNDCTL_DSP_SETFRAGMENT, &fsize) == - 1)
{
perror("SNDCTL_DSP_SETFRAGMENT");
return(0);
}
// set 16-bit output
format = AFMT_S16_NE; // 16 bit signed "native"-endian
if (ioctl(audiofd, SNDCTL_DSP_SETFMT, &format) == - 1)
{
perror("SNDCTL_DSP_SETFMT");
return(0);
}
// now set stereo
stereo = 1;
if (ioctl(audiofd, SNDCTL_DSP_STEREO, &stereo) == - 1)
{
perror("SNDCTL_DSP_STEREO");
return(0);
}
// and the sample rate
rate = sample_rate;
if (ioctl(audiofd, SNDCTL_DSP_SPEED, &rate) == - 1)
{
perror("SNDCTL_DSP_SPEED");
return(0);
}
// and make sure that did what we wanted
ioctl(audiofd, SNDCTL_DSP_GETBLKSIZE, &fsize);
//printf("Fragment size: %d\n", fsize);
hw_present = 1;
#if LOG_WAVE
logfil = fopen("log.bin", "wb");
#endif
return (1);
}
void m1sdr_Exit(void)
{
if (!hw_present) return;
close(audiofd);
#if LOG_WAVE
fclose(logfil);
#endif
}
void m1sdr_SetCallback(void *fn)
{
if (fn == (void *)NULL)
{
printf("ERROR: NULL CALLBACK!\n");
}
// printf("m1sdr_SetCallback: aok!\n");
m1sdr_Callback = (void (*)(unsigned long, signed short *))fn;
}
INT16 m1sdr_IsThere(void)
{
audiofd = open("/dev/dsp", O_WRONLY, 0);
if (audiofd == -1)
{
printf("Error accessing soundcard, sound will be disabled\n");
hw_present = 0;
return(0);
}
close(audiofd);
hw_present = 1;
return (1);
}
INT32 m1sdr_HwPresent(void)
{
return hw_present;
}
// unused stubs for this driver, but the Win32 driver needs them
void m1sdr_PlayStart(void)
{
playtime = 0;
}
void m1sdr_PlayStop(void)
{
}
void m1sdr_FlushAudio(void)
{
memset(samples, 0, nDSoundSegLen * 4);
write(audiofd, samples, nDSoundSegLen * 4);
write(audiofd, samples, nDSoundSegLen * 4);
}
void m1sdr_SetNoWait(int nw)
{
oss_nw = nw;
}
short *m1sdr_GetSamples(void)
{
return samples;
}
int m1sdr_GetPlayTime(void)
{
return playtime;
}

View file

@ -1,27 +0,0 @@
#ifndef _OSS_H_
#define _OSS_H_
extern int audiofd;
extern void (*m1sdr_Callback)(unsigned long dwUser, signed short *smp);
extern unsigned long cbUserData;
// function protos
void m1sdr_Update(void);
INT16 m1sdr_Init(int sample_rate);
void m1sdr_Exit(void);
void m1sdr_PlayStart(void);
void m1sdr_PlayStop(void);
INT16 m1sdr_IsThere(void);
void m1sdr_TimeCheck(void);
void m1sdr_SetSamplesPerTick(UINT32 spf);
void m1sdr_SetHz(UINT32 hz);
void m1sdr_SetCallback(void *fn);
void m1sdr_SetCPUHog(int hog);
INT32 m1sdr_HwPresent(void);
void m1sdr_FlushAudio(void);
void m1sdr_Pause(int);
void m1sdr_SetNoWait(int nw);
short *m1sdr_GetSamples(void);
int m1sdr_GetPlayTime(void);
#endif

View file

@ -1,81 +0,0 @@
Audio Overload SDK - Development Release 1.4.8 February 15, 2009
Copyright (c) 2007-2009 R. Belmont and Richard Bannister.
All rights reserved.
=========================================================
Please refer to license.txt for the specific licensing details of this software.
This SDK opens up some of the music file format engines developed for the Audio Overload project.
You may use this code to play the formats on systems we don't support or inside of applications
other than AO.
Configurables in the makefile:
- Uncomment the line that defines LONG_IS_64BIT for compilation on 64-bit Linux, *BSD, and other operating
systems using the AMD64 recommended ABI (not 64-bit Windows).
- Change LSB_FIRST=1 to =0 for big-endian platforms.
New in Release 1.4.8
- Guard against invalid data sometimes created by makessf.py (fixes crashing Pebble Beach ST-V rips)
Entry points of an AO engine are as follows:
int32 XXX_start(uint8 *, uint32)
This function attempts to recognize and load a file of a specific type. It is assumed external code has
already checked the file's signature in cases where that's possible. The first parameter is a pointer to
the entire file in memory, and the second is the length of the file. The return value is AO_SUCCESS if
the engine properly loaded the file and AO_FAIL if it didn't.
int32 XXX_gen(int16 *, uint32)
This function actually plays the song and generates signed 16-bit stereo samples at 44100 Hz. The first
parameter is a pointer to a buffer in which to place the samples (stereo interleaved), and the second is
the number of stereo samples to generate (so the output buffer size must be (number of samples) * 2 * 2
bytes in length).
int32 XXX_stop(void)
This function ceases playback and cleans up the engine. You must call _start again after this to play more
music.
int32 XXX_command(int32, int32)
For some engines, this allows you to send commands while a song is playing. The first parameter is the
command (these are defined in ao.h), the second is the parameter. These commands are as follows:
COMMAND_PREV (parameter ignored) - for file formats which have more than one song in a file (NSF), this
moves back one song.
COMMAND_NEXT (parameter ignored) - for file formats which have more than one song in a file (NSF), this
moves forward one song.
COMMAND_RESTART (parameter ignored) - Restarts the current song from the beginning. Not supported by
all engines.
COMMAND_HAS_PREV (parameter ignored) - for file formats which have more than one song in a file (NSF),
this checks if moving backwards from the current song is a valid operation. (Returns AO_FAIL if not)
COMMAND_HAS_NEXT (parameter ignored) - for file formats which have more than one song in a file (NSF),
this checks if moving forward from the current song is a valid operation. (Returns AO_FAIL if not)
COMMAND_GET_MIN (parameter ignored) - for file formats which have more than one song in a file (NSF),
this returns the lowest valid song number.
COMMAND_GET_MAX (parameter ignored) - for file formats which have more than one song in a file (NSF),
this returns the highest valid song number.
COMAND_JUMP - for file formats which have more than one song in a file (NSF), this command jumps directly
to a specific song number, which is passed in as the parameter.
int32 XXX_fillinfo(ao_display_info *)
This function fills out the ao_display_info struct (see ao.h for details) with information about the currently
playing song. The information provided varies by engine.

View file

@ -7,7 +7,7 @@
<key>Dumb Framework.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>10</integer>
<integer>7</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>

Some files were not shown because too many files have changed in this diff Show more