Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ebcb35c783 | |||
| 74a023675d | |||
| d0a5ab88d8 | |||
| bb87a68e59 | |||
| 9228bbea43 | |||
| 56420c3a12 | |||
| 1742f0be53 | |||
| 408b2d3c10 | |||
| d2ed27ffca | |||
| 63968244dd | |||
| 9d16f5ef1e | |||
| 1660bd3992 | |||
| 6b71d9c58c | |||
| 5a02e16589 | |||
| c5b4b1166d | |||
| c5efc99e31 | |||
| 76e280cf65 | |||
| 8712f18b46 | |||
| 7dabdd6fbd | |||
| e30fdfec8e | |||
| 2ed73c7f79 | |||
| 0fb71b683b | |||
| e6d22582c7 | |||
| ec17ea864f | |||
| 0010a37c60 | |||
| ec2a8c68e5 | |||
| 8518f32fbb | |||
| cd21ca7a04 | |||
| 3dd30d8179 | |||
| 64ce7e6606 | |||
| bb6ea11c53 | |||
| f7a91239b3 | |||
| 329dddbb3d | |||
| 7dfdd52961 | |||
| c159d4ba46 | |||
| fccfcdca60 | |||
| b816c248d9 | |||
| 178157a03c | |||
| 8ba23f87d1 | |||
| 2413579323 | |||
| 99a2f187bd | |||
| 25b74d66c9 | |||
| 6125b75ff5 | |||
| 173fce5d24 | |||
| bde73deee5 | |||
| 561a47efe1 | |||
| 366bb1c4a9 | |||
| 96b4606d7b |
Binary file not shown.
+17
-7
@@ -3,13 +3,13 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.openemu.${PRODUCT_NAME:identifier}</string>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
@@ -17,13 +17,25 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.3</string>
|
||||
<string>1.4.2</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>OEGameCoreController</string>
|
||||
<key>OEGameCoreClass</key>
|
||||
<string>ProSystemGameCore</string>
|
||||
<key>OEGameCoreOptions</key>
|
||||
<dict>
|
||||
<key>openemu.system.7800</key>
|
||||
<dict>
|
||||
<key>OEGameCoreRewindBufferSeconds</key>
|
||||
<integer>60</integer>
|
||||
<key>OEGameCoreRewindInterval</key>
|
||||
<integer>0</integer>
|
||||
<key>OEGameCoreSupportsRewinding</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>OEGameCorePlayerCount</key>
|
||||
<string>1</string>
|
||||
<string>2</string>
|
||||
<key>OEProjectURL</key>
|
||||
<string>http://home.comcast.net/~gscottstanton/</string>
|
||||
<key>OESystemIdentifiers</key>
|
||||
@@ -33,8 +45,6 @@
|
||||
<key>SUEnableAutomaticChecks</key>
|
||||
<string>1</string>
|
||||
<key>SUFeedURL</key>
|
||||
<string>http://openemu.org/updater/prosystem_appcast.xml</string>
|
||||
<key>SUPublicDSAKeyFile</key>
|
||||
<string>dsa_pub.pem</string>
|
||||
<string>https://raw.github.com/OpenEmu/OpenEmu-Update/master/prosystem_appcast.xml</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
Executable → Regular
+1725
-40
File diff suppressed because it is too large
Load Diff
@@ -35,9 +35,9 @@
|
||||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
82CAFD020FEDD54000CCDC7E /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = 82CAFD010FEDD54000CCDC7E /* dsa_pub.pem */; };
|
||||
82CAFD1E0FEDD5B300CCDC7E /* config.yaml in CopyFiles */ = {isa = PBXBuildFile; fileRef = 82CAFD030FEDD54800CCDC7E /* config.yaml */; };
|
||||
82EC409F0FD9EC420017FC19 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 82EC409E0FD9EC420017FC19 /* libz.dylib */; };
|
||||
871EC9A224F08BF700CEC578 /* ExpansionModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 871EC9A124F08BF600CEC578 /* ExpansionModule.cpp */; };
|
||||
8794D9691B74713300897F57 /* Sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 941F59AF17A6189D0005D7EA /* Sound.cpp */; };
|
||||
8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };
|
||||
8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; };
|
||||
941DFB2715B6425200C6552F /* ProSystemGameCore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 941DFB2615B6425200C6552F /* ProSystemGameCore.mm */; };
|
||||
@@ -88,20 +88,19 @@
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
82CAFD1E0FEDD5B300CCDC7E /* config.yaml in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
|
||||
089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
|
||||
1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
|
||||
82CAFD010FEDD54000CCDC7E /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dsa_pub.pem; sourceTree = "<group>"; };
|
||||
82CAFD030FEDD54800CCDC7E /* config.yaml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = config.yaml; sourceTree = "<group>"; };
|
||||
089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
089C167EFE841241C02AAC07 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
|
||||
1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
82EC409E0FD9EC420017FC19 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
|
||||
871EC9A024F08BF600CEC578 /* ExpansionModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExpansionModule.h; sourceTree = "<group>"; };
|
||||
871EC9A124F08BF600CEC578 /* ExpansionModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExpansionModule.cpp; sourceTree = "<group>"; };
|
||||
8D5B49B6048680CD000E48DA /* ProSystem.oecoreplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ProSystem.oecoreplugin; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
941DFB2615B6425200C6552F /* ProSystemGameCore.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ProSystemGameCore.mm; sourceTree = "<group>"; };
|
||||
@@ -161,38 +160,11 @@
|
||||
941F59BB17A6189D0005D7EA /* Zconf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Zconf.h; sourceTree = "<group>"; };
|
||||
941F59BC17A6189D0005D7EA /* Zip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Zip.h; sourceTree = "<group>"; };
|
||||
941F59BD17A6189D0005D7EA /* Zlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Zlib.h; sourceTree = "<group>"; };
|
||||
941F59DB17A62ADD0005D7EA /* OpenEmuBase.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenEmuBase.framework; path = "../../Library/Developer/Xcode/DerivedData/OpenEmu-dsehantrxgyfywdpbneyslftzzvv/Build/Products/Debug/OpenEmuBase.framework"; sourceTree = "<group>"; };
|
||||
941F59E017A630990005D7EA /* About.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = About.cpp; sourceTree = "<group>"; };
|
||||
941F59E117A630990005D7EA /* About.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = About.h; sourceTree = "<group>"; };
|
||||
941F59E217A630990005D7EA /* Common.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Common.cpp; sourceTree = "<group>"; };
|
||||
941F59E317A630990005D7EA /* Common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Common.h; sourceTree = "<group>"; };
|
||||
941F59E417A630990005D7EA /* Configuration.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Configuration.cpp; sourceTree = "<group>"; };
|
||||
941F59E517A630990005D7EA /* Configuration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Configuration.h; sourceTree = "<group>"; };
|
||||
941F59E617A630990005D7EA /* Console.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Console.cpp; sourceTree = "<group>"; };
|
||||
941F59E717A630990005D7EA /* Console.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Console.h; sourceTree = "<group>"; };
|
||||
941F59E817A630990005D7EA /* Database.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Database.cpp; sourceTree = "<group>"; };
|
||||
941F59E917A630990005D7EA /* Database.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Database.h; sourceTree = "<group>"; };
|
||||
941F59EA17A630990005D7EA /* Display.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Display.cpp; sourceTree = "<group>"; };
|
||||
941F59EB17A630990005D7EA /* Display.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Display.h; sourceTree = "<group>"; };
|
||||
941F59EC17A630990005D7EA /* Help.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Help.cpp; sourceTree = "<group>"; };
|
||||
941F59ED17A630990005D7EA /* Help.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Help.h; sourceTree = "<group>"; };
|
||||
941F59EE17A630990005D7EA /* Input.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Input.cpp; sourceTree = "<group>"; };
|
||||
941F59EF17A630990005D7EA /* Input.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Input.h; sourceTree = "<group>"; };
|
||||
941F59F017A630990005D7EA /* Main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Main.cpp; sourceTree = "<group>"; };
|
||||
941F59F117A630990005D7EA /* Menu.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Menu.cpp; sourceTree = "<group>"; };
|
||||
941F59F217A630990005D7EA /* Menu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Menu.h; sourceTree = "<group>"; };
|
||||
941F59F317A630990005D7EA /* ProSystem.aps */ = {isa = PBXFileReference; lastKnownFileType = file; path = ProSystem.aps; sourceTree = "<group>"; };
|
||||
941F59F417A630990005D7EA /* ProSystem.ico */ = {isa = PBXFileReference; lastKnownFileType = image.ico; path = ProSystem.ico; sourceTree = "<group>"; };
|
||||
941F59F517A630990005D7EA /* ProSystem.rc */ = {isa = PBXFileReference; lastKnownFileType = text; path = ProSystem.rc; sourceTree = "<group>"; };
|
||||
941F59F617A630990005D7EA /* resource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = resource.h; sourceTree = "<group>"; };
|
||||
941F59F717A630990005D7EA /* Sound.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Sound.cpp; sourceTree = "<group>"; };
|
||||
941F59F817A630990005D7EA /* Sound.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Sound.h; sourceTree = "<group>"; };
|
||||
941F59F917A630990005D7EA /* Timer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Timer.cpp; sourceTree = "<group>"; };
|
||||
941F59FA17A630990005D7EA /* Timer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Timer.h; sourceTree = "<group>"; };
|
||||
941F59DB17A62ADD0005D7EA /* OpenEmuBase.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = OpenEmuBase.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
941F59FB17A77CC90005D7EA /* ProSystem.dat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ProSystem.dat; sourceTree = SOURCE_ROOT; };
|
||||
941F5A2617A78FF20005D7EA /* OE7800SystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OE7800SystemResponderClient.h; path = "../OpenEmu/Atari 7800/OE7800SystemResponderClient.h"; sourceTree = "<group>"; };
|
||||
941F5A2617A78FF20005D7EA /* OE7800SystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OE7800SystemResponderClient.h; path = "../OpenEmu/SystemPlugins/Atari 7800/OE7800SystemResponderClient.h"; sourceTree = "<group>"; };
|
||||
B5008DAD0E8BFB3E005AECAF /* ProSystemGameCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProSystemGameCore.h; sourceTree = "<group>"; };
|
||||
D2F7E65807B2D6F200F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
|
||||
D2F7E65807B2D6F200F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -221,6 +193,7 @@
|
||||
);
|
||||
name = VisualBoyAdvance;
|
||||
sourceTree = "<group>";
|
||||
usesTabs = 0;
|
||||
};
|
||||
089C1671FE841209C02AAC07 /* Frameworks and Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
@@ -235,7 +208,6 @@
|
||||
089C167CFE841241C02AAC07 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
82CAFD010FEDD54000CCDC7E /* dsa_pub.pem */,
|
||||
8D5B49B7048680CD000E48DA /* Info.plist */,
|
||||
089C167DFE841241C02AAC07 /* InfoPlist.strings */,
|
||||
);
|
||||
@@ -282,7 +254,6 @@
|
||||
32C88E010371C26100C91783 /* Other Sources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
82CAFD030FEDD54800CCDC7E /* config.yaml */,
|
||||
);
|
||||
name = "Other Sources";
|
||||
sourceTree = "<group>";
|
||||
@@ -301,6 +272,8 @@
|
||||
941F598917A6189D0005D7EA /* Database.cpp */,
|
||||
941F598A17A6189D0005D7EA /* Database.h */,
|
||||
941F598B17A6189D0005D7EA /* Equates.h */,
|
||||
871EC9A124F08BF600CEC578 /* ExpansionModule.cpp */,
|
||||
871EC9A024F08BF600CEC578 /* ExpansionModule.h */,
|
||||
941F598C17A6189D0005D7EA /* Hash.cpp */,
|
||||
941F598D17A6189D0005D7EA /* Hash.h */,
|
||||
941F598E17A6189D0005D7EA /* lib */,
|
||||
@@ -365,47 +338,12 @@
|
||||
path = Lib;
|
||||
sourceTree = SOURCE_ROOT;
|
||||
};
|
||||
941F59DF17A630990005D7EA /* Win */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
941F59E017A630990005D7EA /* About.cpp */,
|
||||
941F59E117A630990005D7EA /* About.h */,
|
||||
941F59E217A630990005D7EA /* Common.cpp */,
|
||||
941F59E317A630990005D7EA /* Common.h */,
|
||||
941F59E417A630990005D7EA /* Configuration.cpp */,
|
||||
941F59E517A630990005D7EA /* Configuration.h */,
|
||||
941F59E617A630990005D7EA /* Console.cpp */,
|
||||
941F59E717A630990005D7EA /* Console.h */,
|
||||
941F59E817A630990005D7EA /* Database.cpp */,
|
||||
941F59E917A630990005D7EA /* Database.h */,
|
||||
941F59EA17A630990005D7EA /* Display.cpp */,
|
||||
941F59EB17A630990005D7EA /* Display.h */,
|
||||
941F59EC17A630990005D7EA /* Help.cpp */,
|
||||
941F59ED17A630990005D7EA /* Help.h */,
|
||||
941F59EE17A630990005D7EA /* Input.cpp */,
|
||||
941F59EF17A630990005D7EA /* Input.h */,
|
||||
941F59F017A630990005D7EA /* Main.cpp */,
|
||||
941F59F117A630990005D7EA /* Menu.cpp */,
|
||||
941F59F217A630990005D7EA /* Menu.h */,
|
||||
941F59F317A630990005D7EA /* ProSystem.aps */,
|
||||
941F59F417A630990005D7EA /* ProSystem.ico */,
|
||||
941F59F517A630990005D7EA /* ProSystem.rc */,
|
||||
941F59F617A630990005D7EA /* resource.h */,
|
||||
941F59F717A630990005D7EA /* Sound.cpp */,
|
||||
941F59F817A630990005D7EA /* Sound.h */,
|
||||
941F59F917A630990005D7EA /* Timer.cpp */,
|
||||
941F59FA17A630990005D7EA /* Timer.h */,
|
||||
);
|
||||
path = Win;
|
||||
sourceTree = SOURCE_ROOT;
|
||||
};
|
||||
94A9E27F157D637B0083A7DC /* Core */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
941F59FB17A77CC90005D7EA /* ProSystem.dat */,
|
||||
941F598017A6189D0005D7EA /* core */,
|
||||
941F59B517A6189D0005D7EA /* Lib */,
|
||||
941F59DF17A630990005D7EA /* Win */,
|
||||
);
|
||||
path = Core;
|
||||
sourceTree = "<group>";
|
||||
@@ -437,12 +375,11 @@
|
||||
089C1669FE841209C02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastUpgradeCheck = 0420;
|
||||
LastUpgradeCheck = 0700;
|
||||
};
|
||||
buildConfigurationList = 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "ProSystem" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
en,
|
||||
@@ -464,7 +401,6 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */,
|
||||
82CAFD020FEDD54000CCDC7E /* dsa_pub.pem in Resources */,
|
||||
941F59FC17A77CC90005D7EA /* ProSystem.dat in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -505,6 +441,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8794D9691B74713300897F57 /* Sound.cpp in Sources */,
|
||||
941DFB2715B6425200C6552F /* ProSystemGameCore.mm in Sources */,
|
||||
941F59BF17A6189D0005D7EA /* Archive.cpp in Sources */,
|
||||
941F59C017A6189D0005D7EA /* Bios.cpp in Sources */,
|
||||
@@ -521,6 +458,7 @@
|
||||
941F59CD17A6189D0005D7EA /* Pokey.cpp in Sources */,
|
||||
941F59CE17A6189D0005D7EA /* ProSystem.cpp in Sources */,
|
||||
941F59CF17A6189D0005D7EA /* Region.cpp in Sources */,
|
||||
871EC9A224F08BF700CEC578 /* ExpansionModule.cpp in Sources */,
|
||||
941F59D017A6189D0005D7EA /* Riot.cpp in Sources */,
|
||||
941F59D117A6189D0005D7EA /* Sally.cpp in Sources */,
|
||||
941F59D317A6189D0005D7EA /* Tia.cpp in Sources */,
|
||||
@@ -547,7 +485,7 @@
|
||||
089C167DFE841241C02AAC07 /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
089C167EFE841241C02AAC07 /* English */,
|
||||
089C167EFE841241C02AAC07 /* en */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
@@ -560,6 +498,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
EXPORTED_SYMBOLS_FILE = "";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"\"$(SRCROOT)/core\"",
|
||||
@@ -567,6 +506,7 @@
|
||||
);
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = "\"$(USER_LIBRARY_DIR)/Application Support/OpenEmu/Cores\"";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.openemu.${PRODUCT_NAME:identifier}";
|
||||
PRODUCT_NAME = ProSystem;
|
||||
SKIP_INSTALL = YES;
|
||||
VALID_ARCHS = x86_64;
|
||||
@@ -579,6 +519,7 @@
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
EXPORTED_SYMBOLS_FILE = "";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"\"$(SRCROOT)/core\"",
|
||||
@@ -586,6 +527,7 @@
|
||||
);
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = "\"$(USER_LIBRARY_DIR)/Application Support/OpenEmu/Cores\"";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.openemu.${PRODUCT_NAME:identifier}";
|
||||
PRODUCT_NAME = ProSystem;
|
||||
SKIP_INSTALL = YES;
|
||||
VALID_ARCHS = x86_64;
|
||||
@@ -596,42 +538,68 @@
|
||||
1DEB913F08733D840010E9CD /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_EXPERIMENTAL = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_INCREASE_PRECOMPILED_HEADER_SHARING = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = "";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
SDKROOT = macosx;
|
||||
VALID_ARCHS = x86_64;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1DEB914008733D840010E9CD /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_EXPERIMENTAL = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_INCREASE_PRECOMPILED_HEADER_SHARING = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_OPTIMIZATION_LEVEL = 3;
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = "";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
SDKROOT = macosx;
|
||||
VALID_ARCHS = x86_64;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
+262
-164
@@ -33,7 +33,7 @@
|
||||
|
||||
#include "ProSystem.h"
|
||||
#include "Database.h"
|
||||
//#include "Sound.h"
|
||||
#include "Sound.h"
|
||||
#include "Palette.h"
|
||||
#include "Maria.h"
|
||||
#include "Tia.h"
|
||||
@@ -42,104 +42,119 @@
|
||||
|
||||
@interface ProSystemGameCore () <OE7800SystemResponderClient>
|
||||
{
|
||||
uint32_t *videoBuffer;
|
||||
uint display_palette32[256];
|
||||
byte keyboard_data[19];
|
||||
uint32_t *_videoBuffer;
|
||||
uint32_t _displayPalette[256];
|
||||
uint8_t *_soundBuffer;
|
||||
uint8_t _inputState[17];
|
||||
int _videoWidth, _videoHeight;
|
||||
BOOL _isLightgunEnabled;
|
||||
}
|
||||
- (void)setPalette32;
|
||||
@end
|
||||
|
||||
ProSystemGameCore *current;
|
||||
@implementation ProSystemGameCore
|
||||
|
||||
static void display_ResetPalette32( ) {
|
||||
for(uint index = 0; index < 256; index++) {
|
||||
uint r = palette_data[(index * 3) + 0] << 16;
|
||||
uint g = palette_data[(index * 3) + 1] << 8;
|
||||
uint b = palette_data[(index * 3) + 2];
|
||||
current->display_palette32[index] = r | g | b;
|
||||
}
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if((self = [super init]))
|
||||
{
|
||||
videoBuffer = (uint32_t *)malloc(320 * 292 * 4);
|
||||
current = self;
|
||||
_videoBuffer = (uint32_t *)malloc(320 * 292 * 4);
|
||||
_soundBuffer = (uint8_t *)malloc(8192);
|
||||
}
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
free(videoBuffer);
|
||||
free(_videoBuffer);
|
||||
free(_soundBuffer);
|
||||
}
|
||||
|
||||
#pragma mark Execution
|
||||
#pragma mark - Execution
|
||||
|
||||
- (BOOL)loadFileAtPath:(NSString *)path
|
||||
- (BOOL)loadFileAtPath:(NSString *)path error:(NSError **)error
|
||||
{
|
||||
if(cartridge_Load([path UTF8String])) {
|
||||
//sound_Stop( );
|
||||
//display_Clear( );
|
||||
|
||||
const int LEFT_DIFF_SWITCH = 15;
|
||||
const int RIGHT_DIFF_SWITCH = 16;
|
||||
const int LEFT_POSITION = 1; // also know as "B"
|
||||
const int RIGHT_POSITION = 0; // also know as "A"
|
||||
|
||||
memset(_inputState, 0, sizeof(_inputState));
|
||||
|
||||
// Difficulty switches: Left position = (B)eginner, Right position = (A)dvanced
|
||||
// Left difficulty switch defaults to left position, "(B)eginner"
|
||||
_inputState[LEFT_DIFF_SWITCH] = LEFT_POSITION;
|
||||
|
||||
// Right difficulty switch defaults to right position, "(A)dvanced", which fixes Tower Toppler
|
||||
_inputState[RIGHT_DIFF_SWITCH] = RIGHT_POSITION;
|
||||
|
||||
if(cartridge_Load(path.fileSystemRepresentation))
|
||||
{
|
||||
NSString *databasePath = [[[NSBundle bundleForClass:[self class]] resourcePath] stringByAppendingPathComponent:@"ProSystem.dat"];
|
||||
database_filename = [databasePath UTF8String];
|
||||
database_filename = databasePath.fileSystemRepresentation;
|
||||
database_enabled = true;
|
||||
|
||||
|
||||
// BIOS is optional
|
||||
NSString *biosROM = [[self biosDirectoryPath] stringByAppendingPathComponent:@"7800 BIOS (U).rom"];
|
||||
if (bios_Load([biosROM UTF8String]))
|
||||
NSString *biosROM = [self.biosDirectoryPath stringByAppendingPathComponent:@"7800 BIOS (U).rom"];
|
||||
if (bios_Load(biosROM.fileSystemRepresentation))
|
||||
bios_enabled = true;
|
||||
|
||||
|
||||
NSLog(@"[ProSystem] Headerless MD5 hash: %s", cartridge_digest.c_str());
|
||||
NSLog(@"[ProSystem] Header info (often wrong):\ntitle: %s\ntype: %d\nregion: %s\npokey: %s", cartridge_title.c_str(), cartridge_type, cartridge_region == REGION_NTSC ? "NTSC" : "PAL", cartridge_pokey ? "true" : "false");
|
||||
|
||||
database_Load(cartridge_digest);
|
||||
prosystem_Reset( );
|
||||
|
||||
std::string title = common_Trim(cartridge_title);
|
||||
NSLog(@"Now Loading: %@", [NSString stringWithUTF8String:title.c_str()]);
|
||||
|
||||
prosystem_Reset();
|
||||
|
||||
if (cart_in_db) {
|
||||
std::string title = common_Trim(cartridge_title);
|
||||
NSLog(@"[ProSystem] Database info:\ntitle: %@\ntype: %d\nregion: %s\npokey: %s", [NSString stringWithUTF8String:title.c_str()], cartridge_type, cartridge_region == REGION_NTSC ? "NTSC" : "PAL", cartridge_pokey ? "true" : "false");
|
||||
}
|
||||
|
||||
//sound_SetSampleRate(48000);
|
||||
//display_ResetPalette( );
|
||||
display_ResetPalette32( );
|
||||
//console_SetZoom(display_zoom);
|
||||
//sound_Play( );
|
||||
|
||||
[self setPalette32];
|
||||
|
||||
_isLightgunEnabled = (cartridge_controller[0] & CARTRIDGE_CONTROLLER_LIGHTGUN);
|
||||
// The light gun 'trigger' is a press on the 'up' button (0x3) and needs the bit toggled
|
||||
if(_isLightgunEnabled)
|
||||
_inputState[3] = 1;
|
||||
|
||||
// Set switch overrides from database
|
||||
_inputState[LEFT_DIFF_SWITCH] = cartridge_left_switch;
|
||||
_inputState[RIGHT_DIFF_SWITCH] = cartridge_right_switch;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)executeFrame
|
||||
{
|
||||
[self executeFrameSkippingFrame:NO];
|
||||
}
|
||||
prosystem_ExecuteFrame(_inputState);
|
||||
|
||||
- (void)executeFrameSkippingFrame:(BOOL)skip
|
||||
{
|
||||
prosystem_ExecuteFrame(keyboard_data); //wants input
|
||||
|
||||
uint height = maria_visibleArea.GetHeight( );
|
||||
uint length = maria_visibleArea.GetLength( );
|
||||
|
||||
const byte* buffer = maria_surface + ((maria_visibleArea.top - maria_displayArea.top) * maria_visibleArea.GetLength( ));
|
||||
|
||||
uint* surface = (uint*)videoBuffer;
|
||||
//uint pitch = 320 >> 2; // should be Distance, in bytes, to the start of next line.
|
||||
uint pitch = 320;
|
||||
for(uint indexY = 0; indexY < height; indexY++) {
|
||||
for(uint indexX = 0; indexX < length; indexX += 4) {
|
||||
surface[indexX + 0] = display_palette32[buffer[indexX + 0]];
|
||||
surface[indexX + 1] = display_palette32[buffer[indexX + 1]];
|
||||
surface[indexX + 2] = display_palette32[buffer[indexX + 2]];
|
||||
surface[indexX + 3] = display_palette32[buffer[indexX + 3]];
|
||||
_videoWidth = maria_visibleArea.GetLength();
|
||||
_videoHeight = maria_visibleArea.GetHeight();
|
||||
|
||||
uint8_t *buffer = maria_surface + ((maria_visibleArea.top - maria_displayArea.top) * maria_visibleArea.GetLength());
|
||||
uint32_t *surface = (uint32_t *)_videoBuffer;
|
||||
int pitch = 320;
|
||||
|
||||
for(int indexY = 0; indexY < _videoHeight; indexY++)
|
||||
{
|
||||
for(int indexX = 0; indexX < _videoWidth; indexX += 4)
|
||||
{
|
||||
surface[indexX + 0] = _displayPalette[buffer[indexX + 0]];
|
||||
surface[indexX + 1] = _displayPalette[buffer[indexX + 1]];
|
||||
surface[indexX + 2] = _displayPalette[buffer[indexX + 2]];
|
||||
surface[indexX + 3] = _displayPalette[buffer[indexX + 3]];
|
||||
}
|
||||
surface += pitch;
|
||||
buffer += length;
|
||||
buffer += _videoWidth;
|
||||
}
|
||||
|
||||
sound_Store();
|
||||
|
||||
int length = sound_Store(_soundBuffer);
|
||||
[[self ringBufferAtIndex:0] write:_soundBuffer maxLength:length];
|
||||
}
|
||||
|
||||
- (void)resetEmulation
|
||||
@@ -147,21 +162,31 @@ static void display_ResetPalette32( ) {
|
||||
prosystem_Reset();
|
||||
}
|
||||
|
||||
#pragma mark Video
|
||||
- (NSTimeInterval)frameInterval
|
||||
{
|
||||
return cartridge_region == REGION_NTSC ? 60 : 50;
|
||||
}
|
||||
|
||||
#pragma mark - Video
|
||||
|
||||
- (const void *)getVideoBufferWithHint:(void *)hint
|
||||
{
|
||||
return _videoBuffer = (uint32_t*)(hint ?: _videoBuffer);
|
||||
}
|
||||
|
||||
- (OEIntRect)screenRect
|
||||
{
|
||||
return OEIntRectMake(0, 0, 320, 240);
|
||||
return OEIntRectMake(0, 0, maria_visibleArea.GetLength(), maria_visibleArea.GetHeight());
|
||||
}
|
||||
|
||||
- (OEIntSize)aspectSize
|
||||
{
|
||||
return OEIntSizeMake(maria_visibleArea.GetLength(), maria_visibleArea.GetHeight());
|
||||
}
|
||||
|
||||
- (OEIntSize)bufferSize
|
||||
{
|
||||
return OEIntSizeMake(320, 240);
|
||||
}
|
||||
|
||||
- (const void *)videoBuffer
|
||||
{
|
||||
return videoBuffer;
|
||||
return OEIntSizeMake(320, 292);
|
||||
}
|
||||
|
||||
- (GLenum)pixelFormat
|
||||
@@ -174,34 +199,86 @@ static void display_ResetPalette32( ) {
|
||||
return GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
}
|
||||
|
||||
- (GLenum)internalPixelFormat
|
||||
{
|
||||
return GL_RGB8;
|
||||
}
|
||||
|
||||
- (NSTimeInterval)frameInterval
|
||||
{
|
||||
return 60;
|
||||
}
|
||||
|
||||
#pragma mark Audio
|
||||
|
||||
- (NSUInteger)channelCount
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#pragma mark - Audio
|
||||
|
||||
- (double)audioSampleRate
|
||||
{
|
||||
return 48000;
|
||||
}
|
||||
|
||||
- (NSUInteger)channelCount
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (NSUInteger)audioBitDepth
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
#pragma mark Input
|
||||
#pragma mark - Save States
|
||||
|
||||
- (void)saveStateToFileAtPath:(NSString *)fileName completionHandler:(void (^)(BOOL, NSError *))block
|
||||
{
|
||||
block(prosystem_Save(fileName.fileSystemRepresentation, false) ? YES : NO, nil);
|
||||
}
|
||||
|
||||
- (void)loadStateFromFileAtPath:(NSString *)fileName completionHandler:(void (^)(BOOL, NSError *))block
|
||||
{
|
||||
block(prosystem_Load(fileName.fileSystemRepresentation) ? YES : NO, nil);
|
||||
}
|
||||
|
||||
- (NSData *)serializeStateWithError:(NSError **)outError
|
||||
{
|
||||
size_t length = cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM ? 32837 : 16453;
|
||||
if(cartridge_xm) {
|
||||
length += 4 + XM_RAM_SIZE;
|
||||
}
|
||||
void *bytes = malloc(length);
|
||||
|
||||
if(prosystem_Save_buffer((uint8_t *)bytes))
|
||||
return [NSData dataWithBytesNoCopy:bytes length:length freeWhenDone:YES];
|
||||
|
||||
if(outError) {
|
||||
*outError = [NSError errorWithDomain:OEGameCoreErrorDomain code:OEGameCoreCouldNotSaveStateError userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Save state data could not be written",
|
||||
NSLocalizedRecoverySuggestionErrorKey : @"The emulator could not write the state data."
|
||||
}];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)deserializeState:(NSData *)state withError:(NSError **)outError
|
||||
{
|
||||
size_t serial_size = cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM ? 32837 : 16453;
|
||||
if(cartridge_xm) {
|
||||
serial_size += 4 + XM_RAM_SIZE;
|
||||
}
|
||||
if(serial_size != state.length) {
|
||||
if(outError) {
|
||||
*outError = [NSError errorWithDomain:OEGameCoreErrorDomain code:OEGameCoreStateHasWrongSizeError userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Save state has wrong file size.",
|
||||
NSLocalizedRecoverySuggestionErrorKey : [NSString stringWithFormat:@"The save state does not have the right size, %ld expected, got: %ld.", serial_size, state.length]
|
||||
}];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
if(prosystem_Load_buffer((uint8_t *)state.bytes))
|
||||
return YES;
|
||||
|
||||
if(outError) {
|
||||
*outError = [NSError errorWithDomain:OEGameCoreErrorDomain code:OEGameCoreCouldNotLoadStateError userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"The save state data could not be read"
|
||||
}];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
#pragma mark - Input
|
||||
// ----------------------------------------------------------------------------
|
||||
// SetInput
|
||||
// +----------+--------------+-------------------------------------------------
|
||||
@@ -225,98 +302,119 @@ static void display_ResetPalette32( ) {
|
||||
// | 15 | Console | Left Difficulty
|
||||
// | 16 | Console | Right Difficulty
|
||||
// +----------+--------------+-------------------------------------------------
|
||||
const int ProSystemMap[] = { 3, 2, 1, 0, 4, 5}; // fix for Joystick 2 and the console buttons
|
||||
const int ProSystemMap[] = { 3, 2, 1, 0, 4, 5, 9, 8, 7, 6, 10, 11, 13, 14, 12, 15, 16};
|
||||
- (oneway void)didPush7800Button:(OE7800Button)button forPlayer:(NSUInteger)player;
|
||||
{
|
||||
//keyboard_data[player-1] |= 1 << ProSystemMap[button];
|
||||
keyboard_data[ProSystemMap[button]] = 1;
|
||||
int playerShift = player != 1 ? 6 : 0;
|
||||
|
||||
switch(button)
|
||||
{
|
||||
case OE7800ButtonUp:
|
||||
_inputState[ProSystemMap[button + playerShift]] ^= 1;
|
||||
break;
|
||||
case OE7800ButtonDown:
|
||||
case OE7800ButtonLeft:
|
||||
case OE7800ButtonRight:
|
||||
case OE7800ButtonFire1:
|
||||
case OE7800ButtonFire2:
|
||||
_inputState[ProSystemMap[button + playerShift]] = 1;
|
||||
break;
|
||||
|
||||
case OE7800ButtonSelect:
|
||||
case OE7800ButtonPause:
|
||||
case OE7800ButtonReset:
|
||||
_inputState[ProSystemMap[button + 6]] = 1;
|
||||
break;
|
||||
|
||||
case OE7800ButtonLeftDiff:
|
||||
case OE7800ButtonRightDiff:
|
||||
_inputState[ProSystemMap[button + 6]] ^= (1 << 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (oneway void)didRelease7800Button:(OE7800Button)button forPlayer:(NSUInteger)player;
|
||||
{
|
||||
//keyboard_data[player-1] &= ~(1 << ProSystemMap[button]);
|
||||
keyboard_data[ProSystemMap[button]] = 0;
|
||||
}
|
||||
int playerShift = player != 1 ? 6 : 0;
|
||||
|
||||
- (BOOL)saveStateToFileAtPath:(NSString *)fileName
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
switch(button)
|
||||
{
|
||||
case OE7800ButtonUp:
|
||||
_inputState[ProSystemMap[button + playerShift]] ^= 1;
|
||||
break;
|
||||
case OE7800ButtonDown:
|
||||
case OE7800ButtonLeft:
|
||||
case OE7800ButtonRight:
|
||||
case OE7800ButtonFire1:
|
||||
case OE7800ButtonFire2:
|
||||
_inputState[ProSystemMap[button + playerShift]] = 0;
|
||||
break;
|
||||
|
||||
- (BOOL)loadStateFromFileAtPath:(NSString *)fileName
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
case OE7800ButtonSelect:
|
||||
case OE7800ButtonPause:
|
||||
case OE7800ButtonReset:
|
||||
_inputState[ProSystemMap[button + 6]] = 0;
|
||||
break;
|
||||
|
||||
static uint sound_GetSampleLength(uint length, uint unit, uint unitMax) {
|
||||
uint sampleLength = length / unitMax;
|
||||
uint sampleRemain = length % unitMax;
|
||||
if(sampleRemain != 0 && sampleRemain >= unit) {
|
||||
sampleLength++;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return sampleLength;
|
||||
}
|
||||
|
||||
static void sound_Resample(const byte* source, byte* target, int length) {
|
||||
typedef struct {
|
||||
word wFormatTag;
|
||||
word nChannels;
|
||||
uint nSamplesPerSec;
|
||||
uint nAvgBytesPerSec;
|
||||
word nBlockAlign;
|
||||
word wBitsPerSample;
|
||||
word cbSize;
|
||||
} WAVEFORMATEX;
|
||||
|
||||
# define WAVE_FORMAT_PCM 0
|
||||
|
||||
static const WAVEFORMATEX SOUND_DEFAULT_FORMAT = {WAVE_FORMAT_PCM, 1, 48000, 48000, 1, 8, 0};
|
||||
static WAVEFORMATEX sound_format = SOUND_DEFAULT_FORMAT;
|
||||
|
||||
int measurement = sound_format.nSamplesPerSec;
|
||||
int sourceIndex = 0;
|
||||
int targetIndex = 0;
|
||||
|
||||
int max = ( ( prosystem_frequency * prosystem_scanlines ) << 1 );
|
||||
while(targetIndex < length) {
|
||||
if(measurement >= max) {
|
||||
target[targetIndex++] = source[sourceIndex];
|
||||
measurement -= max;
|
||||
}
|
||||
else {
|
||||
sourceIndex++;
|
||||
measurement += sound_format.nSamplesPerSec;
|
||||
- (oneway void)mouseMovedAtPoint:(OEIntPoint)aPoint
|
||||
{
|
||||
if(_isLightgunEnabled)
|
||||
{
|
||||
// All of this really needs to be tweaked per the 5 games that support light gun
|
||||
int yoffset = (cartridge_region == REGION_NTSC ? 2 : -2);
|
||||
|
||||
// The number of scanlines for the current cartridge
|
||||
int scanlines = _videoHeight;
|
||||
|
||||
float yratio = ((float)scanlines / (float)_videoHeight);
|
||||
float xratio = ((float)LG_CYCLES_PER_SCANLINE / (float)_videoWidth);
|
||||
|
||||
lightgun_scanline = (((float)aPoint.y * yratio) + (maria_visibleArea.top - maria_displayArea.top + 1) + yoffset);
|
||||
lightgun_cycle = (HBLANK_CYCLES + LG_CYCLES_INDENT + ((float)aPoint.x * xratio));
|
||||
|
||||
if(lightgun_cycle > CYCLES_PER_SCANLINE)
|
||||
{
|
||||
lightgun_scanline++;
|
||||
lightgun_cycle -= CYCLES_PER_SCANLINE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sound_Store() {
|
||||
#define MAX_BUFFER_SIZE 8192
|
||||
|
||||
byte sample[MAX_BUFFER_SIZE];
|
||||
memset( sample, 0, MAX_BUFFER_SIZE );
|
||||
uint length = 48000 / prosystem_frequency; /* sound_GetSampleLength(sound_format.nSamplesPerSec, prosystem_frame, prosystem_frequency); */ /* 48000 / prosystem_frequency */
|
||||
sound_Resample(tia_buffer, sample, length);
|
||||
|
||||
// Ballblazer, Commando
|
||||
//if(cartridge_pokey) {
|
||||
byte pokeySample[MAX_BUFFER_SIZE];
|
||||
memset( pokeySample, 0, MAX_BUFFER_SIZE );
|
||||
sound_Resample(pokey_buffer, pokeySample, length);
|
||||
for(uint index = 0; index < length; index++) {
|
||||
sample[index] += pokeySample[index];
|
||||
sample[index] = sample[index] / 2;
|
||||
}
|
||||
//}
|
||||
[[current ringBufferAtIndex:0] write:sample maxLength:length];
|
||||
// Convert 8u to 16s
|
||||
// for(int i = 0; i != length; i ++)
|
||||
// {
|
||||
// int16_t sample16 = (sample[i] << 8) - 32768;
|
||||
// int16_t frame[2] = {sample16, sample16};
|
||||
//
|
||||
// [[current ringBufferAtIndex:0] write:frame maxLength:2];
|
||||
// }
|
||||
- (oneway void)leftMouseDownAtPoint:(OEIntPoint)aPoint
|
||||
{
|
||||
if(_isLightgunEnabled)
|
||||
{
|
||||
[self mouseMovedAtPoint:aPoint];
|
||||
|
||||
_inputState[3] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
- (oneway void)leftMouseUp
|
||||
{
|
||||
if(_isLightgunEnabled)
|
||||
_inputState[3] = 1;
|
||||
}
|
||||
|
||||
#pragma mark - Misc Helper Methods
|
||||
// Set palette 32bpp
|
||||
- (void)setPalette32
|
||||
{
|
||||
for(int index = 0; index < 256; index++)
|
||||
{
|
||||
uint32_t r = palette_data[(index * 3) + 0] << 16;
|
||||
uint32_t g = palette_data[(index * 3) + 1] << 8;
|
||||
uint32_t b = palette_data[(index * 3) + 2];
|
||||
_displayPalette[index] = r | g | b;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
build_now: 'YES'
|
||||
create_core_path: 'YES'
|
||||
download_base_url: http://github.com/downloads/openemu/openemu
|
||||
release_notes_base_url: http://openemu.org/category/releasenotes/stella/
|
||||
appcast_basefolder: '/Users/jweinberg/Desktop/Appcast'
|
||||
appcast_xml_name: 'stella_appcast.xml'
|
||||
keychain_privkey_name: 'Sparkle Private Key'
|
||||
css_file_name: 'rnotes.css'
|
||||
bundle_extension: 'oecoreplugin'
|
||||
+2
-2
@@ -53,14 +53,14 @@ bool bios_Load(std::string filename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(fseek(file, 0, SEEK_END)) {
|
||||
if(fseek(file, 0L, SEEK_END)) {
|
||||
fclose(file);
|
||||
logger_LogError("Failed to find the end of the bios file.", BIOS_SOURCE);
|
||||
return false;
|
||||
}
|
||||
|
||||
bios_size = ftell(file);
|
||||
if(fseek(file, 0, SEEK_SET)) {
|
||||
if(fseek(file, 0L, SEEK_SET)) {
|
||||
fclose(file);
|
||||
logger_LogError("Failed to find the size of the bios file.", BIOS_SOURCE);
|
||||
return false;
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BIOS_H
|
||||
#define BIOS_H
|
||||
//#define NULL 0
|
||||
|
||||
#include <string>
|
||||
#include "Memory.h"
|
||||
|
||||
+160
-52
@@ -5,7 +5,7 @@
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2005 Greg Stanton
|
||||
//
|
||||
//
|
||||
// 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
|
||||
@@ -23,6 +23,9 @@
|
||||
// Cartridge.cpp
|
||||
// ----------------------------------------------------------------------------
|
||||
#include "Cartridge.h"
|
||||
#include "Region.h"
|
||||
|
||||
#include <string.h>
|
||||
#define CARTRIDGE_SOURCE "Cartridge.cpp"
|
||||
|
||||
std::string cartridge_title;
|
||||
@@ -34,9 +37,20 @@ std::string cartridge_filename;
|
||||
byte cartridge_type;
|
||||
byte cartridge_region;
|
||||
bool cartridge_pokey;
|
||||
byte cartridge_controller[2];
|
||||
bool cartridge_pokey450;
|
||||
byte cartridge_controller[2] = {1, 1};
|
||||
byte cartridge_bank;
|
||||
uint cartridge_flags;
|
||||
int cartridge_crosshair_x;
|
||||
int cartridge_crosshair_y;
|
||||
bool cartridge_dualanalog = false;
|
||||
bool cartridge_xm = false;
|
||||
bool cartridge_disable_bios = false;
|
||||
uint cartridge_hblank = 34;
|
||||
byte cartridge_left_switch = 1;
|
||||
byte cartridge_right_switch = 0;
|
||||
bool cartridge_swap_buttons = false;
|
||||
bool cartridge_hsc_enabled = false;
|
||||
|
||||
static byte* cartridge_buffer = NULL;
|
||||
static uint cartridge_size = 0;
|
||||
@@ -67,11 +81,24 @@ static bool cartridge_CC2(const byte* header) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// GetBank
|
||||
// ----------------------------------------------------------------------------
|
||||
static uint cartridge_GetBank(byte bank) {
|
||||
if ((cartridge_type == CARTRIDGE_TYPE_SUPERCART || cartridge_type == CARTRIDGE_TYPE_SUPERCART_ROM || cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) && cartridge_size <= 65536) {
|
||||
// for some of these carts, there are only 4 banks. in this case we ignore bit 3
|
||||
// previously, games of this type had to be doubled. The first 4 banks needed to be duplicated at the end of the ROM
|
||||
return (bank & 3);
|
||||
}
|
||||
|
||||
return bank;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// GetBankOffset
|
||||
// ----------------------------------------------------------------------------
|
||||
static uint cartridge_GetBankOffset(byte bank) {
|
||||
return bank * 16384;
|
||||
return cartridge_GetBank(bank) * 16384;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -85,17 +112,30 @@ static void cartridge_WriteBank(word address, byte bank) {
|
||||
}
|
||||
}
|
||||
|
||||
static void cartridge_SetTypeBySize(uint size) {
|
||||
if (size <= 0x10000) {
|
||||
cartridge_type = CARTRIDGE_TYPE_NORMAL;
|
||||
} else if (size == 0x24000 ) {
|
||||
cartridge_type = CARTRIDGE_TYPE_SUPERCART_LARGE;
|
||||
} else if (size == 0x20000 ) {
|
||||
cartridge_type = CARTRIDGE_TYPE_SUPERCART_ROM;
|
||||
} else {
|
||||
cartridge_type = CARTRIDGE_TYPE_SUPERCART;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ReadHeader
|
||||
// ----------------------------------------------------------------------------
|
||||
static void cartridge_ReadHeader(const byte* header) {
|
||||
|
||||
char temp[33] = {0};
|
||||
for(int index = 0; index < 32; index++) {
|
||||
temp[index] = header[index + 17];
|
||||
temp[index] = header[index + 17];
|
||||
}
|
||||
cartridge_title = temp;
|
||||
|
||||
cartridge_size = header[49] << 32;
|
||||
|
||||
cartridge_size = header[49] << 24;
|
||||
cartridge_size |= header[50] << 16;
|
||||
cartridge_size |= header[51] << 8;
|
||||
cartridge_size |= header[52];
|
||||
@@ -118,23 +158,47 @@ static void cartridge_ReadHeader(const byte* header) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(header[53] == 1) {
|
||||
if(header[53] == 2 /*1*/) { // Wii: Abs and Act were swapped
|
||||
cartridge_type = CARTRIDGE_TYPE_ABSOLUTE;
|
||||
}
|
||||
else if(header[53] == 2) {
|
||||
else if(header[53] == 1 /*2*/) { // Wii: Abs and Act were swapped
|
||||
cartridge_type = CARTRIDGE_TYPE_ACTIVISION;
|
||||
}
|
||||
else {
|
||||
cartridge_type = CARTRIDGE_TYPE_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
//cartridge_pokey = (header[54] & 1)? true: false;
|
||||
cartridge_pokey = true;
|
||||
|
||||
cartridge_pokey = (header[54] & 1)? true: false;
|
||||
cartridge_pokey450 = (header[54] & 0x40)? true : false;
|
||||
if (cartridge_pokey450) {
|
||||
cartridge_pokey = true;
|
||||
}
|
||||
cartridge_controller[0] = header[55];
|
||||
cartridge_controller[1] = header[56];
|
||||
cartridge_region = header[57];
|
||||
cartridge_flags = 0;
|
||||
cartridge_xm = (header[63] & 1)? true: false;
|
||||
cartridge_hsc_enabled = header[58]&0x01;
|
||||
|
||||
// Wii: Updates to header interpretation
|
||||
byte ct1 = header[54];
|
||||
if(header[53] == 0) {
|
||||
if ((ct1&0x0a)==0x0a) { // BIT1 and BIT3 (Supercart Large: 2) rom at $4000
|
||||
cartridge_type = CARTRIDGE_TYPE_SUPERCART_LARGE;
|
||||
} else if ((ct1&0x12)==0x12) { // BIT1 and BIT4 (Supercart ROM: 4) bank6 at $4000
|
||||
cartridge_type = CARTRIDGE_TYPE_SUPERCART_ROM;
|
||||
} else if ((ct1&0x06)==0x06) { // BIT1 and BIT2 (Supercart RAM: 3) ram at $4000
|
||||
cartridge_type = CARTRIDGE_TYPE_SUPERCART_RAM;
|
||||
} else if ((ct1&0x02)==0x02) { // BIT1 (Supercart) bank switched
|
||||
cartridge_type = CARTRIDGE_TYPE_SUPERCART;
|
||||
} else if (cartridge_size <= 0x10000 && ((ct1&0x04)==0x04)) { // Size < 64k && BIT2 (Normal RAM: ?) ram at $4000 )
|
||||
cartridge_type = CARTRIDGE_TYPE_NORMAL_RAM;
|
||||
} else {
|
||||
// Attempt to determine the cartridge type based on its size
|
||||
cartridge_SetTypeBySize(cartridge_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -147,7 +211,7 @@ static bool cartridge_Load(const byte* data, uint size) {
|
||||
}
|
||||
|
||||
cartridge_Release( );
|
||||
|
||||
|
||||
byte header[128] = {0};
|
||||
for(int index = 0; index < 128; index++) {
|
||||
header[index] = data[index];
|
||||
@@ -163,18 +227,29 @@ if (cartridge_CC2(header)) {
|
||||
cartridge_ReadHeader(header);
|
||||
size -= 128;
|
||||
offset = 128;
|
||||
|
||||
// Several cartridge headers do not have the proper size. So attempt to use the size
|
||||
// of the file.
|
||||
if (cartridge_size != size) {
|
||||
// Necessary for the following roms:
|
||||
// Impossible Mission hacks w/ C64 style graphics
|
||||
if (size % 1024 == 0) {
|
||||
cartridge_size = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
cartridge_size = size;
|
||||
// Attempt to guess the cartridge type based on its size
|
||||
cartridge_SetTypeBySize(size);
|
||||
}
|
||||
|
||||
|
||||
cartridge_buffer = new byte[cartridge_size];
|
||||
for(int index = 0; index < cartridge_size; index++) {
|
||||
cartridge_buffer[index] = data[index + offset];
|
||||
}
|
||||
|
||||
|
||||
cartridge_digest = hash_Compute(cartridge_buffer, cartridge_size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -186,33 +261,33 @@ bool cartridge_Load(std::string filename) {
|
||||
logger_LogError("Cartridge filename is invalid.", CARTRIDGE_SOURCE);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
cartridge_Release( );
|
||||
logger_LogInfo("Opening cartridge file " + filename + ".", CARTRIDGE_SOURCE);
|
||||
|
||||
|
||||
byte* data = NULL;
|
||||
//uint size = archive_GetUncompressedFileSize(filename);
|
||||
uint size;
|
||||
uint size = 0;
|
||||
|
||||
if(size == 0) {
|
||||
FILE *file = fopen(filename.c_str( ), "rb");
|
||||
if(file == NULL) {
|
||||
logger_LogError("Failed to open the cartridge file " + filename + " for reading.", CARTRIDGE_SOURCE);
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(fseek(file, 0, SEEK_END)) {
|
||||
if(fseek(file, 0L, SEEK_END)) {
|
||||
fclose(file);
|
||||
logger_LogError("Failed to find the end of the cartridge file.", CARTRIDGE_SOURCE);
|
||||
return false;
|
||||
}
|
||||
size = ftell(file);
|
||||
if(fseek(file, 0, SEEK_SET)) {
|
||||
if(fseek(file, 0L, SEEK_SET)) {
|
||||
fclose(file);
|
||||
logger_LogError("Failed to find the size of the cartridge file.", CARTRIDGE_SOURCE);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
data = new byte[size];
|
||||
if(fread(data, 1, size, file) != size && ferror(file)) {
|
||||
fclose(file);
|
||||
@@ -220,15 +295,15 @@ bool cartridge_Load(std::string filename) {
|
||||
cartridge_Release( );
|
||||
delete [ ] data;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
fclose(file);
|
||||
}
|
||||
else {
|
||||
data = new byte[size];
|
||||
//archive_Uncompress(filename, data, size);
|
||||
}
|
||||
|
||||
|
||||
if(!cartridge_Load(data, size)) {
|
||||
logger_LogError("Failed to load the cartridge data into memory.", CARTRIDGE_SOURCE);
|
||||
delete [ ] data;
|
||||
@@ -237,7 +312,7 @@ bool cartridge_Load(std::string filename) {
|
||||
if(data != NULL) {
|
||||
delete [ ] data;
|
||||
}
|
||||
|
||||
|
||||
cartridge_filename = filename;
|
||||
return true;
|
||||
}
|
||||
@@ -250,29 +325,37 @@ void cartridge_Store( ) {
|
||||
case CARTRIDGE_TYPE_NORMAL:
|
||||
memory_WriteROM(65536 - cartridge_size, cartridge_size, cartridge_buffer);
|
||||
break;
|
||||
case CARTRIDGE_TYPE_SUPERCART:
|
||||
if(cartridge_GetBankOffset(7) < cartridge_size) {
|
||||
memory_WriteROM(49152, 16384, cartridge_buffer + cartridge_GetBankOffset(7));
|
||||
}
|
||||
case CARTRIDGE_TYPE_NORMAL_RAM:
|
||||
memory_WriteROM(65536 - cartridge_size, cartridge_size, cartridge_buffer);
|
||||
memory_ClearROM(16384, 16384);
|
||||
break;
|
||||
case CARTRIDGE_TYPE_SUPERCART_LARGE:
|
||||
if(cartridge_GetBankOffset(8) < cartridge_size) {
|
||||
memory_WriteROM(49152, 16384, cartridge_buffer + cartridge_GetBankOffset(8));
|
||||
case CARTRIDGE_TYPE_SUPERCART: {
|
||||
uint offset = cartridge_size - 16384;
|
||||
if(offset < cartridge_size) {
|
||||
memory_WriteROM(49152, 16384, cartridge_buffer + offset);
|
||||
}
|
||||
} break;
|
||||
case CARTRIDGE_TYPE_SUPERCART_LARGE: {
|
||||
uint offset = cartridge_size - 16384;
|
||||
if(offset < cartridge_size) {
|
||||
memory_WriteROM(49152, 16384, cartridge_buffer + offset);
|
||||
memory_WriteROM(16384, 16384, cartridge_buffer + cartridge_GetBankOffset(0));
|
||||
}
|
||||
break;
|
||||
case CARTRIDGE_TYPE_SUPERCART_RAM:
|
||||
if(cartridge_GetBankOffset(7) < cartridge_size) {
|
||||
memory_WriteROM(49152, 16384, cartridge_buffer + cartridge_GetBankOffset(7));
|
||||
} break;
|
||||
case CARTRIDGE_TYPE_SUPERCART_RAM: {
|
||||
uint offset = cartridge_size - 16384;
|
||||
if(offset < cartridge_size) {
|
||||
memory_WriteROM(49152, 16384, cartridge_buffer + offset);
|
||||
memory_ClearROM(16384, 16384);
|
||||
}
|
||||
break;
|
||||
case CARTRIDGE_TYPE_SUPERCART_ROM:
|
||||
if(cartridge_GetBankOffset(7) < cartridge_size && cartridge_GetBankOffset(6) < cartridge_size) {
|
||||
memory_WriteROM(49152, 16384, cartridge_buffer + cartridge_GetBankOffset(7));
|
||||
} break;
|
||||
case CARTRIDGE_TYPE_SUPERCART_ROM: {
|
||||
uint offset = cartridge_size - 16384;
|
||||
if(offset < cartridge_size && cartridge_GetBankOffset(6) < cartridge_size) {
|
||||
memory_WriteROM(49152, 16384, cartridge_buffer + offset);
|
||||
memory_WriteROM(16384, 16384, cartridge_buffer + cartridge_GetBankOffset(6));
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
case CARTRIDGE_TYPE_ABSOLUTE:
|
||||
memory_WriteROM(16384, 16384, cartridge_buffer);
|
||||
memory_WriteROM(32768, 32768, cartridge_buffer + cartridge_GetBankOffset(2));
|
||||
@@ -296,16 +379,18 @@ void cartridge_Write(word address, byte data) {
|
||||
switch(cartridge_type) {
|
||||
case CARTRIDGE_TYPE_SUPERCART:
|
||||
case CARTRIDGE_TYPE_SUPERCART_RAM:
|
||||
case CARTRIDGE_TYPE_SUPERCART_ROM:
|
||||
if(address >= 32768 && address < 49152 && data < 9) {
|
||||
case CARTRIDGE_TYPE_SUPERCART_ROM: {
|
||||
uint maxbank = cartridge_size / 16384;
|
||||
if(address >= 32768 && address < 49152 && cartridge_GetBank(data) < maxbank /*9*/) {
|
||||
cartridge_StoreBank(data);
|
||||
}
|
||||
break;
|
||||
case CARTRIDGE_TYPE_SUPERCART_LARGE:
|
||||
if(address >= 32768 && address < 49152 && data < 9) {
|
||||
} break;
|
||||
case CARTRIDGE_TYPE_SUPERCART_LARGE: {
|
||||
uint maxbank = cartridge_size / 16384;
|
||||
if(address >= 32768 && address < 49152 && cartridge_GetBank(data) < maxbank /*9*/) {
|
||||
cartridge_StoreBank(data + 1);
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
case CARTRIDGE_TYPE_ABSOLUTE:
|
||||
if(address == 32768 && (data == 1 || data == 2)) {
|
||||
cartridge_StoreBank(data - 1);
|
||||
@@ -318,8 +403,8 @@ void cartridge_Write(word address, byte data) {
|
||||
break;
|
||||
}
|
||||
|
||||
//if(cartridge_pokey && address >= 0x4000 && address < 0x4009) {
|
||||
if(address >= 0x4000 && address < 0x4009) {
|
||||
#if 0 // WIi: Moved to Memory.cpp
|
||||
if(cartridge_pokey && address >= 0x4000 && address <= 0x400f) {
|
||||
switch(address) {
|
||||
case POKEY_AUDF1:
|
||||
pokey_SetRegister(POKEY_AUDF1, data);
|
||||
@@ -348,8 +433,12 @@ void cartridge_Write(word address, byte data) {
|
||||
case POKEY_AUDCTL:
|
||||
pokey_SetRegister(POKEY_AUDCTL, data);
|
||||
break;
|
||||
case POKEY_SKCTLS:
|
||||
pokey_SetRegister(POKEY_SKCTLS, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -367,7 +456,7 @@ void cartridge_StoreBank(byte bank) {
|
||||
cartridge_WriteBank(32768, bank);
|
||||
break;
|
||||
case CARTRIDGE_TYPE_SUPERCART_LARGE:
|
||||
cartridge_WriteBank(32768, bank);
|
||||
cartridge_WriteBank(32768, bank);
|
||||
break;
|
||||
case CARTRIDGE_TYPE_ABSOLUTE:
|
||||
cartridge_WriteBank(16384, bank);
|
||||
@@ -375,7 +464,7 @@ void cartridge_StoreBank(byte bank) {
|
||||
case CARTRIDGE_TYPE_ACTIVISION:
|
||||
cartridge_WriteBank(40960, bank);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -393,5 +482,24 @@ void cartridge_Release( ) {
|
||||
delete [ ] cartridge_buffer;
|
||||
cartridge_size = 0;
|
||||
cartridge_buffer = NULL;
|
||||
cartridge_title = "";
|
||||
cartridge_type = 0;
|
||||
cartridge_region = 0;
|
||||
cartridge_pokey = 0;
|
||||
cartridge_pokey450 = 0;
|
||||
cartridge_xm = false;
|
||||
// Default to joysticks
|
||||
memset( cartridge_controller, 1, sizeof( cartridge_controller ) );
|
||||
cartridge_bank = 0;
|
||||
cartridge_flags = 0;
|
||||
cartridge_disable_bios = false;
|
||||
cartridge_crosshair_x = 0;
|
||||
cartridge_crosshair_y = 0;
|
||||
cartridge_hblank = HBLANK_DEFAULT;
|
||||
cartridge_dualanalog = false;
|
||||
cartridge_left_switch = 1;
|
||||
cartridge_right_switch = 0;
|
||||
cartridge_swap_buttons = false;
|
||||
cartridge_hsc_enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
+21
-2
@@ -31,12 +31,14 @@
|
||||
#define CARTRIDGE_TYPE_SUPERCART_ROM 4
|
||||
#define CARTRIDGE_TYPE_ABSOLUTE 5
|
||||
#define CARTRIDGE_TYPE_ACTIVISION 6
|
||||
#define CARTRIDGE_TYPE_NORMAL_RAM 7
|
||||
#define CARTRIDGE_CONTROLLER_NONE 0
|
||||
#define CARTRIDGE_CONTROLLER_JOYSTICK 1
|
||||
#define CARTRIDGE_CONTROLLER_LIGHTGUN 2
|
||||
#define CARTRIDGE_WSYNC_MASK 2
|
||||
#define CARTRIDGE_CYCLE_STEALING_MASK 1
|
||||
//#define NULL 0
|
||||
|
||||
#define HBLANK_DEFAULT 34
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
@@ -66,8 +68,25 @@ extern std::string cartridge_filename;
|
||||
extern byte cartridge_type;
|
||||
extern byte cartridge_region;
|
||||
extern bool cartridge_pokey;
|
||||
extern bool cartridge_pokey450;
|
||||
extern bool cartridge_xm;
|
||||
extern byte cartridge_controller[2];
|
||||
extern byte cartridge_bank;
|
||||
extern uint cartridge_flags;
|
||||
extern bool cartridge_disable_bios;
|
||||
extern byte cartridge_left_switch;
|
||||
extern byte cartridge_right_switch;
|
||||
extern bool cartridge_swap_buttons;
|
||||
|
||||
#endif
|
||||
// The x offset for the lightgun crosshair (allows per cartridge adjustments)
|
||||
extern int cartridge_crosshair_x;
|
||||
// The y offset for the lightgun crosshair (allows per cartridge adjustments)
|
||||
extern int cartridge_crosshair_y;
|
||||
// The hblank prior to DMA
|
||||
extern uint cartridge_hblank;
|
||||
// Whether the cartridge supports dual analog
|
||||
extern bool cartridge_dualanalog;
|
||||
// Whether the high score cart is enabled
|
||||
extern bool cartridge_hsc_enabled;
|
||||
|
||||
#endif
|
||||
|
||||
+9
-21
@@ -92,6 +92,13 @@ uint common_ParseUint(std::string text) {
|
||||
return (uint)atoi(text.c_str( ));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ParseInt
|
||||
// ----------------------------------------------------------------------------
|
||||
int common_ParseInt(std::string text) {
|
||||
return (int)atoi(text.c_str( ));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ParseWord
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -136,27 +143,8 @@ std::string common_Trim(std::string target) {
|
||||
// Remove
|
||||
// ----------------------------------------------------------------------------
|
||||
std::string common_Remove(std::string target, char value) {
|
||||
int length = 0;
|
||||
int index;
|
||||
for(index = 0; index < target.size( ); index++) {
|
||||
if(target[index] != value) {
|
||||
length++;
|
||||
}
|
||||
}
|
||||
|
||||
char* buffer = new char[length + 1];
|
||||
int count = 0;
|
||||
for(index = 0; index < target.size( ); index++) {
|
||||
if(target[index] != value) {
|
||||
buffer[count] = target[index];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
buffer[length] = 0;
|
||||
std::string source = buffer;
|
||||
delete[ ] buffer;
|
||||
return source;
|
||||
target.erase(std::remove(target.begin(), target.end(), value), target.end());
|
||||
return target;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -46,6 +46,7 @@ extern std::string common_GetErrorMessage( );
|
||||
//extern std::string common_GetErrorMessage(DWORD error);
|
||||
extern std::string common_GetExtension(std::string filename);
|
||||
extern uint common_ParseUint(std::string text);
|
||||
extern int common_ParseInt(std::string text);
|
||||
extern word common_ParseWord(std::string text);
|
||||
extern byte common_ParseByte(std::string text);
|
||||
extern bool common_ParseBool(std::string text);
|
||||
|
||||
+59
-2
@@ -25,6 +25,7 @@
|
||||
#include "Database.h"
|
||||
#define DATABASE_SOURCE "Database.cpp"
|
||||
|
||||
bool cart_in_db = false;
|
||||
bool database_enabled = true;
|
||||
std::string database_filename;
|
||||
|
||||
@@ -44,6 +45,7 @@ void database_Initialize( ) {
|
||||
// Load
|
||||
// ----------------------------------------------------------------------------
|
||||
bool database_Load(std::string digest) {
|
||||
cart_in_db = false;
|
||||
if(database_enabled) {
|
||||
logger_LogInfo("Accessing database " + database_filename + ".", DATABASE_SOURCE);
|
||||
|
||||
@@ -53,14 +55,24 @@ bool database_Load(std::string digest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// max count of items in the database
|
||||
static int count = 17;
|
||||
|
||||
char buffer[256];
|
||||
while(fgets(buffer, 256, file) != NULL) {
|
||||
std::string line = buffer;
|
||||
if(line.compare(1, 32, digest.c_str( )) == 0) {
|
||||
std::string entry[7];
|
||||
for(int index = 0; index < 7; index++) {
|
||||
cart_in_db = true;
|
||||
std::string entry[count];
|
||||
for (int index = 0; index < count; index++) {
|
||||
buffer[0] = '\0';
|
||||
fgets(buffer, 256, file);
|
||||
if (strchr(buffer, '[')) {
|
||||
// Passed the current game in DB
|
||||
break;
|
||||
}
|
||||
entry[index] = common_Remove(buffer, '\n');
|
||||
entry[index] = common_Remove(entry[index], '\r');
|
||||
}
|
||||
|
||||
cartridge_title = database_GetValue(entry[0]);
|
||||
@@ -70,6 +82,51 @@ bool database_Load(std::string digest) {
|
||||
cartridge_controller[1] = common_ParseByte(database_GetValue(entry[4]));
|
||||
cartridge_region = common_ParseByte(database_GetValue(entry[5]));
|
||||
cartridge_flags = common_ParseUint(database_GetValue(entry[6]));
|
||||
|
||||
// Optionally load the lightgun crosshair offsets, hblank, dual analog
|
||||
for(int index = 7; index < count; index++)
|
||||
{
|
||||
if(entry[index].find("crossx") != std::string::npos)
|
||||
{
|
||||
cartridge_crosshair_x = common_ParseInt(database_GetValue(entry[index]));
|
||||
}
|
||||
if(entry[index].find("crossy") != std::string::npos)
|
||||
{
|
||||
cartridge_crosshair_y = common_ParseInt(database_GetValue(entry[index]));
|
||||
}
|
||||
if(entry[index].find("hblank") != std::string::npos)
|
||||
{
|
||||
cartridge_hblank = common_ParseInt(database_GetValue(entry[index]));
|
||||
}
|
||||
if(entry[index].find("dualanalog") != std::string::npos)
|
||||
{
|
||||
cartridge_dualanalog = common_ParseBool(database_GetValue(entry[index]));
|
||||
}
|
||||
if (entry[index].find("pokey450") != std::string::npos) {
|
||||
cartridge_pokey450 = common_ParseBool(database_GetValue(entry[index]));
|
||||
if (cartridge_pokey450) {
|
||||
cartridge_pokey = true;
|
||||
}
|
||||
}
|
||||
if (entry[index].find("xm") != std::string::npos) {
|
||||
cartridge_xm = common_ParseBool(database_GetValue(entry[index]));
|
||||
}
|
||||
if (entry[index].find("disablebios") != std::string::npos) {
|
||||
cartridge_disable_bios = common_ParseBool(database_GetValue(entry[index]));
|
||||
}
|
||||
if (entry[index].find("leftswitch") != std::string::npos) {
|
||||
cartridge_left_switch = common_ParseByte(database_GetValue(entry[index]));
|
||||
}
|
||||
if (entry[index].find("rightswitch") != std::string::npos) {
|
||||
cartridge_right_switch = common_ParseByte(database_GetValue(entry[index]));
|
||||
}
|
||||
if (entry[index].find("swapbuttons") != std::string::npos) {
|
||||
cartridge_swap_buttons = common_ParseBool(database_GetValue(entry[index]));
|
||||
}
|
||||
if (entry[index].find("hsc") != std::string::npos) {
|
||||
cartridge_hsc_enabled = common_ParseBool(database_GetValue(entry[index]));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -38,5 +38,6 @@ extern void database_Initialize( );
|
||||
extern bool database_Load(std::string digest);
|
||||
extern bool database_enabled;
|
||||
extern std::string database_filename;
|
||||
extern bool cart_in_db;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
Memory map:
|
||||
|
||||
POKEY1 $0450 $045F 16 bytes
|
||||
POKEY2* $0460 $046F 16 bytes
|
||||
XCTRL $0470 $047F 1 byte
|
||||
RAM $4000 $7FFF 16384 bytes
|
||||
|
||||
XCTRL Bit Description
|
||||
|
||||
+-------------------------------+
|
||||
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||
+-------------------------------+
|
||||
| | | | | | | |
|
||||
| | | | | | | +-- Bank select bit 0 \
|
||||
| | | | | | +------ Bank select bit 1 | Totally 128 KByte in 16 KByte banks
|
||||
| | | | | +---------- Bank select bit 3 /
|
||||
| | | | +-------------- Enable memory bit (1 = Memory enabled, 0 after power on)
|
||||
| | | +------------------ Enable POKEY bit** (1 = POKEY enabled, 0 after power on)
|
||||
| | |
|
||||
NA NA NA = Not Available or Not Used
|
||||
|
||||
* = Can be mounted piggy back on the first POKEY. Description how to do this will come when i have tried it out.
|
||||
** This bit controls both POKEY chip select signals.
|
||||
|
||||
|
||||
The mapping is totally non compatible with pretty much everything.
|
||||
There is a bank select latch located at $0470 and the POKEY is located at $0450
|
||||
(There's also a chip select output ($0460) on the PLD which alows you to simply piggy back a second POKEY).
|
||||
Since the PLD is reconfigurable I could map the POKEY (or the RAM for that matter) to pretty much anything
|
||||
if you wanted to. However since the PLD is soldered under the POKEY this needs to be configured before delivery.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "ExpansionModule.h"
|
||||
|
||||
byte xm_ram[XM_RAM_SIZE] = {0};
|
||||
byte xm_reg = 0;
|
||||
byte xm_bank = 0;
|
||||
bool xm_pokey_enabled = false;
|
||||
bool xm_mem_enabled = false;
|
||||
|
||||
void xm_Reset() {
|
||||
memset(xm_ram, 0, XM_RAM_SIZE);
|
||||
xm_bank = 0;
|
||||
xm_reg = 0;
|
||||
xm_pokey_enabled = false;
|
||||
xm_mem_enabled = false;
|
||||
}
|
||||
|
||||
byte xm_Read(word address) {
|
||||
if (xm_pokey_enabled && (address >= 0x0450 && address < 0x0460)) {
|
||||
byte b = pokey_GetRegister(0x4000 + (address - 0x0450));
|
||||
return b;
|
||||
} else if (xm_pokey_enabled && (address >= 0x0460 && address < 0x0470)) {
|
||||
byte b = pokey_GetRegister(0x4000 + (address - 0x0460));
|
||||
return b;
|
||||
} else if (xm_mem_enabled && (address >= 0x4000 && address < 0x8000)) {
|
||||
byte b = xm_ram[(xm_bank * 0x4000) + (address - 0x4000)];
|
||||
return b;
|
||||
} else if (address >= 0x0470 && address < 0x0480) {
|
||||
// TODO: Should the value be returned?
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void xm_Write(word address, byte data) {
|
||||
if (xm_pokey_enabled && (address >= 0x0450 && address < 0x0460)) {
|
||||
pokey_SetRegister(0x4000 + (address - 0x0450), data);
|
||||
} else if (xm_pokey_enabled && (address >= 0x0460 && address < 0x0470)) {
|
||||
pokey_SetRegister(0x4000 + (address - 0x0460), data);
|
||||
} else if (xm_mem_enabled && (address >= 0x4000 && address < 0x8000)) {
|
||||
|
||||
xm_ram[(xm_bank * 0x4000) + (address - 0x4000)] = data;
|
||||
} else if (address >= 0x0470 && address < 0x0480) {
|
||||
xm_reg = data;
|
||||
xm_bank = xm_reg & 7;
|
||||
xm_pokey_enabled = (xm_reg & 0x10) > 0;
|
||||
xm_mem_enabled = (xm_reg & 0x08) > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef EXPANSIONMODULE_H
|
||||
#define EXPANSIONMODULE_H
|
||||
|
||||
#include "Cartridge.h"
|
||||
#include "Memory.h"
|
||||
|
||||
#define XM_RAM_SIZE 0x20000
|
||||
|
||||
extern byte xm_ram[XM_RAM_SIZE];
|
||||
extern bool xm_pokey_enabled;
|
||||
extern bool xm_mem_enabled;
|
||||
extern byte xm_reg;
|
||||
extern byte xm_bank;
|
||||
|
||||
|
||||
void xm_Reset();
|
||||
byte xm_Read(word address);
|
||||
void xm_Write(word address, byte data);
|
||||
#endif
|
||||
@@ -27,7 +27,6 @@
|
||||
#define LOGGER_LEVEL_DEBUG 0
|
||||
#define LOGGER_LEVEL_INFO 1
|
||||
#define LOGGER_LEVEL_ERROR 2
|
||||
//#define NULL 0
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
+70
-30
@@ -5,7 +5,7 @@
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2005 Greg Stanton
|
||||
//
|
||||
//
|
||||
// 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
|
||||
@@ -37,7 +37,7 @@ static pair maria_dp;
|
||||
static pair maria_pp;
|
||||
static byte maria_horizontal;
|
||||
static byte maria_palette;
|
||||
static char maria_offset;
|
||||
static signed char maria_offset;
|
||||
static byte maria_h08;
|
||||
static byte maria_h16;
|
||||
static byte maria_wmode;
|
||||
@@ -45,12 +45,12 @@ static byte maria_wmode;
|
||||
// ----------------------------------------------------------------------------
|
||||
// StoreCell
|
||||
// ----------------------------------------------------------------------------
|
||||
static void maria_StoreCell(byte data) {
|
||||
static inline void maria_StoreCell(byte data) {
|
||||
if(maria_horizontal < MARIA_LINERAM_SIZE) {
|
||||
if(data) {
|
||||
maria_lineRAM[maria_horizontal] = maria_palette | data;
|
||||
}
|
||||
else {
|
||||
else {
|
||||
byte kmode = memory_ram[CTRL] & 4;
|
||||
if(kmode) {
|
||||
maria_lineRAM[maria_horizontal] = 0;
|
||||
@@ -63,12 +63,12 @@ static void maria_StoreCell(byte data) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// StoreCell
|
||||
// ----------------------------------------------------------------------------
|
||||
static void maria_StoreCell(byte high, byte low) {
|
||||
static inline void maria_StoreCell(byte high, byte low) {
|
||||
if(maria_horizontal < MARIA_LINERAM_SIZE) {
|
||||
if(low || high) {
|
||||
maria_lineRAM[maria_horizontal] = maria_palette & 16 | high | low;
|
||||
maria_lineRAM[maria_horizontal] = (maria_palette & 16) | high | low;
|
||||
}
|
||||
else {
|
||||
else {
|
||||
byte kmode = memory_ram[CTRL] & 4;
|
||||
if(kmode) {
|
||||
maria_lineRAM[maria_horizontal] = 0;
|
||||
@@ -81,7 +81,7 @@ static void maria_StoreCell(byte high, byte low) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// IsHolyDMA
|
||||
// ----------------------------------------------------------------------------
|
||||
static bool maria_IsHolyDMA( ) {
|
||||
static inline bool maria_IsHolyDMA( ) {
|
||||
if(maria_pp.w > 32767) {
|
||||
if(maria_h16 && (maria_pp.w & 4096)) {
|
||||
return true;
|
||||
@@ -96,7 +96,7 @@ static bool maria_IsHolyDMA( ) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// GetColor
|
||||
// ----------------------------------------------------------------------------
|
||||
static byte maria_GetColor(byte data) {
|
||||
static inline byte maria_GetColor(byte data) {
|
||||
if(data & 3) {
|
||||
return memory_ram[BACKGRND + data];
|
||||
}
|
||||
@@ -108,12 +108,15 @@ static byte maria_GetColor(byte data) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// StoreGraphic
|
||||
// ----------------------------------------------------------------------------
|
||||
static void maria_StoreGraphic( ) {
|
||||
static inline void maria_StoreGraphic( ) {
|
||||
byte data = memory_ram[maria_pp.w];
|
||||
if(maria_wmode) {
|
||||
if(maria_IsHolyDMA( )) {
|
||||
#if 0 // Wii: disabled due to rendering in Kangaroo mode
|
||||
maria_StoreCell(0, 0);
|
||||
maria_StoreCell(0, 0);
|
||||
#endif
|
||||
maria_horizontal+=2;
|
||||
}
|
||||
else {
|
||||
maria_StoreCell((data & 12), (data & 192) >> 6);
|
||||
@@ -122,10 +125,13 @@ static void maria_StoreGraphic( ) {
|
||||
}
|
||||
else {
|
||||
if(maria_IsHolyDMA( )) {
|
||||
#if 0 // Wii: disabled due to rendering in Kangaroo mode
|
||||
maria_StoreCell(0);
|
||||
maria_StoreCell(0);
|
||||
maria_StoreCell(0);
|
||||
maria_StoreCell(0);
|
||||
#endif
|
||||
maria_horizontal+=4;
|
||||
}
|
||||
else {
|
||||
maria_StoreCell((data & 192) >> 6);
|
||||
@@ -140,12 +146,13 @@ static void maria_StoreGraphic( ) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// WriteLineRAM
|
||||
// ----------------------------------------------------------------------------
|
||||
static void maria_WriteLineRAM(byte* buffer) {
|
||||
static inline void maria_WriteLineRAM(byte* buffer) {
|
||||
byte rmode = memory_ram[CTRL] & 3;
|
||||
if(rmode == 0) {
|
||||
// 160A/B
|
||||
int pixel = 0;
|
||||
for(int index = 0; index < MARIA_LINERAM_SIZE; index += 4) {
|
||||
byte color;
|
||||
word color;
|
||||
color = maria_GetColor(maria_lineRAM[index + 0]);
|
||||
buffer[pixel++] = color;
|
||||
buffer[pixel++] = color;
|
||||
@@ -160,7 +167,8 @@ static void maria_WriteLineRAM(byte* buffer) {
|
||||
buffer[pixel++] = color;
|
||||
}
|
||||
}
|
||||
else if(rmode == 2) {
|
||||
else if(rmode == 2) {
|
||||
// 320B/D
|
||||
int pixel = 0;
|
||||
for(int index = 0; index < MARIA_LINERAM_SIZE; index += 4) {
|
||||
buffer[pixel++] = maria_GetColor((maria_lineRAM[index + 0] & 16) | ((maria_lineRAM[index + 0] & 8) >> 3) | ((maria_lineRAM[index + 0] & 2)));
|
||||
@@ -174,6 +182,7 @@ static void maria_WriteLineRAM(byte* buffer) {
|
||||
}
|
||||
}
|
||||
else if(rmode == 3) {
|
||||
// 320A/C
|
||||
int pixel = 0;
|
||||
for(int index = 0; index < MARIA_LINERAM_SIZE; index += 4) {
|
||||
buffer[pixel++] = maria_GetColor((maria_lineRAM[index + 0] & 30));
|
||||
@@ -191,29 +200,29 @@ static void maria_WriteLineRAM(byte* buffer) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// StoreLineRAM
|
||||
// ----------------------------------------------------------------------------
|
||||
static void maria_StoreLineRAM( ) {
|
||||
static inline void maria_StoreLineRAM( ) {
|
||||
for(int index = 0; index < MARIA_LINERAM_SIZE; index++) {
|
||||
maria_lineRAM[index] = 0;
|
||||
}
|
||||
|
||||
|
||||
byte mode = memory_ram[maria_dp.w + 1];
|
||||
while(mode & 0x5f) {
|
||||
byte width;
|
||||
byte indirect = 0;
|
||||
|
||||
|
||||
maria_pp.b.l = memory_ram[maria_dp.w];
|
||||
maria_pp.b.h = memory_ram[maria_dp.w + 2];
|
||||
|
||||
if(mode & 31) {
|
||||
maria_cycles += 8;
|
||||
|
||||
if(mode & 31) {
|
||||
maria_cycles += 8; // Maria cycles (Header 4 byte)
|
||||
maria_palette = (memory_ram[maria_dp.w + 1] & 224) >> 3;
|
||||
maria_horizontal = memory_ram[maria_dp.w + 3];
|
||||
width = memory_ram[maria_dp.w + 1] & 31;
|
||||
width = ((~width) & 31) + 1;
|
||||
maria_dp.w += 4;
|
||||
}
|
||||
else {
|
||||
maria_cycles += 10;
|
||||
else {
|
||||
maria_cycles += 12; // Maria cycles (Header 5 byte)
|
||||
maria_palette = (memory_ram[maria_dp.w + 3] & 224) >> 3;
|
||||
maria_horizontal = memory_ram[maria_dp.w + 4];
|
||||
indirect = memory_ram[maria_dp.w + 1] & 32;
|
||||
@@ -226,7 +235,7 @@ static void maria_StoreLineRAM( ) {
|
||||
if(!indirect) {
|
||||
maria_pp.b.h += maria_offset;
|
||||
for(int index = 0; index < width; index++) {
|
||||
maria_cycles += 3;
|
||||
maria_cycles += 3; // Maria cycles (Direct graphic read)
|
||||
maria_StoreGraphic( );
|
||||
}
|
||||
}
|
||||
@@ -234,14 +243,13 @@ static void maria_StoreLineRAM( ) {
|
||||
byte cwidth = memory_ram[CTRL] & 16;
|
||||
pair basePP = maria_pp;
|
||||
for(int index = 0; index < width; index++) {
|
||||
maria_cycles += 3;
|
||||
maria_cycles += 3; // Maria cycles (Indirect)
|
||||
maria_pp.b.l = memory_ram[basePP.w++];
|
||||
maria_pp.b.h = memory_ram[CHARBASE] + maria_offset;
|
||||
|
||||
maria_cycles += 6;
|
||||
maria_cycles += 3; // Maria cycles (Indirect, 1 byte)
|
||||
maria_StoreGraphic( );
|
||||
if(cwidth) {
|
||||
maria_cycles += 3;
|
||||
maria_cycles += 3; // Maria cycles (Indirect, 2 bytes)
|
||||
maria_StoreGraphic( );
|
||||
}
|
||||
}
|
||||
@@ -258,6 +266,17 @@ void maria_Reset( ) {
|
||||
for(int index = 0; index < MARIA_SURFACE_SIZE; index++) {
|
||||
maria_surface[index] = 0;
|
||||
}
|
||||
|
||||
maria_cycles = 0;
|
||||
maria_dpp.w = 0;
|
||||
maria_dp.w = 0;
|
||||
maria_pp.w = 0;
|
||||
maria_horizontal = 0;
|
||||
maria_palette = 0;
|
||||
maria_offset = 0;
|
||||
maria_h08 = 0;
|
||||
maria_h16 = 0;
|
||||
maria_wmode = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -265,10 +284,24 @@ void maria_Reset( ) {
|
||||
// ----------------------------------------------------------------------------
|
||||
uint maria_RenderScanline( ) {
|
||||
maria_cycles = 0;
|
||||
|
||||
// lightgun flash
|
||||
// Displays the background color when Maria is disabled (if applicable)
|
||||
if( ( ( memory_ram[CTRL] & 96 ) != 64 ) &&
|
||||
maria_scanline >= maria_visibleArea.top &&
|
||||
maria_scanline <= maria_visibleArea.bottom ) {
|
||||
byte bgcolor = maria_GetColor(0);
|
||||
byte *bgstart = maria_surface + ((maria_scanline - maria_displayArea.top) * maria_displayArea.GetLength());
|
||||
for(uint index = 0; index < MARIA_LINERAM_SIZE; index++ ) {
|
||||
*bgstart++ = bgcolor;
|
||||
*bgstart++ = bgcolor;
|
||||
}
|
||||
}
|
||||
|
||||
if((memory_ram[CTRL] & 96) == 64 && maria_scanline >= maria_displayArea.top && maria_scanline <= maria_displayArea.bottom) {
|
||||
maria_cycles += 31;
|
||||
maria_cycles += 5; // Maria cycles (DMA Startup)
|
||||
if(maria_scanline == maria_displayArea.top) {
|
||||
maria_cycles += 7;
|
||||
maria_cycles += 10; // Maria cycles (End of VBLANK)
|
||||
maria_dpp.b.l = memory_ram[DPPL];
|
||||
maria_dpp.b.h = memory_ram[DPPH];
|
||||
maria_h08 = memory_ram[maria_dpp.w] & 32;
|
||||
@@ -277,6 +310,7 @@ uint maria_RenderScanline( ) {
|
||||
maria_dp.b.l = memory_ram[maria_dpp.w + 2];
|
||||
maria_dp.b.h = memory_ram[maria_dpp.w + 1];
|
||||
if(memory_ram[maria_dpp.w] & 128) {
|
||||
maria_cycles += 20; // Maria cycles (NMI) /*29, 16, 20*/
|
||||
sally_ExecuteNMI( );
|
||||
}
|
||||
}
|
||||
@@ -289,15 +323,21 @@ uint maria_RenderScanline( ) {
|
||||
maria_StoreLineRAM( );
|
||||
maria_offset--;
|
||||
if(maria_offset < 0) {
|
||||
maria_cycles += 10; // Maria cycles (Last line of zone) /*20*/
|
||||
maria_dpp.w += 3;
|
||||
maria_h08 = memory_ram[maria_dpp.w] & 32;
|
||||
maria_h16 = memory_ram[maria_dpp.w] & 64;
|
||||
maria_offset = memory_ram[maria_dpp.w] & 15;
|
||||
if(memory_ram[maria_dpp.w] & 128) {
|
||||
maria_cycles += 20; // Maria cycles (NMI) /*29, 16, 20*/
|
||||
sally_ExecuteNMI( );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
maria_cycles += 4; // Maria cycles (Other lines of zone)
|
||||
}
|
||||
}
|
||||
}
|
||||
return maria_cycles;
|
||||
}
|
||||
@@ -309,4 +349,4 @@ void maria_Clear( ) {
|
||||
for(int index = 0; index < MARIA_SURFACE_SIZE; index++) {
|
||||
maria_surface[index] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+50
-14
@@ -5,7 +5,7 @@
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2005 Greg Stanton
|
||||
//
|
||||
//
|
||||
// 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
|
||||
@@ -23,6 +23,7 @@
|
||||
// Memory.cpp
|
||||
// ----------------------------------------------------------------------------
|
||||
#include "Memory.h"
|
||||
#include "ExpansionModule.h"
|
||||
|
||||
byte memory_ram[MEMORY_SIZE] = {0};
|
||||
byte memory_rom[MEMORY_SIZE] = {0};
|
||||
@@ -46,17 +47,32 @@ void memory_Reset( ) {
|
||||
byte memory_Read(word address) {
|
||||
byte tmp_byte;
|
||||
|
||||
if (cartridge_xm) {
|
||||
if ((address >= 0x0470 && address < 0x0480) ||
|
||||
(xm_pokey_enabled && (address >= 0x0450 && address < 0x0470)) ||
|
||||
(xm_mem_enabled && (address >= 0x4000 && address < 0x8000))) {
|
||||
return xm_Read(address);
|
||||
}
|
||||
}
|
||||
|
||||
if (cartridge_pokey && (
|
||||
(!cartridge_pokey450 && (address >= 0x4000 && address <= 0x400f)) ||
|
||||
(cartridge_pokey450 && (address >= 0x0450 && address < 0x0470)))) {
|
||||
return pokey_GetRegister(
|
||||
cartridge_pokey450 ? 0x4000 + (address - 0x0450) : address);
|
||||
}
|
||||
|
||||
switch ( address ) {
|
||||
case INTIM:
|
||||
case INTIM | 0x2:
|
||||
memory_ram[INTFLG] &= 0x7f;
|
||||
memory_ram[INTFLG] &= 0x7f;
|
||||
return memory_ram[INTIM];
|
||||
break;
|
||||
break;
|
||||
case INTFLG:
|
||||
case INTFLG | 0x2:
|
||||
tmp_byte = memory_ram[INTFLG];
|
||||
memory_ram[INTFLG] &= 0x7f;
|
||||
return tmp_byte;
|
||||
tmp_byte = memory_ram[INTFLG];
|
||||
memory_ram[INTFLG] &= 0x7f;
|
||||
return tmp_byte;
|
||||
break;
|
||||
default:
|
||||
return memory_ram[address];
|
||||
@@ -68,6 +84,22 @@ byte memory_Read(word address) {
|
||||
// Write
|
||||
// ----------------------------------------------------------------------------
|
||||
void memory_Write(word address, byte data) {
|
||||
if (cartridge_xm &&
|
||||
((address >= 0x0470 && address < 0x0480) ||
|
||||
((xm_pokey_enabled && (address >= 0x0450 && address < 0x0470)) ||
|
||||
(xm_mem_enabled && (address >= 0x4000 && address < 0x8000))))) {
|
||||
xm_Write(address, data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cartridge_pokey && (
|
||||
(!cartridge_pokey450 && (address >= 0x4000 && address <= 0x400f)) ||
|
||||
(cartridge_pokey450 && (address >= 0x0450 && address < 0x0470)))) {
|
||||
pokey_SetRegister(
|
||||
(cartridge_pokey450 ? 0x4000 + (address - 0x0450) : address), data);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!memory_rom[address]) {
|
||||
switch(address) {
|
||||
case WSYNC:
|
||||
@@ -76,8 +108,8 @@ void memory_Write(word address, byte data) {
|
||||
}
|
||||
break;
|
||||
case INPTCTRL:
|
||||
if(data == 22 && cartridge_IsLoaded( )) {
|
||||
cartridge_Store( );
|
||||
if(data == 22 && cartridge_IsLoaded( )) {
|
||||
cartridge_Store( );
|
||||
}
|
||||
else if(data == 2 && bios_enabled) {
|
||||
bios_Store( );
|
||||
@@ -113,10 +145,13 @@ void memory_Write(word address, byte data) {
|
||||
case AUDV1:
|
||||
tia_SetRegister(AUDV1, data);
|
||||
break;
|
||||
case SWCHB:
|
||||
break;
|
||||
case CTLSWB:
|
||||
break;
|
||||
case SWCHA: /*gdement: Writing here actually writes to DRA inside the RIOT chip.
|
||||
This value only indirectly affects output of SWCHA. Ditto for SWCHB.*/
|
||||
riot_SetDRA(data);
|
||||
break;
|
||||
case SWCHB:
|
||||
riot_SetDRB(data);
|
||||
break;
|
||||
case TIM1T:
|
||||
case TIM1T | 0x8:
|
||||
riot_SetTimer(TIM1T, data);
|
||||
@@ -148,6 +183,7 @@ void memory_Write(word address, byte data) {
|
||||
memory_ram[address + 8192] = data;
|
||||
}
|
||||
break;
|
||||
/*TODO: gdement: test here for debug port. Don't put it in the switch because that will change behavior.*/
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -158,7 +194,7 @@ void memory_Write(word address, byte data) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// WriteROM
|
||||
// ----------------------------------------------------------------------------
|
||||
void memory_WriteROM(word address, word size, const byte* data) {
|
||||
void memory_WriteROM(word address, uint size, const byte* data) {
|
||||
if((address + size) <= MEMORY_SIZE && data != NULL) {
|
||||
for(uint index = 0; index < size; index++) {
|
||||
memory_ram[address + index] = data[index];
|
||||
@@ -170,7 +206,7 @@ void memory_WriteROM(word address, word size, const byte* data) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// ClearROM
|
||||
// ----------------------------------------------------------------------------
|
||||
void memory_ClearROM(word address, word size) {
|
||||
void memory_ClearROM(word address, uint size) {
|
||||
if((address + size) <= MEMORY_SIZE) {
|
||||
for(uint index = 0; index < size; index++) {
|
||||
memory_ram[address + index] = 0;
|
||||
|
||||
+3
-4
@@ -5,7 +5,7 @@
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2005 Greg Stanton
|
||||
//
|
||||
//
|
||||
// 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
|
||||
@@ -25,7 +25,6 @@
|
||||
#ifndef MEMORY_H
|
||||
#define MEMORY_H
|
||||
#define MEMORY_SIZE 65536
|
||||
//#define NULL 0
|
||||
|
||||
#include "Equates.h"
|
||||
#include "Bios.h"
|
||||
@@ -40,8 +39,8 @@ typedef unsigned int uint;
|
||||
extern void memory_Reset( );
|
||||
extern byte memory_Read(word address);
|
||||
extern void memory_Write(word address, byte data);
|
||||
extern void memory_WriteROM(word address, word size, const byte* data);
|
||||
extern void memory_ClearROM(word address, word size);
|
||||
extern void memory_WriteROM(word address, uint size, const byte* data);
|
||||
extern void memory_ClearROM(word address, uint size);
|
||||
extern byte memory_ram[MEMORY_SIZE];
|
||||
extern byte memory_rom[MEMORY_SIZE];
|
||||
|
||||
|
||||
+5
-5
@@ -68,12 +68,12 @@ byte palette_data[PALETTE_SIZE] = {
|
||||
0x00,0x71,0xC6,0x00,0x86,0xD0,0x0A,0x9B,0xDF,0x1A,0xA8,0xEC,
|
||||
0x2B,0xB6,0xFF,0x3F,0xC2,0xFF,0x45,0xCB,0xFF,0x59,0xD3,0xFF,
|
||||
0x7F,0xDA,0xFF,0x8F,0xDE,0xFF,0xA0,0xE2,0xFF,0xB0,0xEB,0xFF,
|
||||
0x00,0x4A,0x00,0x00,0x4C,0x00,0x00,0x6A,0x20,0x50,0x8E,0x79,
|
||||
0x40,0x99,0x99,0x00,0x9C,0xAA,0x00,0xA1,0xBB,0x01,0xA4,0xCC,
|
||||
0x03,0xA5,0xD7,0x05,0xDA,0xE2,0x18,0xE5,0xFF,0x34,0xEA,0xFF,
|
||||
0x00,0x38,0x39,0x00,0x3C,0x48,0x00,0x3D,0x5B,0x02,0x66,0x7F,
|
||||
0x03,0x73,0x83,0x00,0x9C,0xAA,0x00,0xA1,0xBB,0x01,0xA4,0xCC,
|
||||
0x03,0xBB,0xFF,0x05,0xDA,0xE2,0x18,0xE5,0xFF,0x34,0xEA,0xFF,
|
||||
0x49,0xEF,0xFF,0x66,0xF2,0xFF,0x84,0xF4,0xFF,0x9E,0xF9,0xFF,
|
||||
0x00,0x4A,0x00,0x00,0x5D,0x00,0x00,0x70,0x00,0x00,0x83,0x00,
|
||||
0x00,0x95,0x00,0x00,0xAB,0x00,0x07,0xBD,0x07,0x0A,0xD0,0x0A,
|
||||
0x00,0x4A,0x00,0x00,0x5D,0x00,0x00,0x70,0x00,0x00,0x8B,0x00,
|
||||
0x00,0xA9,0x00,0x00,0xBB,0x05,0x00,0xBD,0x00,0x02,0xD0,0x05,
|
||||
0x1A,0xD5,0x40,0x5A,0xF1,0x77,0x82,0xEF,0xA7,0x84,0xED,0xD1,
|
||||
0x89,0xFF,0xED,0x7D,0xFF,0xFF,0x93,0xFF,0xFF,0x9B,0xFF,0xFF,
|
||||
0x22,0x4A,0x03,0x27,0x53,0x04,0x30,0x64,0x05,0x3C,0x77,0x0C,
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#ifndef PALETTE_H
|
||||
#define PALETTE_H
|
||||
#define PALETTE_SIZE 768
|
||||
//#define NULL 0
|
||||
|
||||
#include <string>
|
||||
#include "Logger.h"
|
||||
|
||||
+182
-35
@@ -5,7 +5,7 @@
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2005 Greg Stanton
|
||||
//
|
||||
//
|
||||
// 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
|
||||
@@ -21,31 +21,33 @@
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
// ----------------------------------------------------------------------------
|
||||
// PokeySound is Copyright(c) 1997 by Ron Fries
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of version 2 of the GNU Library General Public License
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
|
||||
// General Public License for more details.
|
||||
// To obtain a copy of the GNU Library General Public License, write to the
|
||||
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// Any permitted reproduction of these routines, in whole or in part, must
|
||||
// bear this legend.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of version 2 of the GNU Library General Public License
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
|
||||
// General Public License for more details.
|
||||
// To obtain a copy of the GNU Library General Public License, write to the
|
||||
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// Any permitted reproduction of these routines, in whole or in part, must
|
||||
// bear this legend.
|
||||
// ----------------------------------------------------------------------------
|
||||
// Pokey.cpp
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "Pokey.h"
|
||||
#include "ProSystem.h"
|
||||
#define POKEY_NOTPOLY5 0x80
|
||||
#define POKEY_POLY4 0x40
|
||||
#define POKEY_PURE 0x20
|
||||
#define POKEY_VOLUME_ONLY 0x10
|
||||
#define POKEY_VOLUME_MASK 0x0f
|
||||
#define POKEY_POLY9 0x80
|
||||
#define POKEY_POLY9 0x80
|
||||
#define POKEY_CH1_179 0x40
|
||||
#define POKEY_CH3_179 0x20
|
||||
#define POKEY_CH1_CH2 0x10
|
||||
@@ -65,8 +67,10 @@
|
||||
#define POKEY_CHANNEL4 3
|
||||
#define POKEY_SAMPLE 4
|
||||
|
||||
#define SK_RESET 0x03
|
||||
|
||||
byte pokey_buffer[POKEY_BUFFER_SIZE] = {0};
|
||||
uint pokey_size = 524;
|
||||
uint pokey_size = (POKEY_BUFFER_SIZE - 512); // 524 previously
|
||||
|
||||
static uint pokey_frequency = 1787520;
|
||||
static uint pokey_sampleRate = 31440;
|
||||
@@ -90,10 +94,47 @@ static uint pokey_sampleMax;
|
||||
static uint pokey_sampleCount[2];
|
||||
static uint pokey_baseMultiplier;
|
||||
|
||||
static byte rand9[0x1ff];
|
||||
static byte rand17[0x1ffff];
|
||||
static uint r9;
|
||||
static uint r17;
|
||||
static byte SKCTL;
|
||||
byte RANDOM;
|
||||
|
||||
byte POT_input[8] = {228, 228, 228, 228, 228, 228, 228, 228};
|
||||
static int pot_scanline;
|
||||
|
||||
static ulong random_scanline_counter;
|
||||
static ulong prev_random_scanline_counter;
|
||||
|
||||
static void rand_init(byte *rng, int size, int left, int right, int add)
|
||||
{
|
||||
int mask = (1 << size) - 1;
|
||||
int i, x = 0;
|
||||
|
||||
for( i = 0; i < mask; i++ )
|
||||
{
|
||||
if (size == 17)
|
||||
*rng = x >> 6; /* use bits 6..13 */
|
||||
else
|
||||
*rng = x; /* use bits 0..7 */
|
||||
rng++;
|
||||
/* calculate next bit */
|
||||
x = ((x << left) + (x >> right) + add) & mask;
|
||||
}
|
||||
}
|
||||
|
||||
void pokey_setSampleRate( uint rate ) {
|
||||
pokey_sampleRate = rate;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Reset
|
||||
// ----------------------------------------------------------------------------
|
||||
void pokey_Reset( ) {
|
||||
pot_scanline = 0;
|
||||
pokey_soundCntr = 0;
|
||||
|
||||
for(int index = 0; index < POKEY_POLY17_SIZE; index++) {
|
||||
pokey_poly17[index] = rand( ) & 1;
|
||||
}
|
||||
@@ -118,16 +159,108 @@ void pokey_Reset( ) {
|
||||
pokey_audf[channel] = 0;
|
||||
}
|
||||
|
||||
for(int i = 0; i < 8; i++) {
|
||||
POT_input[i] = 228;
|
||||
}
|
||||
|
||||
pokey_audctl = 0;
|
||||
pokey_baseMultiplier = POKEY_DIV_64;
|
||||
}
|
||||
|
||||
/* initialize the random arrays */
|
||||
rand_init(rand9, 9, 8, 1, 0x00180);
|
||||
rand_init(rand17, 17,16, 1, 0x1c000);
|
||||
|
||||
SKCTL = SK_RESET;
|
||||
RANDOM = 0;
|
||||
|
||||
r9 = 0;
|
||||
r17 = 0;
|
||||
random_scanline_counter = 0;
|
||||
prev_random_scanline_counter = 0;
|
||||
}
|
||||
|
||||
/* Called prior to each frame */
|
||||
void pokey_Frame() {
|
||||
}
|
||||
|
||||
/* Called prior to each scanline */
|
||||
void pokey_Scanline() {
|
||||
random_scanline_counter += CYCLES_PER_SCANLINE;
|
||||
|
||||
if (pot_scanline < 228)
|
||||
pot_scanline++;
|
||||
}
|
||||
|
||||
byte pokey_GetRegister(word address) {
|
||||
byte data = 0;
|
||||
|
||||
byte addr = address & 0x0f;
|
||||
if (addr < 8) {
|
||||
byte b = POT_input[addr];
|
||||
if (b <= pot_scanline)
|
||||
return b;
|
||||
return pot_scanline;
|
||||
}
|
||||
|
||||
switch (address) {
|
||||
case POKEY_ALLPOT: {
|
||||
byte b = 0;
|
||||
for (int i = 0; i < 8; i++)
|
||||
if (POT_input[addr] <= pot_scanline)
|
||||
b &= ~(1 << i); /* reset bit if pot value known */
|
||||
return b;
|
||||
}
|
||||
case POKEY_RANDOM:
|
||||
ulong curr_scanline_counter =
|
||||
( random_scanline_counter + prosystem_cycles + prosystem_extra_cycles );
|
||||
|
||||
if( SKCTL & SK_RESET )
|
||||
{
|
||||
ulong adjust = ( ( curr_scanline_counter - prev_random_scanline_counter ) >> 2 );
|
||||
r9 = (uint)((adjust + r9) % 0x001ff);
|
||||
r17 = (uint)((adjust + r17) % 0x1ffff);
|
||||
}
|
||||
else
|
||||
{
|
||||
r9 = 0;
|
||||
r17 = 0;
|
||||
}
|
||||
if( pokey_audctl & POKEY_POLY9 )
|
||||
{
|
||||
RANDOM = rand9[r9];
|
||||
}
|
||||
else
|
||||
{
|
||||
RANDOM = rand17[r17];
|
||||
}
|
||||
|
||||
prev_random_scanline_counter = curr_scanline_counter;
|
||||
|
||||
RANDOM = RANDOM ^ 0xff;
|
||||
data = RANDOM;
|
||||
break;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// SetRegister
|
||||
// ----------------------------------------------------------------------------
|
||||
void pokey_SetRegister(word address, byte value) {
|
||||
byte channelMask;
|
||||
byte channelMask;
|
||||
switch(address) {
|
||||
case POKEY_POTGO:
|
||||
if (!(SKCTL & 4))
|
||||
pot_scanline = 0; /* slow pot mode */
|
||||
return;
|
||||
|
||||
case POKEY_SKCTLS:
|
||||
SKCTL = value;
|
||||
if (value & 4)
|
||||
pot_scanline = 228; /* fast pot mode - return results immediately */
|
||||
return;
|
||||
|
||||
case POKEY_AUDF1:
|
||||
pokey_audf[POKEY_CHANNEL1] = value;
|
||||
channelMask = 1 << POKEY_CHANNEL1;
|
||||
@@ -135,7 +268,7 @@ void pokey_SetRegister(word address, byte value) {
|
||||
channelMask |= 1 << POKEY_CHANNEL2;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case POKEY_AUDC1:
|
||||
pokey_audc[POKEY_CHANNEL1] = value;
|
||||
channelMask = 1 << POKEY_CHANNEL1;
|
||||
@@ -196,7 +329,7 @@ void pokey_SetRegister(word address, byte value) {
|
||||
channelMask = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
uint newValue = 0;
|
||||
|
||||
if(channelMask & (1 << POKEY_CHANNEL1)) {
|
||||
@@ -244,7 +377,7 @@ void pokey_SetRegister(word address, byte value) {
|
||||
}
|
||||
if(newValue!= pokey_divideMax[POKEY_CHANNEL3]) {
|
||||
pokey_divideMax[POKEY_CHANNEL3] = newValue;
|
||||
if(pokey_divideCount[POKEY_CHANNEL3] > newValue) {
|
||||
if(pokey_divideCount[POKEY_CHANNEL3] > newValue) {
|
||||
pokey_divideCount[POKEY_CHANNEL3] = newValue;
|
||||
}
|
||||
}
|
||||
@@ -266,19 +399,25 @@ void pokey_SetRegister(word address, byte value) {
|
||||
pokey_divideMax[POKEY_CHANNEL4] = newValue;
|
||||
if(pokey_divideCount[POKEY_CHANNEL4] > newValue) {
|
||||
pokey_divideCount[POKEY_CHANNEL4] = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(byte channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) {
|
||||
if(channelMask & (1 << channel)) {
|
||||
if((pokey_audc[channel] & POKEY_VOLUME_ONLY) || ((pokey_audc[channel] & POKEY_VOLUME_MASK) == 0) || (pokey_divideMax[channel] < (pokey_sampleMax >> 8))) {
|
||||
if((pokey_audc[channel] & POKEY_VOLUME_ONLY) ||
|
||||
((pokey_audc[channel] & POKEY_VOLUME_MASK) == 0) ||
|
||||
(pokey_divideMax[channel] < (pokey_sampleMax >> 8))) {
|
||||
#if 1 // WII
|
||||
pokey_outVol[channel] = 1;
|
||||
#else
|
||||
pokey_outVol[channel] = pokey_audc[channel] & POKEY_VOLUME_MASK;
|
||||
#endif
|
||||
pokey_divideCount[channel] = 0x7fffffff;
|
||||
pokey_divideMax[channel] = 0x7fffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -286,13 +425,18 @@ void pokey_SetRegister(word address, byte value) {
|
||||
// ----------------------------------------------------------------------------
|
||||
void pokey_Process(uint length) {
|
||||
byte* buffer = pokey_buffer + pokey_soundCntr;
|
||||
uint* sampleCntrPtr = (uint*)((byte*)(&pokey_sampleCount[0]) + 1);
|
||||
//#ifdef BIG_ENDIAN
|
||||
// uint* sampleCntrPtrB = (uint*)((byte*)&pokey_sampleCount[0] + 3);
|
||||
//#else
|
||||
uint* sampleCntrPtrB = (uint*)((byte*)&pokey_sampleCount[0] + 1);
|
||||
//#endif
|
||||
uint size = length;
|
||||
|
||||
while(length) {
|
||||
|
||||
byte currentValue;
|
||||
byte nextEvent = POKEY_SAMPLE;
|
||||
uint eventMin = *sampleCntrPtr;
|
||||
uint eventMin = *sampleCntrPtrB;
|
||||
|
||||
byte channel;
|
||||
for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) {
|
||||
@@ -301,12 +445,12 @@ void pokey_Process(uint length) {
|
||||
nextEvent = channel;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) {
|
||||
pokey_divideCount[channel] -= eventMin;
|
||||
}
|
||||
|
||||
*sampleCntrPtr -= eventMin;
|
||||
*sampleCntrPtrB -= eventMin;
|
||||
pokey_polyAdjust += eventMin;
|
||||
|
||||
if(nextEvent != POKEY_SAMPLE) {
|
||||
@@ -336,7 +480,11 @@ void pokey_Process(uint length) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
//#ifdef BIG_ENDIAN
|
||||
// *(pokey_sampleCount + 1) += pokey_sampleMax;
|
||||
//#else
|
||||
*pokey_sampleCount += pokey_sampleMax;
|
||||
//#endif
|
||||
currentValue = 0;
|
||||
|
||||
for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) {
|
||||
@@ -347,8 +495,8 @@ void pokey_Process(uint length) {
|
||||
*buffer++ = currentValue;
|
||||
length--;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pokey_soundCntr += size;
|
||||
if(pokey_soundCntr >= pokey_size) {
|
||||
pokey_soundCntr = 0;
|
||||
@@ -359,7 +507,6 @@ void pokey_Process(uint length) {
|
||||
// Clear
|
||||
// ----------------------------------------------------------------------------
|
||||
void pokey_Clear( ) {
|
||||
for(int index = 0; index < POKEY_BUFFER_SIZE; index++) {
|
||||
pokey_buffer[index] = 0;
|
||||
}
|
||||
}
|
||||
pokey_soundCntr = 0;
|
||||
memset(pokey_buffer, 0, POKEY_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
@@ -50,16 +50,43 @@
|
||||
#define POKEY_AUDF4 0x4006
|
||||
#define POKEY_AUDC4 0x4007
|
||||
#define POKEY_AUDCTL 0x4008
|
||||
#define POKEY_STIMER 0x4009
|
||||
#define POKEY_SKRES 0x400a
|
||||
#define POKEY_POTGO 0x400b
|
||||
#define POKEY_SEROUT 0x400d
|
||||
#define POKEY_IRQEN 0x400e
|
||||
#define POKEY_SKCTLS 0x400f
|
||||
|
||||
#define POKEY_POT0 0x4000
|
||||
#define POKEY_POT1 0x4001
|
||||
#define POKEY_POT2 0x4002
|
||||
#define POKEY_POT3 0x4003
|
||||
#define POKEY_POT4 0x4004
|
||||
#define POKEY_POT5 0x4005
|
||||
#define POKEY_POT6 0x4006
|
||||
#define POKEY_POT7 0x4007
|
||||
#define POKEY_ALLPOT 0x4008
|
||||
#define POKEY_KBCODE 0x4009
|
||||
#define POKEY_RANDOM 0x400a
|
||||
#define POKEY_SERIN 0x400d
|
||||
#define POKEY_IRQST 0x400e
|
||||
#define POKEY_SKSTAT 0x400f
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short word;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned long long ulong;
|
||||
|
||||
extern void pokey_Reset( );
|
||||
extern void pokey_SetRegister(word address, byte value);
|
||||
extern byte pokey_GetRegister(word address);
|
||||
extern void pokey_Process(uint length);
|
||||
extern void pokey_Clear( );
|
||||
extern byte pokey_buffer[POKEY_BUFFER_SIZE];
|
||||
extern uint pokey_size;
|
||||
|
||||
extern void pokey_Frame();
|
||||
extern void pokey_Scanline();
|
||||
extern void pokey_setSampleRate(uint rate);
|
||||
|
||||
#endif
|
||||
|
||||
+378
-67
@@ -32,6 +32,12 @@ word prosystem_frequency = 60;
|
||||
byte prosystem_frame = 0;
|
||||
word prosystem_scanlines = 262;
|
||||
uint prosystem_cycles = 0;
|
||||
int lightgun_scanline = 0;
|
||||
float lightgun_cycle = 0;
|
||||
|
||||
// Whether the last CPU operation resulted in a half cycle (need to take it
|
||||
// into consideration)
|
||||
extern bool half_cycle;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Reset
|
||||
@@ -40,15 +46,17 @@ void prosystem_Reset( ) {
|
||||
if(cartridge_IsLoaded( )) {
|
||||
prosystem_paused = false;
|
||||
prosystem_frame = 0;
|
||||
sally_Reset( );
|
||||
region_Reset( );
|
||||
tia_Clear( );
|
||||
tia_Reset( );
|
||||
pokey_Clear( );
|
||||
pokey_Reset( );
|
||||
xm_Reset( );
|
||||
memory_Reset( );
|
||||
maria_Clear( );
|
||||
maria_Reset( );
|
||||
riot_Reset ( );
|
||||
riot_Reset( );
|
||||
if(bios_enabled) {
|
||||
bios_Store( );
|
||||
}
|
||||
@@ -60,57 +68,142 @@ void prosystem_Reset( ) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Strobe based on the current lightgun location
|
||||
*/
|
||||
static void prosystem_FireLightGun()
|
||||
{
|
||||
if( ( ( maria_scanline >= lightgun_scanline ) &&
|
||||
( maria_scanline <= ( lightgun_scanline + 3 ) ) ) &&
|
||||
( prosystem_cycles >= ((int)lightgun_cycle ) - 1 ) )
|
||||
{
|
||||
memory_ram[INPT4] &= 0x7f;
|
||||
}
|
||||
else
|
||||
{
|
||||
memory_ram[INPT4] |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
uint prosystem_extra_cycles = 0;
|
||||
// ----------------------------------------------------------------------------
|
||||
// ExecuteFrame
|
||||
// ----------------------------------------------------------------------------
|
||||
void prosystem_ExecuteFrame(const byte* input) {
|
||||
// Is WSYNC enabled for the current frame?
|
||||
bool wsync = !(cartridge_flags & CARTRIDGE_WSYNC_MASK);
|
||||
|
||||
// Is Maria cycle stealing enabled for the current frame?
|
||||
bool cycle_stealing = !(cartridge_flags & CARTRIDGE_CYCLE_STEALING_MASK);
|
||||
|
||||
// Is the lightgun enabled for the current frame?
|
||||
bool lightgun = ((cartridge_controller[0] & CARTRIDGE_CONTROLLER_LIGHTGUN) && (memory_ram[CTRL] & 96) != 64);
|
||||
|
||||
riot_SetInput(input);
|
||||
|
||||
|
||||
prosystem_extra_cycles = 0;
|
||||
|
||||
if(cartridge_pokey || cartridge_xm) pokey_Frame();
|
||||
|
||||
for(maria_scanline = 1; maria_scanline <= prosystem_scanlines; maria_scanline++) {
|
||||
if(maria_scanline == maria_displayArea.top) {
|
||||
memory_ram[MSTAT] = 0;
|
||||
}
|
||||
if(maria_scanline == maria_displayArea.bottom) {
|
||||
else if(maria_scanline == maria_displayArea.bottom) {
|
||||
memory_ram[MSTAT] = 128;
|
||||
}
|
||||
|
||||
uint cycles;
|
||||
prosystem_cycles %= 456;
|
||||
while(prosystem_cycles < 28) {
|
||||
|
||||
// Was a WSYNC performed withing the current scanline?
|
||||
bool wsync_scanline = false;
|
||||
|
||||
uint cycles = 0;
|
||||
|
||||
if(!cycle_stealing || (memory_ram[CTRL] & 96 ) != 64) {
|
||||
// Exact cycle counts when Maria is disabled
|
||||
prosystem_cycles %= CYCLES_PER_SCANLINE;
|
||||
prosystem_extra_cycles = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
prosystem_extra_cycles = (prosystem_cycles % CYCLES_PER_SCANLINE);
|
||||
|
||||
// Some fudge for Maria cycles. Unfortunately Maria cycle counting
|
||||
// isn't exact (This adds some extra cycles).
|
||||
prosystem_cycles = 0;
|
||||
}
|
||||
|
||||
// If lightgun is enabled, check to see if it should be fired
|
||||
if(lightgun) prosystem_FireLightGun();
|
||||
|
||||
while(prosystem_cycles < cartridge_hblank) {
|
||||
cycles = sally_ExecuteInstruction( );
|
||||
prosystem_cycles += (cycles << 2);
|
||||
if(half_cycle) prosystem_cycles += 2;
|
||||
|
||||
if(riot_timing) {
|
||||
riot_UpdateTimer(cycles);
|
||||
}
|
||||
if(memory_ram[WSYNC] && !(cartridge_flags & CARTRIDGE_WSYNC_MASK)) {
|
||||
prosystem_cycles = 456;
|
||||
|
||||
// If lightgun is enabled, check to see if it should be fired
|
||||
if(lightgun) prosystem_FireLightGun();
|
||||
|
||||
if(memory_ram[WSYNC] && wsync) {
|
||||
memory_ram[WSYNC] = false;
|
||||
wsync_scanline = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cycles = maria_RenderScanline( );
|
||||
if(cartridge_flags & CARTRIDGE_CYCLE_STEALING_MASK) {
|
||||
|
||||
if(cycle_stealing) {
|
||||
prosystem_cycles += cycles;
|
||||
|
||||
if(riot_timing) {
|
||||
riot_UpdateTimer(cycles >> 2);
|
||||
}
|
||||
}
|
||||
|
||||
while(prosystem_cycles < 456) {
|
||||
|
||||
while(!wsync_scanline && prosystem_cycles < CYCLES_PER_SCANLINE) {
|
||||
cycles = sally_ExecuteInstruction( );
|
||||
prosystem_cycles += (cycles << 2);
|
||||
if(half_cycle) prosystem_cycles += 2;
|
||||
|
||||
// If lightgun is enabled, check to see if it should be fired
|
||||
if(lightgun) prosystem_FireLightGun();
|
||||
|
||||
if(riot_timing) {
|
||||
riot_UpdateTimer(cycles);
|
||||
}
|
||||
if(memory_ram[WSYNC] && !(cartridge_flags & CARTRIDGE_WSYNC_MASK)) {
|
||||
prosystem_cycles = 456;
|
||||
|
||||
if(memory_ram[WSYNC] && wsync) {
|
||||
memory_ram[WSYNC] = false;
|
||||
wsync_scanline = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If a WSYNC was performed and the current cycle count is less than
|
||||
// the cycles per scanline, add those cycles to current timers.
|
||||
if(wsync_scanline && prosystem_cycles < CYCLES_PER_SCANLINE) {
|
||||
if(riot_timing)
|
||||
{
|
||||
riot_UpdateTimer((CYCLES_PER_SCANLINE - prosystem_cycles) >> 2);
|
||||
}
|
||||
prosystem_cycles = CYCLES_PER_SCANLINE;
|
||||
}
|
||||
|
||||
// If lightgun is enabled, check to see if it should be fired
|
||||
if(lightgun) prosystem_FireLightGun();
|
||||
|
||||
tia_Process(2);
|
||||
//if(cartridge_pokey) {
|
||||
if(cartridge_pokey || cartridge_xm) {
|
||||
pokey_Process(2);
|
||||
//}
|
||||
}
|
||||
|
||||
if(cartridge_pokey || cartridge_xm) pokey_Scanline();
|
||||
}
|
||||
|
||||
prosystem_frame++;
|
||||
if(prosystem_frame >= prosystem_frequency) {
|
||||
prosystem_frame = 0;
|
||||
@@ -127,72 +220,158 @@ bool prosystem_Save(std::string filename, bool compress) {
|
||||
}
|
||||
|
||||
logger_LogInfo("Saving game state to file " + filename + ".", PRO_SYSTEM_SOURCE);
|
||||
|
||||
byte buffer[32829] = {0};
|
||||
|
||||
byte loc_buffer[33000 + XM_RAM_SIZE + 4] = {0};
|
||||
|
||||
uint size = 0;
|
||||
|
||||
uint index;
|
||||
for(index = 0; index < 16; index++) {
|
||||
buffer[size + index] = PRO_SYSTEM_STATE_HEADER[index];
|
||||
loc_buffer[size + index] = PRO_SYSTEM_STATE_HEADER[index];
|
||||
}
|
||||
size += 16;
|
||||
|
||||
buffer[size++] = 1;
|
||||
loc_buffer[size++] = 1;
|
||||
for(index = 0; index < 4; index++) {
|
||||
buffer[size + index] = 0;
|
||||
loc_buffer[size + index] = 0;
|
||||
}
|
||||
size += 4;
|
||||
|
||||
for(index = 0; index < 32; index++) {
|
||||
buffer[size + index] = cartridge_digest[index];
|
||||
loc_buffer[size + index] = cartridge_digest[index];
|
||||
}
|
||||
size += 32;
|
||||
|
||||
buffer[size++] = sally_a;
|
||||
buffer[size++] = sally_x;
|
||||
buffer[size++] = sally_y;
|
||||
buffer[size++] = sally_p;
|
||||
buffer[size++] = sally_s;
|
||||
buffer[size++] = sally_pc.b.l;
|
||||
buffer[size++] = sally_pc.b.h;
|
||||
buffer[size++] = cartridge_bank;
|
||||
loc_buffer[size++] = sally_a;
|
||||
loc_buffer[size++] = sally_x;
|
||||
loc_buffer[size++] = sally_y;
|
||||
loc_buffer[size++] = sally_p;
|
||||
loc_buffer[size++] = sally_s;
|
||||
loc_buffer[size++] = sally_pc.b.l;
|
||||
loc_buffer[size++] = sally_pc.b.h;
|
||||
loc_buffer[size++] = cartridge_bank;
|
||||
|
||||
for(index = 0; index < 16384; index++) {
|
||||
buffer[size + index] = memory_ram[index];
|
||||
loc_buffer[size + index] = memory_ram[index];
|
||||
}
|
||||
size += 16384;
|
||||
|
||||
if(cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) {
|
||||
for(index = 0; index < 16384; index++) {
|
||||
buffer[size + index] = memory_ram[16384 + index];
|
||||
loc_buffer[size + index] = memory_ram[16384 + index];
|
||||
}
|
||||
size += 16384;
|
||||
}
|
||||
|
||||
if(!compress) {
|
||||
|
||||
// RIOT state
|
||||
loc_buffer[size++] = riot_dra;
|
||||
loc_buffer[size++] = riot_drb;
|
||||
loc_buffer[size++] = riot_timing;
|
||||
loc_buffer[size++] = ( 0xff & ( riot_timer >> 8 ) );
|
||||
loc_buffer[size++] = ( 0xff & riot_timer );
|
||||
loc_buffer[size++] = riot_intervals;
|
||||
loc_buffer[size++] = ( 0xff & ( riot_clocks >> 8 ) );
|
||||
loc_buffer[size++] = ( 0xff & riot_clocks );
|
||||
|
||||
// XM (if applicable)
|
||||
if (cartridge_xm) {
|
||||
loc_buffer[size++] = xm_reg;
|
||||
loc_buffer[size++] = xm_bank;
|
||||
loc_buffer[size++] = xm_pokey_enabled;
|
||||
loc_buffer[size++] = xm_mem_enabled;
|
||||
|
||||
for (index = 0; index < XM_RAM_SIZE; index++) {
|
||||
loc_buffer[size + index] = xm_ram[index];
|
||||
}
|
||||
size += XM_RAM_SIZE;
|
||||
}
|
||||
|
||||
FILE* file = fopen(filename.c_str( ), "wb");
|
||||
if(file == NULL) {
|
||||
logger_LogError("Failed to open the file " + filename + " for writing.", PRO_SYSTEM_SOURCE);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(fwrite(buffer, 1, size, file) != size) {
|
||||
if(fwrite(loc_buffer, 1, size, file) != size) {
|
||||
fclose(file);
|
||||
logger_LogError("Failed to write the save state data to the file " + filename + ".", PRO_SYSTEM_SOURCE);
|
||||
return false;
|
||||
}
|
||||
|
||||
fflush(file);
|
||||
fclose(file);
|
||||
}
|
||||
else {
|
||||
if(!archive_Compress(filename.c_str( ), "Save.sav", buffer, size)) {
|
||||
logger_LogError("Failed to compress the save state data to the file " + filename + ".", PRO_SYSTEM_SOURCE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool prosystem_Save_buffer(byte *buffer)
|
||||
{
|
||||
uint size = 0;
|
||||
uint index;
|
||||
|
||||
for(index = 0; index < 16; index++) {
|
||||
buffer[size + index] = PRO_SYSTEM_STATE_HEADER[index];
|
||||
}
|
||||
size += 16;
|
||||
|
||||
buffer[size++] = 1;
|
||||
for(index = 0; index < 4; index++) {
|
||||
buffer[size + index] = 0;
|
||||
}
|
||||
size += 4;
|
||||
|
||||
for(index = 0; index < 32; index++) {
|
||||
buffer[size + index] = cartridge_digest[index];
|
||||
}
|
||||
size += 32;
|
||||
|
||||
buffer[size++] = sally_a;
|
||||
buffer[size++] = sally_x;
|
||||
buffer[size++] = sally_y;
|
||||
buffer[size++] = sally_p;
|
||||
buffer[size++] = sally_s;
|
||||
buffer[size++] = sally_pc.b.l;
|
||||
buffer[size++] = sally_pc.b.h;
|
||||
buffer[size++] = cartridge_bank;
|
||||
|
||||
for(index = 0; index < 16384; index++) {
|
||||
buffer[size + index] = memory_ram[index];
|
||||
}
|
||||
size += 16384;
|
||||
|
||||
if(cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) {
|
||||
for(index = 0; index < 16384; index++) {
|
||||
buffer[size + index] = memory_ram[16384 + index];
|
||||
}
|
||||
size += 16384;
|
||||
}
|
||||
|
||||
// RIOT state
|
||||
buffer[size++] = riot_dra;
|
||||
buffer[size++] = riot_drb;
|
||||
buffer[size++] = riot_timing;
|
||||
buffer[size++] = ( 0xff & ( riot_timer >> 8 ) );
|
||||
buffer[size++] = ( 0xff & riot_timer );
|
||||
buffer[size++] = riot_intervals;
|
||||
buffer[size++] = ( 0xff & ( riot_clocks >> 8 ) );
|
||||
buffer[size++] = ( 0xff & riot_clocks );
|
||||
|
||||
// XM (if applicable)
|
||||
if (cartridge_xm) {
|
||||
buffer[size++] = xm_reg;
|
||||
buffer[size++] = xm_bank;
|
||||
buffer[size++] = xm_pokey_enabled;
|
||||
buffer[size++] = xm_mem_enabled;
|
||||
|
||||
for (index = 0; index < XM_RAM_SIZE; index++) {
|
||||
buffer[size + index] = xm_ram[index];
|
||||
}
|
||||
size += XM_RAM_SIZE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Load
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -202,10 +381,10 @@ bool prosystem_Load(const std::string filename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
logger_LogInfo("Loading game state from file " + filename + ".", PRO_SYSTEM_SOURCE);
|
||||
|
||||
byte loc_buffer[33000 + XM_RAM_SIZE + 4] = {0};
|
||||
|
||||
byte buffer[32829] = {0};
|
||||
uint size = archive_GetUncompressedFileSize(filename);
|
||||
if(size == 0) {
|
||||
FILE* file = fopen(filename.c_str( ), "rb");
|
||||
@@ -214,34 +393,35 @@ bool prosystem_Load(const std::string filename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(fseek(file, 0, SEEK_END)) {
|
||||
if(fseek(file, 0L, SEEK_END)) {
|
||||
fclose(file);
|
||||
logger_LogError("Failed to find the end of the file.", PRO_SYSTEM_SOURCE);
|
||||
return false;
|
||||
}
|
||||
|
||||
size = ftell(file);
|
||||
if(fseek(file, 0, SEEK_SET)) {
|
||||
if(fseek(file, 0L, SEEK_SET)) {
|
||||
fclose(file);
|
||||
logger_LogError("Failed to find the size of the file.", PRO_SYSTEM_SOURCE);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(size != 16445 && size != 32829) {
|
||||
if( size != 16445 && size != 32829 && /* no RIOT */
|
||||
size != 16453 && size != 32837 && /* with RIOT */
|
||||
size != (16453 + 4 + XM_RAM_SIZE) && /* XM without supercart ram */
|
||||
size != (32837 + 4 + XM_RAM_SIZE)) /* XM with supercart ram */
|
||||
{
|
||||
fclose(file);
|
||||
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(fread(buffer, 1, size, file) != size && ferror(file)) {
|
||||
if(fread(loc_buffer, 1, size, file) != size && ferror(file)) {
|
||||
fclose(file);
|
||||
logger_LogError("Failed to read the file data.", PRO_SYSTEM_SOURCE);
|
||||
return false;
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
else if(size == 16445 || size == 32829) {
|
||||
archive_Uncompress(filename, buffer, size);
|
||||
}
|
||||
else {
|
||||
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
|
||||
@@ -251,13 +431,13 @@ bool prosystem_Load(const std::string filename) {
|
||||
uint offset = 0;
|
||||
uint index;
|
||||
for(index = 0; index < 16; index++) {
|
||||
if(buffer[offset + index] != PRO_SYSTEM_STATE_HEADER[index]) {
|
||||
if(loc_buffer[offset + index] != PRO_SYSTEM_STATE_HEADER[index]) {
|
||||
logger_LogError("File is not a valid ProSystem save state.", PRO_SYSTEM_SOURCE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
offset += 16;
|
||||
byte version = buffer[offset++];
|
||||
byte version = loc_buffer[offset++];
|
||||
|
||||
uint date = 0;
|
||||
for(index = 0; index < 4; index++) {
|
||||
@@ -268,7 +448,7 @@ bool prosystem_Load(const std::string filename) {
|
||||
|
||||
char digest[33] = {0};
|
||||
for(index = 0; index < 32; index++) {
|
||||
digest[index] = buffer[offset + index];
|
||||
digest[index] = loc_buffer[offset + index];
|
||||
}
|
||||
offset += 32;
|
||||
if(cartridge_digest != std::string(digest)) {
|
||||
@@ -276,35 +456,166 @@ bool prosystem_Load(const std::string filename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sally_a = buffer[offset++];
|
||||
sally_x = buffer[offset++];
|
||||
sally_y = buffer[offset++];
|
||||
sally_p = buffer[offset++];
|
||||
sally_s = buffer[offset++];
|
||||
sally_pc.b.l = buffer[offset++];
|
||||
sally_pc.b.h = buffer[offset++];
|
||||
sally_a = loc_buffer[offset++];
|
||||
sally_x = loc_buffer[offset++];
|
||||
sally_y = loc_buffer[offset++];
|
||||
sally_p = loc_buffer[offset++];
|
||||
sally_s = loc_buffer[offset++];
|
||||
sally_pc.b.l = loc_buffer[offset++];
|
||||
sally_pc.b.h = loc_buffer[offset++];
|
||||
|
||||
cartridge_StoreBank(buffer[offset++]);
|
||||
cartridge_StoreBank(loc_buffer[offset++]);
|
||||
|
||||
for(index = 0; index < 16384; index++) {
|
||||
memory_ram[index] = buffer[offset + index];
|
||||
memory_ram[index] = loc_buffer[offset + index];
|
||||
}
|
||||
offset += 16384;
|
||||
|
||||
if(cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) {
|
||||
if(size != 32829) {
|
||||
if (size != 32829 && /* no RIOT */
|
||||
size != 32837 && /* with RIOT */
|
||||
size != (32837 + 4 + XM_RAM_SIZE)) /* XM */ {
|
||||
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
|
||||
return false;
|
||||
}
|
||||
for(index = 0; index < 16384; index++) {
|
||||
memory_ram[16384 + index] = buffer[offset + index];
|
||||
memory_ram[16384 + index] = loc_buffer[offset + index];
|
||||
}
|
||||
offset += 16384;
|
||||
}
|
||||
|
||||
if (size == 16453 || /* no supercart ram */
|
||||
size == 32837 || /* supercart ram */
|
||||
size == (16453 + 4 + XM_RAM_SIZE) || /* xm, no supercart ram */
|
||||
size == (32837 + 4 + XM_RAM_SIZE)) /* xm, supercart ram */ {
|
||||
// RIOT state
|
||||
riot_dra = loc_buffer[offset++];
|
||||
riot_drb = loc_buffer[offset++];
|
||||
riot_timing = loc_buffer[offset++];
|
||||
riot_timer = ( loc_buffer[offset++] << 8 );
|
||||
riot_timer |= loc_buffer[offset++];
|
||||
riot_intervals = loc_buffer[offset++];
|
||||
riot_clocks = ( loc_buffer[offset++] << 8 );
|
||||
riot_clocks |= loc_buffer[offset++];
|
||||
}
|
||||
|
||||
// XM (if applicable)
|
||||
if (cartridge_xm) {
|
||||
if ((size != (16453 + 4 + XM_RAM_SIZE)) &&
|
||||
(size != (32837 + 4 + XM_RAM_SIZE))) {
|
||||
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
|
||||
return false;
|
||||
}
|
||||
xm_reg = loc_buffer[offset++];
|
||||
xm_bank = loc_buffer[offset++];
|
||||
xm_pokey_enabled = loc_buffer[offset++];
|
||||
xm_mem_enabled = loc_buffer[offset++];
|
||||
|
||||
for (index = 0; index < XM_RAM_SIZE; index++) {
|
||||
xm_ram[index] = loc_buffer[offset++];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool prosystem_Load_buffer(const byte *buffer)
|
||||
{
|
||||
uint size = cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM ? 32837 : 16453;
|
||||
if(cartridge_xm) {
|
||||
size += 4 + XM_RAM_SIZE;
|
||||
}
|
||||
uint offset = 0;
|
||||
uint index;
|
||||
|
||||
for(index = 0; index < 16; index++) {
|
||||
if(buffer[offset + index] != PRO_SYSTEM_STATE_HEADER[index]) {
|
||||
logger_LogError("File is not a valid ProSystem save state.", PRO_SYSTEM_SOURCE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
offset += 16;
|
||||
|
||||
byte version = buffer[offset++];
|
||||
//uint date = 0;
|
||||
|
||||
offset += 4;
|
||||
|
||||
//prosystem_Reset(); // TODO doesn't seem necessary but needs investigation
|
||||
|
||||
char digest[33] = {0};
|
||||
for(index = 0; index < 32; index++) {
|
||||
digest[index] = buffer[offset + index];
|
||||
}
|
||||
offset += 32;
|
||||
if(cartridge_digest != std::string(digest)) {
|
||||
logger_LogError("Load state digest [" + std::string(digest) + "] does not match loaded cartridge digest [" + cartridge_digest + "].", PRO_SYSTEM_SOURCE);
|
||||
return false;
|
||||
}
|
||||
|
||||
sally_a = buffer[offset++];
|
||||
sally_x = buffer[offset++];
|
||||
sally_y = buffer[offset++];
|
||||
sally_p = buffer[offset++];
|
||||
sally_s = buffer[offset++];
|
||||
sally_pc.b.l = buffer[offset++];
|
||||
sally_pc.b.h = buffer[offset++];
|
||||
|
||||
cartridge_StoreBank(buffer[offset++]);
|
||||
|
||||
for(index = 0; index < 16384; index++) {
|
||||
memory_ram[index] = buffer[offset + index];
|
||||
}
|
||||
offset += 16384;
|
||||
|
||||
if(cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) {
|
||||
if (size != 32829 && /* no RIOT */
|
||||
size != 32837 && /* with RIOT */
|
||||
size != (32837 + 4 + XM_RAM_SIZE)) /* XM */ {
|
||||
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
|
||||
return false;
|
||||
}
|
||||
for(index = 0; index < 16384; index++) {
|
||||
memory_ram[16384 + index] = buffer[offset + index];
|
||||
}
|
||||
offset += 16384;
|
||||
}
|
||||
|
||||
if (size == 16453 || /* no supercart ram */
|
||||
size == 32837 || /* supercart ram */
|
||||
size == (16453 + 4 + XM_RAM_SIZE) || /* xm, no supercart ram */
|
||||
size == (32837 + 4 + XM_RAM_SIZE)) /* xm, supercart ram */ {
|
||||
// RIOT state
|
||||
riot_dra = buffer[offset++];
|
||||
riot_drb = buffer[offset++];
|
||||
riot_timing = buffer[offset++];
|
||||
riot_timer = ( buffer[offset++] << 8 );
|
||||
riot_timer |= buffer[offset++];
|
||||
riot_intervals = buffer[offset++];
|
||||
riot_clocks = ( buffer[offset++] << 8 );
|
||||
riot_clocks |= buffer[offset++];
|
||||
}
|
||||
|
||||
// XM (if applicable)
|
||||
if (cartridge_xm) {
|
||||
if ((size != (16453 + 4 + XM_RAM_SIZE)) &&
|
||||
(size != (32837 + 4 + XM_RAM_SIZE))) {
|
||||
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
|
||||
return false;
|
||||
}
|
||||
xm_reg = buffer[offset++];
|
||||
xm_bank = buffer[offset++];
|
||||
xm_pokey_enabled = buffer[offset++];
|
||||
xm_mem_enabled = buffer[offset++];
|
||||
|
||||
for (index = 0; index < XM_RAM_SIZE; index++) {
|
||||
xm_ram[index] = buffer[offset++];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Pause
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
+21
-2
@@ -24,7 +24,6 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef PRO_SYSTEM_H
|
||||
#define PRO_SYSTEM_H
|
||||
//#define NULL 0
|
||||
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
@@ -39,15 +38,27 @@
|
||||
#include "Archive.h"
|
||||
#include "Tia.h"
|
||||
#include "Pokey.h"
|
||||
#include "ExpansionModule.h"
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short word;
|
||||
typedef unsigned int uint;
|
||||
|
||||
// The number of cycles per scan line
|
||||
#define CYCLES_PER_SCANLINE 454
|
||||
// The number of cycles for HBLANK
|
||||
#define HBLANK_CYCLES 136
|
||||
// The number of cycles per scanline that the 7800 checks for a hit
|
||||
#define LG_CYCLES_PER_SCANLINE 318
|
||||
// The number of cycles indented (after HBLANK) prior to checking for a hit
|
||||
#define LG_CYCLES_INDENT 52
|
||||
|
||||
extern void prosystem_Reset( );
|
||||
extern void prosystem_ExecuteFrame(const byte* input);
|
||||
extern bool prosystem_Save(std::string filename, bool compress);
|
||||
extern bool prosystem_Load(std::string filename);
|
||||
extern bool prosystem_Save_buffer(byte *buffer);
|
||||
extern bool prosystem_Load_buffer(const byte *buffer);
|
||||
extern void prosystem_Pause(bool pause);
|
||||
extern void prosystem_Close( );
|
||||
extern bool prosystem_active;
|
||||
@@ -56,5 +67,13 @@ extern word prosystem_frequency;
|
||||
extern byte prosystem_frame;
|
||||
extern word prosystem_scanlines;
|
||||
extern uint prosystem_cycles;
|
||||
extern uint prosystem_extra_cycles;
|
||||
|
||||
#endif
|
||||
// The scanline that the lightgun shot occurred at
|
||||
extern int lightgun_scanline;
|
||||
// The cycle that the lightgun shot occurred at
|
||||
extern float lightgun_cycle;
|
||||
// Whether the lightgun is enabled for the current cartridge
|
||||
//extern bool lightgun_enabled;
|
||||
|
||||
#endif
|
||||
|
||||
+10
-8
@@ -26,12 +26,13 @@
|
||||
|
||||
byte region_type = REGION_AUTO;
|
||||
|
||||
static const rect REGION_VISIBLE_AREA_NTSC = {0, 26, 319, 248};
|
||||
static const rect REGION_VISIBLE_AREA_PAL = {0, 26, 319, 297};
|
||||
static const rect REGION_DISPLAY_AREA_NTSC = {0, 16, 319, 258};
|
||||
static const rect REGION_DISPLAY_AREA_PAL = {0, 16, 319, 306};
|
||||
static const rect REGION_VISIBLE_AREA_NTSC = {0, 26, 319, 250};
|
||||
static const byte REGION_FREQUENCY_NTSC = 60;
|
||||
static const word REGION_SCANLINES_NTSC = 262;
|
||||
|
||||
static const rect REGION_DISPLAY_AREA_PAL = {0, 16, 319, 308};
|
||||
static const rect REGION_VISIBLE_AREA_PAL = {0, 26, 319, 297};
|
||||
static const byte REGION_FREQUENCY_PAL = 50;
|
||||
static const word REGION_SCANLINES_PAL = 312;
|
||||
|
||||
@@ -79,12 +80,12 @@ static const byte REGION_PALETTE_NTSC[ ] = {
|
||||
0x00,0x71,0xC6,0x00,0x86,0xD0,0x0A,0x9B,0xDF,0x1A,0xA8,0xEC,
|
||||
0x2B,0xB6,0xFF,0x3F,0xC2,0xFF,0x45,0xCB,0xFF,0x59,0xD3,0xFF,
|
||||
0x7F,0xDA,0xFF,0x8F,0xDE,0xFF,0xA0,0xE2,0xFF,0xB0,0xEB,0xFF,
|
||||
0x00,0x4A,0x00,0x00,0x4C,0x00,0x00,0x6A,0x20,0x50,0x8E,0x79,
|
||||
0x40,0x99,0x99,0x00,0x9C,0xAA,0x00,0xA1,0xBB,0x01,0xA4,0xCC,
|
||||
0x03,0xA5,0xD7,0x05,0xDA,0xE2,0x18,0xE5,0xFF,0x34,0xEA,0xFF,
|
||||
0x00,0x38,0x39,0x00,0x3C,0x48,0x00,0x3D,0x5B,0x02,0x66,0x7F,
|
||||
0x03,0x73,0x83,0x00,0x9C,0xAA,0x00,0xA1,0xBB,0x01,0xA4,0xCC,
|
||||
0x03,0xBB,0xFF,0x05,0xDA,0xE2,0x18,0xE5,0xFF,0x34,0xEA,0xFF,
|
||||
0x49,0xEF,0xFF,0x66,0xF2,0xFF,0x84,0xF4,0xFF,0x9E,0xF9,0xFF,
|
||||
0x00,0x4A,0x00,0x00,0x5D,0x00,0x00,0x70,0x00,0x00,0x83,0x00,
|
||||
0x00,0x95,0x00,0x00,0xAB,0x00,0x07,0xBD,0x07,0x0A,0xD0,0x0A,
|
||||
0x00,0x4A,0x00,0x00,0x5D,0x00,0x00,0x70,0x00,0x00,0x8B,0x00,
|
||||
0x00,0xA9,0x00,0x00,0xBB,0x05,0x00,0xBD,0x00,0x02,0xD0,0x05,
|
||||
0x1A,0xD5,0x40,0x5A,0xF1,0x77,0x82,0xEF,0xA7,0x84,0xED,0xD1,
|
||||
0x89,0xFF,0xED,0x7D,0xFF,0xFF,0x93,0xFF,0xFF,0x9B,0xFF,0xFF,
|
||||
0x22,0x4A,0x03,0x27,0x53,0x04,0x30,0x64,0x05,0x3C,0x77,0x0C,
|
||||
@@ -199,4 +200,5 @@ void region_Reset( ) {
|
||||
tia_size = 524;
|
||||
pokey_size = 524;
|
||||
}
|
||||
pokey_setSampleRate((prosystem_scanlines * prosystem_frequency) << 1);
|
||||
}
|
||||
|
||||
+147
-41
@@ -28,11 +28,23 @@ bool riot_timing = false;
|
||||
word riot_timer = TIM64T;
|
||||
byte riot_intervals;
|
||||
|
||||
byte riot_dra = 0;
|
||||
byte riot_drb = 0;
|
||||
static bool riot_elapsed;
|
||||
static int riot_currentTime;
|
||||
static word riot_clocks;
|
||||
word riot_clocks;
|
||||
|
||||
void riot_Reset(void) {
|
||||
riot_SetDRA(0);
|
||||
riot_SetDRB(0);
|
||||
|
||||
riot_timing = false;
|
||||
riot_timer = TIM64T;
|
||||
riot_intervals = 0;
|
||||
riot_clocks = 0;
|
||||
|
||||
riot_elapsed = false;
|
||||
riot_currentTime = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -59,53 +71,147 @@ void riot_Reset(void) {
|
||||
// | 16 | Console | Right Difficulty
|
||||
// +----------+--------------+-------------------------------------------------
|
||||
void riot_SetInput(const byte* input) {
|
||||
(input[0x00])? memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x80: memory_ram[SWCHA] = memory_ram[SWCHA] | 0x80;
|
||||
(input[0x01])? memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x40: memory_ram[SWCHA] = memory_ram[SWCHA] | 0x40;
|
||||
(input[0x02])? memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x20: memory_ram[SWCHA] = memory_ram[SWCHA] | 0x20;
|
||||
(input[0x03])? memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x10: memory_ram[SWCHA] = memory_ram[SWCHA] | 0x10;
|
||||
if(input[0x04]) {
|
||||
memory_ram[INPT0] = memory_ram[INPT0] | 0x80;
|
||||
memory_ram[INPT4] = memory_ram[INPT4] &~ 0x80;
|
||||
|
||||
/*gdement: Comments are messy, but wanted to document how this all works.
|
||||
Changed this routine to support 1 vs 2 button modes.
|
||||
Also added the interaction of CTLSWA and DRA on the SWCHA output, and same for SWCHB.
|
||||
SWCHA is directionals. SWCHB is console switches and button mode.
|
||||
button signals are in high bits of INPT0-5.*/
|
||||
|
||||
memory_ram[SWCHA] = ((~memory_ram[CTLSWA]) | riot_dra); /*SWCHA as driven by RIOT*/
|
||||
/*now console switches will force bits to ground:*/
|
||||
if (input[0x00]) memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x80;
|
||||
if (input[0x01]) memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x40;
|
||||
if (input[0x02]) memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x20;
|
||||
if (input[0x03]) memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x10;
|
||||
if (input[0x06]) memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x08;
|
||||
if (input[0x07]) memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x04;
|
||||
if (input[0x08]) memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x02;
|
||||
if (input[0x09]) memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x01;
|
||||
/*Switches can always push the appropriate bit of SWCHA to ground, as in above code block.
|
||||
In addition, RIOT can be configured to drive ground even when switch is open.
|
||||
By doing this it's possible for real hardware to behave as if switches are permanently held (tested this).*/
|
||||
|
||||
|
||||
/*As with swcha, the value seen at SWCHB is derived from CTLSWB and DRB (an internal RIOT register)
|
||||
(Any write to SWCHB actually gets stored in DRB)
|
||||
If a given bit in CTLSWB is 0 (input mode), then RIOT puts a 1 on SWCHB.
|
||||
If bit in CTLSWB is 1 (output mode), then RIOT puts stored DRB value on SWCHB.
|
||||
The SWCHB outputs from RIOT can be overdriven to 0 by console switches.
|
||||
The CTLSWB/DRB interaction is important at bits 2 and 4, which control button mode for each player.
|
||||
Bit 5 appears unused, and other bits are the console switches.
|
||||
|
||||
CTLSWB DRB SWCHB result on button mode (for bits 2 and 4)
|
||||
------- --- ----- -----------------------------------------
|
||||
0 0 1 1 button mode - this is default state after boot
|
||||
0 1 1 1 button mode
|
||||
1 0 0 2 button mode
|
||||
1 1 1 1 button mode
|
||||
This chart was confirmed on hardware
|
||||
From the default state after boot, simply changing CTLSWB to 1 will result in 2 button mode.
|
||||
Some games rely on this, and don't actually store anything to SWCHB.*/
|
||||
|
||||
memory_ram[SWCHB] = ((~memory_ram[CTLSWB]) | riot_drb); /*SWCHB as driven by RIOT*/
|
||||
|
||||
if(input != NULL)
|
||||
{
|
||||
/*now the console switches can force certain bits to ground:*/
|
||||
if (input[0x0c]) memory_ram[SWCHB] = memory_ram[SWCHB] &~ 0x01;
|
||||
if (input[0x0d]) memory_ram[SWCHB] = memory_ram[SWCHB] &~ 0x02;
|
||||
if (input[0x0e]) memory_ram[SWCHB] = memory_ram[SWCHB] &~ 0x08;
|
||||
if (input[0x0f]) memory_ram[SWCHB] = memory_ram[SWCHB] &~ 0x40;
|
||||
if (input[0x10]) memory_ram[SWCHB] = memory_ram[SWCHB] &~ 0x80;
|
||||
}
|
||||
else {
|
||||
memory_ram[INPT0] = memory_ram[INPT0] &~ 0x80;
|
||||
memory_ram[INPT4] = memory_ram[INPT4] | 0x80;
|
||||
|
||||
/*When in 1 button mode, only the legacy 2600 button signal is active. The others stay off.
|
||||
When in 2 button mode, only the new signals are active. 2600 button stays off. (tested)
|
||||
see: http://www.atariage.com/forums/index.php?showtopic=127162
|
||||
also see 7800 schematic and RIOT datasheet */
|
||||
|
||||
if(memory_ram[SWCHB] & 0x04) //first player in 1 button mode
|
||||
{
|
||||
memory_ram[INPT0] &= 0x7f; //new style buttons are always off in this mode
|
||||
memory_ram[INPT1] &= 0x7f;
|
||||
if(input[0x04] || input[0x05]) //in this mode, either button triggers only the legacy button signal
|
||||
{
|
||||
memory_ram[INPT4] &= 0x7f; //this button signal activates by turning off the high bit
|
||||
}
|
||||
else
|
||||
{
|
||||
memory_ram[INPT4] |= 0x80;
|
||||
}
|
||||
}
|
||||
if(input[0x05]) {
|
||||
memory_ram[INPT1] = memory_ram[INPT1] | 0x80;
|
||||
memory_ram[INPT4] = memory_ram[INPT4] &~ 0x80;
|
||||
else //first player in 2 button mode
|
||||
{
|
||||
memory_ram[INPT4] |= 0x80; //2600 button is always off in this mode
|
||||
if(input[0x04]) //left button (button 1)
|
||||
{
|
||||
memory_ram[INPT1] |= 0x80; //these buttons activate by turning on the high bit.
|
||||
}
|
||||
else
|
||||
{
|
||||
memory_ram[INPT1] &= 0x7f;
|
||||
}
|
||||
if(input[0x05]) //right button (button 2)
|
||||
{
|
||||
memory_ram[INPT0] |= 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
memory_ram[INPT0] &= 0x7f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
memory_ram[INPT1] = memory_ram[INPT1] &~ 0x80;
|
||||
memory_ram[INPT4] = memory_ram[INPT4] | 0x80;
|
||||
|
||||
/*now repeat for 2nd player*/
|
||||
if(memory_ram[SWCHB] & 0x10)
|
||||
{
|
||||
memory_ram[INPT2] &= 0x7f;
|
||||
memory_ram[INPT3] &= 0x7f;
|
||||
if(input[0x0a] || input[0x0b])
|
||||
{
|
||||
memory_ram[INPT5] &= 0x7f;
|
||||
}
|
||||
else
|
||||
{
|
||||
memory_ram[INPT5] |= 0x80;
|
||||
}
|
||||
}
|
||||
(input[0x06])? memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x08: memory_ram[SWCHA] = memory_ram[SWCHA] | 0x08;
|
||||
(input[0x07])? memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x04: memory_ram[SWCHA] = memory_ram[SWCHA] | 0x04;
|
||||
(input[0x08])? memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x02: memory_ram[SWCHA] = memory_ram[SWCHA] | 0x02;
|
||||
(input[0x09])? memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x01: memory_ram[SWCHA] = memory_ram[SWCHA] | 0x01;
|
||||
if(input[0x0a]) {
|
||||
memory_ram[INPT2] = memory_ram[INPT2] | 0x80;
|
||||
memory_ram[INPT5] = memory_ram[INPT5] &~ 0x80;
|
||||
else
|
||||
{
|
||||
memory_ram[INPT5] |= 0x80;
|
||||
if(input[0x0a])
|
||||
{
|
||||
memory_ram[INPT3] |= 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
memory_ram[INPT3] &= 0x7f;
|
||||
}
|
||||
if(input[0x0b])
|
||||
{
|
||||
memory_ram[INPT2] |= 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
memory_ram[INPT2] &= 0x7f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
memory_ram[INPT2] = memory_ram[INPT2] &~ 0x80;
|
||||
memory_ram[INPT5] = memory_ram[INPT5] | 0x80;
|
||||
}
|
||||
if(input[0x0b]) {
|
||||
memory_ram[INPT3] = memory_ram[INPT3] | 0x80;
|
||||
memory_ram[INPT5] = memory_ram[INPT5] &~ 0x80;
|
||||
}
|
||||
else {
|
||||
memory_ram[INPT3] = memory_ram[INPT3] &~ 0x80;
|
||||
memory_ram[INPT5] = memory_ram[INPT5] | 0x80;
|
||||
}
|
||||
(input[0x0c])? memory_ram[SWCHB] = memory_ram[SWCHB] &~ 0x01: memory_ram[SWCHB] = memory_ram[SWCHB] | 0x01;
|
||||
(input[0x0d])? memory_ram[SWCHB] = memory_ram[SWCHB] &~ 0x02: memory_ram[SWCHB] = memory_ram[SWCHB] | 0x02;
|
||||
(input[0x0e])? memory_ram[SWCHB] = memory_ram[SWCHB] &~ 0x08: memory_ram[SWCHB] = memory_ram[SWCHB] | 0x08;
|
||||
(input[0x0f])? memory_ram[SWCHB] = memory_ram[SWCHB] &~ 0x40: memory_ram[SWCHB] = memory_ram[SWCHB] | 0x40;
|
||||
(input[0x10])? memory_ram[SWCHB] = memory_ram[SWCHB] &~ 0x80: memory_ram[SWCHB] = memory_ram[SWCHB] | 0x80;
|
||||
}
|
||||
|
||||
/***********************************************************************************
|
||||
* riot_setDRA(byte data) and riot_setDRB(byte data) gdement
|
||||
* -------------------------------------------------
|
||||
* Stores a value written to SWCHA/SWCHB into the RIOT's internal DRA/DRB registers.
|
||||
* These are distinct from what you see when reading SWCHA/SWCHB.
|
||||
***********************************************************************************/
|
||||
void riot_SetDRA(byte data) {
|
||||
riot_dra=data;
|
||||
}
|
||||
void riot_SetDRB(byte data) {
|
||||
riot_drb=data;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// SetTimer
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -34,10 +34,15 @@ typedef unsigned int uint;
|
||||
|
||||
extern void riot_Reset(void);
|
||||
extern void riot_SetInput(const byte* input);
|
||||
extern void riot_SetDRA(byte data);
|
||||
extern void riot_SetDRB(byte data);
|
||||
extern void riot_SetTimer(word timer, byte intervals);
|
||||
extern void riot_UpdateTimer(byte cycles);
|
||||
extern bool riot_timing;
|
||||
extern word riot_timer;
|
||||
extern byte riot_intervals;
|
||||
extern byte riot_dra;
|
||||
extern byte riot_drb;
|
||||
extern word riot_clocks;
|
||||
|
||||
#endif
|
||||
|
||||
+41
-4
@@ -35,6 +35,12 @@ static byte sally_opcode;
|
||||
static pair sally_address;
|
||||
static uint sally_cycles;
|
||||
|
||||
// Whether the last operation resulted in a half cycle. (needs to be taken
|
||||
// into consideration by ProSystem when cycle counting). This can occur when
|
||||
// a TIA or RIOT are accessed (drops to 1.19Mhz when the TIA or RIOT chips
|
||||
// are accessed)
|
||||
bool half_cycle = false;
|
||||
|
||||
struct Flag {
|
||||
byte C;
|
||||
byte Z;
|
||||
@@ -58,11 +64,11 @@ static const Vector SALLY_NMI = {65531, 65530};
|
||||
static const Vector SALLY_IRQ = {65535, 65534};
|
||||
|
||||
static const byte SALLY_CYCLES[256] = {
|
||||
7,6,0,0,0,3,5,0,3,2,2,0,0,4,6,0,
|
||||
7,6,0,0,0,3,5,0,3,2,2,2,0,4,6,0,
|
||||
2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0,
|
||||
6,6,0,0,3,3,5,0,4,2,2,0,4,4,6,0,
|
||||
6,6,0,0,3,3,5,0,4,2,2,2,4,4,6,0,
|
||||
2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0,
|
||||
6,6,0,0,0,3,5,0,3,2,2,0,3,4,6,0,
|
||||
6,6,0,0,0,3,5,0,3,2,2,2,3,4,6,0,
|
||||
2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0,
|
||||
6,6,0,0,0,3,5,0,4,2,2,0,5,4,6,0,
|
||||
2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0,
|
||||
@@ -116,7 +122,7 @@ static void sally_Flags(byte data) {
|
||||
static void sally_Branch(byte branch) {
|
||||
if(branch) {
|
||||
pair temp = sally_pc;
|
||||
sally_pc.w += (char)sally_address.b.l;
|
||||
sally_pc.w += (signed char)sally_address.b.l;
|
||||
|
||||
if(temp.b.h != sally_pc.b.h) {
|
||||
sally_cycles += 2;
|
||||
@@ -935,6 +941,9 @@ void sally_Reset( ) {
|
||||
// ExecuteInstruction
|
||||
// ----------------------------------------------------------------------------
|
||||
uint sally_ExecuteInstruction( ) {
|
||||
// Reset half cycle flag
|
||||
half_cycle = false;
|
||||
|
||||
sally_opcode = memory_Read(sally_pc.w++);
|
||||
sally_cycles = SALLY_CYCLES[sally_opcode];
|
||||
|
||||
@@ -1036,6 +1045,14 @@ uint sally_ExecuteInstruction( ) {
|
||||
case 0x24:
|
||||
sally_ZeroPage( );
|
||||
sally_BIT( );
|
||||
// Add a half cycle if RIOT/TIA location is accessed. We only track
|
||||
// INPT4 since it is the only one that is accessed during the lightgun
|
||||
// hit detection loop. This should be extended to take into consideration
|
||||
// all RIOT and TIA accesses.
|
||||
if( sally_address.w == INPT4 )
|
||||
{
|
||||
half_cycle = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x25:
|
||||
@@ -1688,6 +1705,26 @@ uint sally_ExecuteInstruction( ) {
|
||||
sally_INC( );
|
||||
break;
|
||||
|
||||
case 0x4b: // ALR (ASR)
|
||||
sally_Immediate();
|
||||
sally_AND();
|
||||
sally_LSRA();
|
||||
break;
|
||||
|
||||
case 0x0b: // ANC
|
||||
case 0x2b: { // ANC
|
||||
sally_Immediate();
|
||||
sally_AND();
|
||||
if (sally_a & 128) {
|
||||
sally_p |= SALLY_FLAG.C;
|
||||
}
|
||||
else {
|
||||
//sally_p &= ~SALLY_FLAG.C;
|
||||
sally_p = (sally_p & ~SALLY_FLAG.C) & 0xFF;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+54
-400
@@ -1,11 +1,12 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// ___ ___ ___ ___ ___ ____ ___ _ _
|
||||
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ /
|
||||
// / / \ /__/ ___/ ___/ ___/ / /__ / / emulator
|
||||
// ___ ___ ___ ___ ___ ____ ___ _ _ __ ___
|
||||
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ / / / _
|
||||
// / / \ /__/ ___/ ___/ ___/ / /__ / / ___/ /__/
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2005 Greg Stanton
|
||||
//
|
||||
// Copyright 2020 Rupert Carmichael
|
||||
//
|
||||
// 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
|
||||
@@ -20,414 +21,67 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
// ----------------------------------------------------------------------------
|
||||
// Sound.cpp
|
||||
// Sound.c
|
||||
// ----------------------------------------------------------------------------
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Sound.h"
|
||||
#define SOUND_LATENCY_SCALE 4
|
||||
|
||||
byte sound_latency = SOUND_LATENCY_VERY_LOW;
|
||||
#define MAX_BUFFER_SIZE 8192
|
||||
|
||||
static const WAVEFORMATEX SOUND_DEFAULT_FORMAT = {WAVE_FORMAT_PCM, 1, 44100, 44100, 1, 8, 0};
|
||||
static LPDIRECTSOUND sound_dsound = NULL;
|
||||
static LPDIRECTSOUNDBUFFER sound_primaryBuffer = NULL;
|
||||
static LPDIRECTSOUNDBUFFER sound_buffer = NULL;
|
||||
static WAVEFORMATEX sound_format = SOUND_DEFAULT_FORMAT;
|
||||
static uint sound_counter = 0;
|
||||
static bool sound_muted = false;
|
||||
static uint32_t nSamplesPerSec = 48000;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// GetSampleLength
|
||||
// ----------------------------------------------------------------------------
|
||||
static uint sound_GetSampleLength(uint length, uint unit, uint unitMax) {
|
||||
uint sampleLength = length / unitMax;
|
||||
uint sampleRemain = length % unitMax;
|
||||
if(sampleRemain != 0 && sampleRemain >= unit) {
|
||||
sampleLength++;
|
||||
}
|
||||
return sampleLength;
|
||||
static void sound_Resample(const uint8_t *source, uint8_t *target, int length) {
|
||||
int measurement = nSamplesPerSec;
|
||||
int sourceIndex = 0;
|
||||
int targetIndex = 0;
|
||||
int max = ((prosystem_frequency * prosystem_scanlines) << 1);
|
||||
|
||||
while (targetIndex < length) {
|
||||
if (measurement >= max) {
|
||||
target[targetIndex++] = source[sourceIndex];
|
||||
measurement -= max;
|
||||
}
|
||||
else {
|
||||
sourceIndex++;
|
||||
measurement += nSamplesPerSec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Resample
|
||||
// ----------------------------------------------------------------------------
|
||||
static void sound_Resample(const byte* source, byte* target, int length) {
|
||||
int measurement = sound_format.nSamplesPerSec;
|
||||
int sourceIndex = 0;
|
||||
int targetIndex = 0;
|
||||
|
||||
while(targetIndex < length) {
|
||||
if(measurement >= 31440) {
|
||||
target[targetIndex++] = source[sourceIndex];
|
||||
measurement -= 31440;
|
||||
uint32_t sound_Store(uint8_t *out_buffer) {
|
||||
memset(out_buffer, 0, MAX_BUFFER_SIZE);
|
||||
uint32_t length = nSamplesPerSec / prosystem_frequency;
|
||||
sound_Resample(tia_buffer, out_buffer, length);
|
||||
tia_Clear();
|
||||
|
||||
// Ballblazer, Commando, various homebrew and hacks
|
||||
if(cartridge_pokey || xm_pokey_enabled) {
|
||||
uint8_t pokeySample[MAX_BUFFER_SIZE];
|
||||
memset(pokeySample, 0, MAX_BUFFER_SIZE);
|
||||
sound_Resample(pokey_buffer, pokeySample, length);
|
||||
|
||||
for(uint32_t index = 0; index < length; index++) {
|
||||
uint32_t sound = out_buffer[index] + pokeySample[index];
|
||||
out_buffer[index] = sound >> 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sourceIndex++;
|
||||
measurement += sound_format.nSamplesPerSec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// RestoreBuffer
|
||||
// ----------------------------------------------------------------------------
|
||||
static bool sound_RestoreBuffer( ) {
|
||||
if(sound_buffer != NULL) {
|
||||
HRESULT hr = sound_buffer->Restore( );
|
||||
if(FAILED(hr)) {
|
||||
logger_LogError(IDS_SOUND1,"");
|
||||
logger_LogError("",common_Format(hr));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ReleaseBuffer
|
||||
// ----------------------------------------------------------------------------
|
||||
static bool sound_ReleaseBuffer(LPDIRECTSOUNDBUFFER buffer) {
|
||||
if(buffer != NULL) {
|
||||
HRESULT hr = buffer->Release( );
|
||||
sound_buffer = NULL;
|
||||
if(FAILED(hr)) {
|
||||
logger_LogError(IDS_SOUND2,"");
|
||||
logger_LogError("",common_Format(hr));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ReleaseSound
|
||||
// ----------------------------------------------------------------------------
|
||||
static bool sound_ReleaseSound( ) {
|
||||
if(sound_dsound != NULL) {
|
||||
HRESULT hr = sound_dsound->Release( );
|
||||
sound_dsound = NULL;
|
||||
if(FAILED(hr)) {
|
||||
logger_LogError(IDS_SOUND3,"");
|
||||
logger_LogError("",common_Format(hr));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Initialize
|
||||
// ----------------------------------------------------------------------------
|
||||
bool sound_Initialize(HWND hWnd) {
|
||||
if(hWnd == NULL) {
|
||||
logger_LogError(IDS_INPUT1,"");
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT hr = DirectSoundCreate(NULL, &sound_dsound, NULL);
|
||||
if(FAILED(hr) || sound_dsound == NULL) {
|
||||
logger_LogError(IDS_SOUND4,"");
|
||||
logger_LogError("",common_Format(hr));
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = sound_dsound->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
|
||||
if(FAILED(hr)) {
|
||||
logger_LogError(IDS_INPUT6,"");
|
||||
logger_LogError("",common_Format(hr));
|
||||
return false;
|
||||
}
|
||||
|
||||
DSBUFFERDESC primaryDesc;
|
||||
primaryDesc.dwReserved = 0;
|
||||
primaryDesc.dwSize = sizeof(DSBUFFERDESC);
|
||||
primaryDesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
|
||||
primaryDesc.dwBufferBytes = 0;
|
||||
primaryDesc.lpwfxFormat = NULL;
|
||||
|
||||
hr = sound_dsound->CreateSoundBuffer(&primaryDesc, &sound_primaryBuffer, NULL);
|
||||
if(FAILED(hr) || sound_primaryBuffer == NULL) {
|
||||
logger_LogError(IDS_SOUND5,"");
|
||||
logger_LogError("",common_Format(hr));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!sound_SetFormat(SOUND_DEFAULT_FORMAT)) {
|
||||
logger_LogError(IDS_SOUND6,"");
|
||||
return false;
|
||||
}
|
||||
|
||||
//Leonis
|
||||
sound_SetSampleRate(samplerate);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// SetFormat
|
||||
// ----------------------------------------------------------------------------
|
||||
bool sound_SetFormat(WAVEFORMATEX format) {
|
||||
if(sound_dsound == NULL) {
|
||||
logger_LogError(IDS_SOUND7,"");
|
||||
return false;
|
||||
}
|
||||
if(sound_primaryBuffer == NULL) {
|
||||
logger_LogError(IDS_SOUND8,"");
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT hr = sound_primaryBuffer->SetFormat(&format);
|
||||
if(FAILED(hr)) {
|
||||
logger_LogError(IDS_SOUND9,"");
|
||||
logger_LogError("",common_Format(hr));
|
||||
return false;
|
||||
}
|
||||
|
||||
DSBUFFERDESC secondaryDesc;
|
||||
secondaryDesc.dwReserved = 0;
|
||||
secondaryDesc.dwSize = sizeof(DSBUFFERDESC);
|
||||
secondaryDesc.dwFlags = DSBCAPS_GLOBALFOCUS;
|
||||
secondaryDesc.dwBufferBytes = format.nSamplesPerSec;
|
||||
secondaryDesc.lpwfxFormat = &format;
|
||||
|
||||
hr = sound_dsound->CreateSoundBuffer(&secondaryDesc, &sound_buffer, NULL);
|
||||
if(FAILED(hr) || sound_buffer == NULL) {
|
||||
logger_LogError(IDS_SOUND10,"");
|
||||
logger_LogError("",common_Format(hr));
|
||||
return false;
|
||||
}
|
||||
|
||||
sound_format = format;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Store
|
||||
// ----------------------------------------------------------------------------
|
||||
bool sound_Store( ) {
|
||||
if(sound_dsound == NULL) {
|
||||
logger_LogError(IDS_SOUND7,"");
|
||||
return false;
|
||||
}
|
||||
if(sound_primaryBuffer == NULL) {
|
||||
logger_LogError(IDS_SOUND8,"");
|
||||
return false;
|
||||
}
|
||||
if(sound_buffer == NULL) {
|
||||
logger_LogError(IDS_SOUND11,"");
|
||||
return false;
|
||||
}
|
||||
|
||||
byte sample[1920];
|
||||
uint length = sound_GetSampleLength(sound_format.nSamplesPerSec, prosystem_frame, prosystem_frequency);
|
||||
sound_Resample(tia_buffer, sample, length);
|
||||
|
||||
if(cartridge_pokey) {
|
||||
byte pokeySample[1920];
|
||||
sound_Resample(pokey_buffer, pokeySample, length);
|
||||
for(int index = 0; index < length; index++) {
|
||||
sample[index] += pokeySample[index];
|
||||
sample[index] = sample[index] / 2;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD lockCount = 0;
|
||||
byte* lockStream = NULL;
|
||||
DWORD wrapCount = 0;
|
||||
byte* wrapStream = NULL;
|
||||
|
||||
HRESULT hr = sound_buffer->Lock(sound_counter, length, (void**)&lockStream, &lockCount, (void**)&wrapStream, &wrapCount, 0);
|
||||
if(FAILED(hr) || lockStream == NULL) {
|
||||
logger_LogError(IDS_SOUND12,"");
|
||||
logger_LogError("",common_Format(hr));
|
||||
if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint bufferCounter = 0;
|
||||
for(uint lockIndex = 0; lockIndex < lockCount; lockIndex++) {
|
||||
lockStream[lockIndex] = sample[bufferCounter++];
|
||||
}
|
||||
|
||||
for(uint wrapIndex = 0; wrapIndex < wrapCount; wrapIndex++) {
|
||||
wrapStream[wrapIndex] = sample[bufferCounter++];
|
||||
}
|
||||
|
||||
hr = sound_buffer->Unlock(lockStream, lockCount, wrapStream, wrapCount);
|
||||
if(FAILED(hr)) {
|
||||
logger_LogError(IDS_SOUND13,"");
|
||||
logger_LogError("",common_Format(hr));
|
||||
if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
sound_counter += length;
|
||||
if(sound_counter >= sound_format.nSamplesPerSec) {
|
||||
sound_counter -= sound_format.nSamplesPerSec;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Clear
|
||||
// ----------------------------------------------------------------------------
|
||||
bool sound_Clear( ) {
|
||||
if(sound_dsound == NULL) {
|
||||
logger_LogError(IDS_SOUND7,"");
|
||||
return false;
|
||||
}
|
||||
if(sound_primaryBuffer == NULL) {
|
||||
logger_LogError(IDS_SOUND8,"");
|
||||
return false;
|
||||
}
|
||||
if(sound_buffer == NULL) {
|
||||
logger_LogError(IDS_SOUND11,"");
|
||||
return false;
|
||||
}
|
||||
|
||||
byte* lockStream = NULL;
|
||||
DWORD lockCount = 0;
|
||||
HRESULT hr = sound_buffer->Lock(0, sound_format.nSamplesPerSec, (void**)&lockStream, &lockCount, NULL, NULL, DSBLOCK_ENTIREBUFFER);
|
||||
if(FAILED(hr) || lockStream == NULL) {
|
||||
logger_LogError(IDS_SOUND12,"");
|
||||
logger_LogError("",common_Format(hr));
|
||||
if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for(uint lockIndex = 0; lockIndex < lockCount; lockIndex++) {
|
||||
lockStream[lockIndex] = 0;
|
||||
}
|
||||
|
||||
hr = sound_buffer->Unlock(lockStream, lockCount, NULL, NULL);
|
||||
if(FAILED(hr)) {
|
||||
logger_LogError(IDS_SOUND13,"");
|
||||
logger_LogError("",common_Format(hr));
|
||||
if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Play
|
||||
// ----------------------------------------------------------------------------
|
||||
bool sound_Play( ) {
|
||||
if(sound_dsound == NULL) {
|
||||
logger_LogError(IDS_SOUND7,"");
|
||||
return false;
|
||||
}
|
||||
if(sound_primaryBuffer == NULL) {
|
||||
logger_LogError(IDS_SOUND8,"");
|
||||
return false;
|
||||
}
|
||||
if(sound_buffer == NULL) {
|
||||
logger_LogError(IDS_SOUND11,"");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!sound_muted) {
|
||||
HRESULT hr = sound_buffer->SetCurrentPosition(0);
|
||||
if(FAILED(hr)) {
|
||||
logger_LogError(IDS_SOUND14,"");
|
||||
logger_LogError("",common_Format(hr));
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = sound_buffer->Play(0, 0, DSBPLAY_LOOPING);
|
||||
if(FAILED(hr)) {
|
||||
logger_LogError(IDS_SOUND15,"");
|
||||
logger_LogError("",common_Format(hr));
|
||||
if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
sound_counter = (sound_format.nSamplesPerSec / prosystem_frequency) * (sound_latency * SOUND_LATENCY_SCALE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Stop
|
||||
// ----------------------------------------------------------------------------
|
||||
bool sound_Stop( ) {
|
||||
if(sound_dsound == NULL) {
|
||||
logger_LogError(IDS_SOUND7,"");
|
||||
return false;
|
||||
}
|
||||
if(sound_primaryBuffer == NULL) {
|
||||
logger_LogError(IDS_SOUND8,"");
|
||||
return false;
|
||||
}
|
||||
if(sound_buffer == NULL) {
|
||||
logger_LogError(IDS_SOUND11,"");
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT hr = sound_buffer->Stop( );
|
||||
if(FAILED(hr)) {
|
||||
logger_LogError(IDS_SOUND16,"");
|
||||
logger_LogError("",common_Format(hr));
|
||||
if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// SetSampleRate
|
||||
// ----------------------------------------------------------------------------
|
||||
bool sound_SetSampleRate(uint rate) {
|
||||
sound_format.nSamplesPerSec = rate;
|
||||
sound_format.nAvgBytesPerSec = rate;
|
||||
return sound_SetFormat(sound_format);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// GetSampleRate
|
||||
// ----------------------------------------------------------------------------
|
||||
uint sound_GetSampleRate( ) {
|
||||
return sound_format.nSamplesPerSec;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// SetMuted
|
||||
// ----------------------------------------------------------------------------
|
||||
bool sound_SetMuted(bool muted) {
|
||||
if(sound_muted != muted) {
|
||||
if(!muted) {
|
||||
if(!sound_Play( )) {
|
||||
return false;
|
||||
for(uint32_t index = 0; index < length; index++) {
|
||||
out_buffer[index] = out_buffer[index] * 0.75; //>> 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!sound_Stop( )) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
sound_muted = muted;
|
||||
}
|
||||
return true;
|
||||
pokey_Clear();
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// IsMuted
|
||||
// ----------------------------------------------------------------------------
|
||||
bool sound_IsMuted( ) {
|
||||
return sound_muted;
|
||||
void sound_SetSampleRate(uint32_t rate) {
|
||||
nSamplesPerSec = rate;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Release
|
||||
// ----------------------------------------------------------------------------
|
||||
void sound_Release( ) {
|
||||
sound_ReleaseBuffer(sound_buffer);
|
||||
sound_ReleaseBuffer(sound_primaryBuffer);
|
||||
sound_ReleaseSound( );
|
||||
}
|
||||
uint32_t sound_GetSampleRate(void) {
|
||||
return nSamplesPerSec;
|
||||
}
|
||||
|
||||
+4
-24
@@ -24,19 +24,8 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef SOUND_H
|
||||
#define SOUND_H
|
||||
#define SOUND_LATENCY_NONE 0
|
||||
#define SOUND_LATENCY_VERY_LOW 1
|
||||
#define SOUND_LATENCY_LOW 2
|
||||
#define SOUND_LATENCY_MEDIUM 3
|
||||
#define SOUND_LATENCY_HIGH 4
|
||||
#define SOUND_LATENCY_VERY_HIGH 5
|
||||
//#define NULL 0
|
||||
|
||||
//#include <DSound.h>
|
||||
#include "Common.h"
|
||||
#include "Logger.h"
|
||||
#include "ProSystem.h"
|
||||
#include "Configuration.h"
|
||||
#include "Tia.h"
|
||||
#include "Pokey.h"
|
||||
|
||||
@@ -44,17 +33,8 @@ typedef unsigned char byte;
|
||||
typedef unsigned short word;
|
||||
typedef unsigned int uint;
|
||||
|
||||
extern bool sound_Initialize(HWND hWnd);
|
||||
extern bool sound_Store( );
|
||||
extern bool sound_Clear( );
|
||||
extern bool sound_SetFormat(WAVEFORMATEX format);
|
||||
extern bool sound_Play( );
|
||||
extern bool sound_Stop( );
|
||||
extern bool sound_SetSampleRate(uint rate);
|
||||
extern uint sound_GetSampleRate( );
|
||||
extern bool sound_SetMuted(bool muted);
|
||||
extern bool sound_IsMuted( );
|
||||
extern void sound_Release( );
|
||||
extern byte sound_latency;
|
||||
extern uint sound_Store(byte *out_buffer);
|
||||
extern void sound_SetSampleRate(uint rate);
|
||||
extern uint sound_GetSampleRate();
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+20
-20
@@ -5,7 +5,7 @@
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2005 Greg Stanton
|
||||
//
|
||||
//
|
||||
// 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
|
||||
@@ -21,30 +21,31 @@
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
// ----------------------------------------------------------------------------
|
||||
// TiaSound is Copyright(c) 1997 by Ron Fries
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of version 2 of the GNU Library General Public License
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
|
||||
// General Public License for more details.
|
||||
// To obtain a copy of the GNU Library General Public License, write to the
|
||||
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of version 2 of the GNU Library General Public License
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
|
||||
// General Public License for more details.
|
||||
// To obtain a copy of the GNU Library General Public License, write to the
|
||||
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// Any permitted reproduction of these routines, in whole or in part, must
|
||||
// bear this legend.
|
||||
// bear this legend.
|
||||
// ----------------------------------------------------------------------------
|
||||
// Tia.cpp
|
||||
// ----------------------------------------------------------------------------
|
||||
#include "Tia.h"
|
||||
#include <string.h>
|
||||
#define TIA_POLY4_SIZE 15
|
||||
#define TIA_POLY5_SIZE 31
|
||||
#define TIA_POLY9_SIZE 511
|
||||
|
||||
byte tia_buffer[TIA_BUFFER_SIZE] = {0};
|
||||
uint tia_size = 524;
|
||||
uint tia_size = TIA_BUFFER_SIZE; // previously was 524
|
||||
|
||||
static const byte TIA_POLY4[ ] = {1,1,0,1,1,1,0,0,0,0,1,0,1,0,0};
|
||||
static const byte TIA_POLY5[ ] = {0,0,1,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,0,0,0,1};
|
||||
@@ -119,9 +120,8 @@ void tia_Reset( ) {
|
||||
// Clear
|
||||
// ----------------------------------------------------------------------------
|
||||
void tia_Clear( ) {
|
||||
for(int index = 0; index < TIA_BUFFER_SIZE; index++) {
|
||||
tia_buffer[index] = 0;
|
||||
}
|
||||
tia_soundCntr = 0;
|
||||
memset(tia_buffer, 0, TIA_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -130,7 +130,7 @@ void tia_Clear( ) {
|
||||
void tia_SetRegister(word address, byte data) {
|
||||
byte channel;
|
||||
byte frequency;
|
||||
|
||||
|
||||
switch(address) {
|
||||
case AUDC0:
|
||||
tia_audc[0] = data & 15;
|
||||
@@ -203,4 +203,4 @@ void tia_Process(uint length) {
|
||||
tia_soundCntr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIDOjCCAi0GByqGSM44BAEwggIgAoIBAQD/nSuLzikeU6MrymSPr34AiU2RDJz6
|
||||
0pm/3PPs27f6QTtbUAvGC13q6XWrE3HJU8Gz7RM0EJZGpiwb86LgqOJhjfQ7WKse
|
||||
uaGdbHnvJEFsGqpKX7rnUWaWO3HAsKzDx4HzJqKupFEbTbzXl/GT3JMm+a3PXA3S
|
||||
kyATydRPrX583Ih8iHO1zQs1pwp2AnUvaQXvp4QOLFWheH5napkDZBjc9B7H38dg
|
||||
f4c0QqEXJw0lJbG26FxhpOWMiXwpWpOHSfb+XtmzpeTDIHxKPLMEdf2wc+xNC/M9
|
||||
GdVBfM7+hCEhl1JGqNWPpT7ZzciX8Cxg+5/MIfx+BQ7xQ4wo1SN7y1bZAhUAuBcT
|
||||
+ZsHbLXlR3uGHLIMg8boUKcCggEAGKgD56/tB6siFr5zEY+RTozPLmbBEcvhz5/p
|
||||
hAQo7z7ODimZAA1MN1J7Hv7o1S5D9dpZuOnGhiXaN3Z50WdePb9LVH7twrB8v3Xn
|
||||
ZOEHpumYNcYhvXrIx8LbhnMZmU27xSnrOQF9UfokRxGnXkNmlIwjT0NWqZCqQZwM
|
||||
wVj1Bgld3YV7CpGTF3aGM6a0pk9LBB71PoczXAx0Cum87ouXXy3c8F/82RF9tgXE
|
||||
ZBQ+7K2QXYPv9smbYDB+ZlsQ4VTOi3AReG5AeHTVWha3uaSFxY5vKpfau31iMRuT
|
||||
b1VQ2HVynBpemwhAw4FFvj5dm94aN0Rrvq9BKM09DL4zoOlLogOCAQUAAoIBAE8B
|
||||
I8z38GdbtswSoSV5JZ9z9cBMj/7x/sHi5ED9v1M8MD6AcxJSbo2cbK98xA3A9U22
|
||||
6XFHthGReVLa0dyN3Ov+GhBdf8b4CBuebAAS4z8du2EvUFtwDUHorLIo2Qtq2SYR
|
||||
wpznpB9+3g+z+8GZbzZkdm2mFBKa6GItj82qfEHwxB40aEBx7uQXzM3TH0rV8sMq
|
||||
u91aAVUQuoiG2/IYWc5O34kKMlHUTt6+uuJiSG0ax8ysWE5XltCfSh/VJcGrzKU6
|
||||
ZjGBzh8j5+KSXgoe9TuKlsnN5HDCZKaFTCvrxq889HJj0/ks4UrIF+meEyJvDt4P
|
||||
O4HHoKRtUdLEBMcY0JA=
|
||||
-----END PUBLIC KEY-----
|
||||
@@ -0,0 +1,2 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||
Reference in New Issue
Block a user