Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 |
+16
-6
@@ -9,7 +9,7 @@
|
||||
<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</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>3600</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
+146
-19
@@ -30,6 +30,8 @@ controller1=3
|
||||
controller2=3
|
||||
region=0
|
||||
flags=0
|
||||
crossx=15
|
||||
crossy=15
|
||||
[de3e9496cb7341f865f27e5a72c7f2f5]
|
||||
title=Alien Brigade
|
||||
type=2
|
||||
@@ -38,6 +40,16 @@ controller1=3
|
||||
controller2=3
|
||||
region=1
|
||||
flags=0
|
||||
crossx=15
|
||||
crossy=-20
|
||||
[510ea66b6375a848a21db019b36078dd]
|
||||
title=Apple Snaffle (Aug 3-Rev 1.30) (2010)
|
||||
type=1
|
||||
pokey=true
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=0
|
||||
[07342c78619ba6ffcc61c10e907e3b50]
|
||||
title=Asteroids
|
||||
type=0
|
||||
@@ -54,6 +66,7 @@ controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=0
|
||||
hblank=28
|
||||
[b558814d54904ce0582e2f6a801d03af]
|
||||
title=Ballblazer
|
||||
type=0
|
||||
@@ -62,22 +75,27 @@ controller1=1
|
||||
controller2=1
|
||||
region=1
|
||||
flags=0
|
||||
hblank=28
|
||||
[42682415906c21c6af80e4198403ffda]
|
||||
title=Barnyard Blaster
|
||||
type=1
|
||||
pokey=true
|
||||
controller1=1
|
||||
pokey=false
|
||||
controller1=2
|
||||
controller2=1
|
||||
region=0
|
||||
flags=0
|
||||
crossx=0
|
||||
crossy=10
|
||||
[babe2bc2976688bafb8b23c192658126]
|
||||
title=Barnyard Blaster
|
||||
type=1
|
||||
pokey=true
|
||||
controller1=1
|
||||
pokey=false
|
||||
controller1=2
|
||||
controller2=1
|
||||
region=1
|
||||
flags=0
|
||||
crossx=0
|
||||
crossy=12
|
||||
[f5f6b69c5eb4b55fc163158d1a6b423e]
|
||||
title=Basketbrawl
|
||||
type=4
|
||||
@@ -85,7 +103,7 @@ pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=1
|
||||
flags=0
|
||||
[fba002089fcfa176454ab507e0eb76cb]
|
||||
title=Basketbrawl
|
||||
type=4
|
||||
@@ -94,6 +112,22 @@ controller1=1
|
||||
controller2=1
|
||||
region=1
|
||||
flags=0
|
||||
[7adbd2cec2e2cbc1e0ad237778ee46b9]
|
||||
title=Beef Drop (Jul 18 2006)
|
||||
type=0
|
||||
pokey=true
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=0
|
||||
[aefb78276913e8a166e460222e378fec]
|
||||
title=Beef Drop (Oct 15 2006)
|
||||
type=0
|
||||
pokey=true
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=0
|
||||
[5a09946e57dbe30408a8f253a28d07db]
|
||||
title=Centipede
|
||||
type=0
|
||||
@@ -117,7 +151,7 @@ pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=1
|
||||
flags=0
|
||||
[59d4edb0230b5acc918b94f6bc94779f]
|
||||
title=Choplifter
|
||||
type=0
|
||||
@@ -125,7 +159,7 @@ pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=1
|
||||
flags=1
|
||||
flags=0
|
||||
[2e8e28f6ad8b9b9267d518d880c73ebb]
|
||||
title=Commando
|
||||
type=1
|
||||
@@ -166,6 +200,8 @@ controller1=3
|
||||
controller2=3
|
||||
region=0
|
||||
flags=0
|
||||
crossx=15
|
||||
crossy=10
|
||||
[63db371d67a98daec547b2abd5e7aa95]
|
||||
title=Crossbow
|
||||
type=2
|
||||
@@ -174,6 +210,8 @@ controller1=3
|
||||
controller2=3
|
||||
region=1
|
||||
flags=0
|
||||
crossx=15
|
||||
crossy=5
|
||||
[179b76ff729d4849b8f66a502398acae]
|
||||
title=Dark Chambers
|
||||
type=1
|
||||
@@ -213,7 +251,7 @@ pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=1;
|
||||
flags=0
|
||||
[408dca9fc40e2b5d805f403fa0509436]
|
||||
title=Dig Dug
|
||||
type=0
|
||||
@@ -448,7 +486,7 @@ region=0
|
||||
flags=0
|
||||
[5e0a1e832bbcea6facb832fde23a440a]
|
||||
title=Karateka
|
||||
type=0
|
||||
type=4
|
||||
pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
@@ -469,7 +507,7 @@ pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=2;
|
||||
flags=0
|
||||
[2931b75811ad03f3ac9330838f3d231b]
|
||||
title=Kung Fu Master
|
||||
type=0
|
||||
@@ -530,18 +568,22 @@ flags=0
|
||||
title=Meltdown
|
||||
type=4
|
||||
pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
controller1=2
|
||||
controller2=2
|
||||
region=0
|
||||
flags=0
|
||||
crossx=0
|
||||
crossy=20
|
||||
[c80155d7eec9e3dcb79aa6b83c9ccd1e]
|
||||
title=Meltdown
|
||||
type=4
|
||||
pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
controller1=2
|
||||
controller2=2
|
||||
region=1
|
||||
flags=0
|
||||
crossx=0
|
||||
crossy=10
|
||||
[bc1e905db1008493a9632aa83ab4682b]
|
||||
title=Midnight Mutants
|
||||
type=4
|
||||
@@ -549,7 +591,7 @@ pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=1
|
||||
flags=0
|
||||
[6794ea31570eba0b88a0bf1ead3f3f1b]
|
||||
title=Midnight Mutants
|
||||
type=4
|
||||
@@ -557,7 +599,15 @@ pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=1
|
||||
flags=1
|
||||
flags=0
|
||||
[017066f522908081ec3ee624f5e4a8aa]
|
||||
title=Missing in Action
|
||||
type=2
|
||||
pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=3
|
||||
[3bc8f554cf86f8132a623cc2201a564b]
|
||||
title=Motor Psycho
|
||||
type=4
|
||||
@@ -639,7 +689,15 @@ controller2=1
|
||||
region=1
|
||||
flags=0
|
||||
[ec206c8db4316eb1ebce9fc960da7d8f]
|
||||
title=Pit Fighter
|
||||
title=Pit Fighter (Overdump)
|
||||
type=4
|
||||
pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=0
|
||||
[05f43244465943ce819780a71a5b572a]
|
||||
title=Pit Fighter
|
||||
type=4
|
||||
pokey=false
|
||||
controller1=1
|
||||
@@ -653,7 +711,7 @@ pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=1
|
||||
flags=0
|
||||
[2837a8fd49b7fc7ccd70fd45b69c5099]
|
||||
title=Planet Smashers
|
||||
type=4
|
||||
@@ -662,6 +720,14 @@ controller1=1
|
||||
controller2=1
|
||||
region=1
|
||||
flags=0
|
||||
[86546808dc60961cdb1b20e761c50ab1]
|
||||
title=Plutos
|
||||
type=3
|
||||
pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=0
|
||||
[584582bb09ee8122e7fc09dc7d1ed813]
|
||||
title=Pole Position II
|
||||
type=0
|
||||
@@ -694,7 +760,23 @@ controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=0
|
||||
[442761655bb25ddfe5f7ab16bf591c6f]
|
||||
title=Rampart
|
||||
type=1
|
||||
pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=0
|
||||
[bfad016d6e77eaccec74c0340aded8b9]
|
||||
title=Realsports Baseball (Overdump)
|
||||
type=1
|
||||
pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=0
|
||||
[383ed9bd1efb9b6cb3388a777678c928]
|
||||
title=Realsports Baseball
|
||||
type=1
|
||||
pokey=false
|
||||
@@ -718,6 +800,7 @@ controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=0
|
||||
dualanalog=true
|
||||
[980c35ae9625773a450aa7ef51751c04]
|
||||
title=Scrapyard Dog
|
||||
type=4
|
||||
@@ -742,6 +825,26 @@ controller1=2
|
||||
controller2=2
|
||||
region=0
|
||||
flags=0
|
||||
crossx=13
|
||||
crossy=-13
|
||||
[5469b4de0608f23a5c4f98f331c9e75f]
|
||||
title=Sentinel
|
||||
type=4
|
||||
pokey=false
|
||||
controller1=2
|
||||
controller2=2
|
||||
region=1
|
||||
flags=0
|
||||
crossx=20
|
||||
crossy=25
|
||||
[2d643ac548c40e58c99d0fe433ba4ba0]
|
||||
title=Sirius
|
||||
type=3
|
||||
pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=0
|
||||
[cbb0746192540a13b4c7775c7ce2021f]
|
||||
title=Summer Games
|
||||
type=3
|
||||
@@ -783,6 +886,14 @@ controller2=1
|
||||
region=1
|
||||
flags=0
|
||||
[44f862bca77d68b56b32534eda5c198d]
|
||||
title=Tank Command (Overdump)
|
||||
type=1
|
||||
pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=0
|
||||
[5c4f752371a523f15e9980fea73b874d]
|
||||
title=Tank Command
|
||||
type=1
|
||||
pokey=false
|
||||
@@ -831,6 +942,14 @@ controller2=1
|
||||
region=0
|
||||
flags=0
|
||||
[d12e665347f354048b9d13092f7868c9]
|
||||
title=Tower Toppler (Overdump)
|
||||
type=3
|
||||
pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=0
|
||||
[8d64763db3100aadc552db5e6868506a]
|
||||
title=Tower Toppler
|
||||
type=3
|
||||
pokey=false
|
||||
@@ -847,6 +966,14 @@ controller2=1
|
||||
region=1
|
||||
flags=0
|
||||
[acf63758ecf3f3dd03e9d654ae6b69b7]
|
||||
title=Water Ski (Overdump)
|
||||
type=1
|
||||
pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=0
|
||||
[427cb05d0a1abb068998e2760d77f4fb]
|
||||
title=Water Ski
|
||||
type=1
|
||||
pokey=false
|
||||
@@ -885,7 +1012,7 @@ pokey=false
|
||||
controller1=1
|
||||
controller2=1
|
||||
region=0
|
||||
flags=1
|
||||
flags=0
|
||||
[b1a9f196ce5f47ca8caf8fa7bc4ca46c]
|
||||
title=Xevious
|
||||
type=0
|
||||
|
||||
@@ -35,9 +35,8 @@
|
||||
/* 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 */; };
|
||||
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,7 +87,6 @@
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
82CAFD1E0FEDD5B300CCDC7E /* config.yaml in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -99,8 +97,6 @@
|
||||
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>"; };
|
||||
82EC409E0FD9EC420017FC19 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
|
||||
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>"; };
|
||||
@@ -162,33 +158,6 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
B5008DAD0E8BFB3E005AECAF /* ProSystemGameCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProSystemGameCore.h; sourceTree = "<group>"; };
|
||||
@@ -235,7 +204,6 @@
|
||||
089C167CFE841241C02AAC07 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
82CAFD010FEDD54000CCDC7E /* dsa_pub.pem */,
|
||||
8D5B49B7048680CD000E48DA /* Info.plist */,
|
||||
089C167DFE841241C02AAC07 /* InfoPlist.strings */,
|
||||
);
|
||||
@@ -282,7 +250,6 @@
|
||||
32C88E010371C26100C91783 /* Other Sources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
82CAFD030FEDD54800CCDC7E /* config.yaml */,
|
||||
);
|
||||
name = "Other Sources";
|
||||
sourceTree = "<group>";
|
||||
@@ -365,47 +332,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>";
|
||||
@@ -438,7 +370,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastUpgradeCheck = 0420;
|
||||
LastUpgradeCheck = 0700;
|
||||
};
|
||||
buildConfigurationList = 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "ProSystem" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
@@ -464,7 +396,6 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */,
|
||||
82CAFD020FEDD54000CCDC7E /* dsa_pub.pem in Resources */,
|
||||
941F59FC17A77CC90005D7EA /* ProSystem.dat in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -505,6 +436,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 */,
|
||||
@@ -560,6 +492,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 +500,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 +513,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 +521,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 +532,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;
|
||||
};
|
||||
|
||||
+253
-155
@@ -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,120 @@
|
||||
|
||||
@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 UTF8String]))
|
||||
{
|
||||
NSString *databasePath = [[[NSBundle bundleForClass:[self class]] resourcePath] stringByAppendingPathComponent:@"ProSystem.dat"];
|
||||
database_filename = [databasePath UTF8String];
|
||||
database_enabled = true;
|
||||
|
||||
|
||||
// BIOS is optional
|
||||
NSString *biosROM = [[self biosDirectoryPath] stringByAppendingPathComponent:@"7800 BIOS (U).rom"];
|
||||
if (bios_Load([biosROM UTF8String]))
|
||||
bios_enabled = true;
|
||||
|
||||
|
||||
NSLog(@"Headerless MD5 hash: %s", cartridge_digest.c_str());
|
||||
NSLog(@"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( );
|
||||
|
||||
prosystem_Reset();
|
||||
|
||||
std::string title = common_Trim(cartridge_title);
|
||||
NSLog(@"Now Loading: %@", [NSString stringWithUTF8String:title.c_str()]);
|
||||
|
||||
NSLog(@"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 defaults for Bentley Bear (homebrew) so button 1 = run/shoot and button 2 = jump
|
||||
if(cartridge_digest == "ad35a98040a2facb10ecb120bf83bcc3")
|
||||
{
|
||||
_inputState[LEFT_DIFF_SWITCH] = RIGHT_POSITION;
|
||||
_inputState[RIGHT_DIFF_SWITCH] = LEFT_POSITION;
|
||||
}
|
||||
|
||||
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 +163,31 @@ static void display_ResetPalette32( ) {
|
||||
prosystem_Reset();
|
||||
}
|
||||
|
||||
#pragma mark Video
|
||||
- (NSTimeInterval)frameInterval
|
||||
{
|
||||
return cartridge_region == REGION_NTSC ? 60 : 50;
|
||||
}
|
||||
|
||||
#pragma mark - Video
|
||||
|
||||
- (const void *)videoBuffer
|
||||
{
|
||||
return _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
|
||||
@@ -179,29 +205,80 @@ static void display_ResetPalette32( ) {
|
||||
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;
|
||||
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(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"
|
||||
|
||||
+31
-8
@@ -37,6 +37,10 @@ bool cartridge_pokey;
|
||||
byte cartridge_controller[2];
|
||||
byte cartridge_bank;
|
||||
uint cartridge_flags;
|
||||
int cartridge_crosshair_x;
|
||||
int cartridge_crosshair_y;
|
||||
bool cartridge_dualanalog = false;
|
||||
uint cartridge_hblank = 34;
|
||||
|
||||
static byte* cartridge_buffer = NULL;
|
||||
static uint cartridge_size = 0;
|
||||
@@ -71,6 +75,12 @@ static bool cartridge_CC2(const byte* header) {
|
||||
// GetBankOffset
|
||||
// ----------------------------------------------------------------------------
|
||||
static uint cartridge_GetBankOffset(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) * 16384;
|
||||
}
|
||||
|
||||
return bank * 16384;
|
||||
}
|
||||
|
||||
@@ -95,7 +105,7 @@ static void cartridge_ReadHeader(const byte* header) {
|
||||
}
|
||||
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];
|
||||
@@ -129,8 +139,7 @@ static void cartridge_ReadHeader(const byte* header) {
|
||||
}
|
||||
}
|
||||
|
||||
//cartridge_pokey = (header[54] & 1)? true: false;
|
||||
cartridge_pokey = true;
|
||||
cartridge_pokey = (header[54] & 1)? true: false;
|
||||
cartridge_controller[0] = header[55];
|
||||
cartridge_controller[1] = header[56];
|
||||
cartridge_region = header[57];
|
||||
@@ -163,6 +172,7 @@ if (cartridge_CC2(header)) {
|
||||
cartridge_ReadHeader(header);
|
||||
size -= 128;
|
||||
offset = 128;
|
||||
cartridge_size = size;
|
||||
}
|
||||
else {
|
||||
cartridge_size = size;
|
||||
@@ -192,7 +202,7 @@ bool cartridge_Load(std::string filename) {
|
||||
|
||||
byte* data = NULL;
|
||||
//uint size = archive_GetUncompressedFileSize(filename);
|
||||
uint size;
|
||||
uint size = 0;
|
||||
|
||||
if(size == 0) {
|
||||
FILE *file = fopen(filename.c_str( ), "rb");
|
||||
@@ -201,13 +211,13 @@ bool cartridge_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 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;
|
||||
@@ -318,8 +328,7 @@ void cartridge_Write(word address, byte data) {
|
||||
break;
|
||||
}
|
||||
|
||||
//if(cartridge_pokey && address >= 0x4000 && address < 0x4009) {
|
||||
if(address >= 0x4000 && address < 0x4009) {
|
||||
if(cartridge_pokey && address >= 0x4000 && address <= 0x400f) {
|
||||
switch(address) {
|
||||
case POKEY_AUDF1:
|
||||
pokey_SetRegister(POKEY_AUDF1, data);
|
||||
@@ -348,6 +357,9 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -393,5 +405,16 @@ void cartridge_Release( ) {
|
||||
delete [ ] cartridge_buffer;
|
||||
cartridge_size = 0;
|
||||
cartridge_buffer = NULL;
|
||||
|
||||
cartridge_type = 0;
|
||||
cartridge_region = 0;
|
||||
cartridge_pokey = 0;
|
||||
memset(cartridge_controller, 0, sizeof(cartridge_controller));
|
||||
cartridge_bank = 0;
|
||||
cartridge_flags = 0;
|
||||
cartridge_crosshair_x = 0;
|
||||
cartridge_crosshair_y = 0;
|
||||
cartridge_hblank = 34;
|
||||
cartridge_dualanalog = false;
|
||||
}
|
||||
}
|
||||
|
||||
+9
-1
@@ -36,7 +36,6 @@
|
||||
#define CARTRIDGE_CONTROLLER_LIGHTGUN 2
|
||||
#define CARTRIDGE_WSYNC_MASK 2
|
||||
#define CARTRIDGE_CYCLE_STEALING_MASK 1
|
||||
//#define NULL 0
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
@@ -70,4 +69,13 @@ extern byte cartridge_controller[2];
|
||||
extern byte cartridge_bank;
|
||||
extern uint cartridge_flags;
|
||||
|
||||
// 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;
|
||||
|
||||
#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);
|
||||
|
||||
+25
-2
@@ -57,10 +57,11 @@ bool database_Load(std::string digest) {
|
||||
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++) {
|
||||
std::string entry[11];
|
||||
for(int index = 0; index < 11; index++) {
|
||||
fgets(buffer, 256, file);
|
||||
entry[index] = common_Remove(buffer, '\n');
|
||||
entry[index] = common_Remove(entry[index], '\r');
|
||||
}
|
||||
|
||||
cartridge_title = database_GetValue(entry[0]);
|
||||
@@ -70,6 +71,28 @@ 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 < 11; 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]));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
+43
-11
@@ -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;
|
||||
@@ -66,7 +66,7 @@ static void maria_StoreCell(byte data) {
|
||||
static 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 {
|
||||
byte kmode = memory_ram[CTRL] & 4;
|
||||
@@ -145,7 +145,7 @@ static void maria_WriteLineRAM(byte* buffer) {
|
||||
if(rmode == 0) {
|
||||
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;
|
||||
@@ -205,7 +205,7 @@ static void maria_StoreLineRAM( ) {
|
||||
maria_pp.b.h = memory_ram[maria_dp.w + 2];
|
||||
|
||||
if(mode & 31) {
|
||||
maria_cycles += 8;
|
||||
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;
|
||||
@@ -213,7 +213,7 @@ static void maria_StoreLineRAM( ) {
|
||||
maria_dp.w += 4;
|
||||
}
|
||||
else {
|
||||
maria_cycles += 10;
|
||||
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 +226,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 +234,14 @@ 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 +258,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 +276,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 +302,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,14 +315,20 @@ 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;
|
||||
|
||||
+14
-4
@@ -46,6 +46,11 @@ void memory_Reset( ) {
|
||||
byte memory_Read(word address) {
|
||||
byte tmp_byte;
|
||||
|
||||
if(cartridge_pokey && address == POKEY_RANDOM)
|
||||
{
|
||||
return pokey_GetRegister(POKEY_RANDOM);
|
||||
}
|
||||
|
||||
switch ( address ) {
|
||||
case INTIM:
|
||||
case INTIM | 0x2:
|
||||
@@ -68,6 +73,7 @@ byte memory_Read(word address) {
|
||||
// Write
|
||||
// ----------------------------------------------------------------------------
|
||||
void memory_Write(word address, byte data) {
|
||||
|
||||
if(!memory_rom[address]) {
|
||||
switch(address) {
|
||||
case WSYNC:
|
||||
@@ -113,10 +119,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 +157,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 {
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#ifndef MEMORY_H
|
||||
#define MEMORY_H
|
||||
#define MEMORY_SIZE 65536
|
||||
//#define NULL 0
|
||||
|
||||
#include "Equates.h"
|
||||
#include "Bios.h"
|
||||
|
||||
+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"
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
#include <stdlib.h>
|
||||
#include "Pokey.h"
|
||||
#include "Prosystem.h"
|
||||
#define POKEY_NOTPOLY5 0x80
|
||||
#define POKEY_POLY4 0x40
|
||||
#define POKEY_PURE 0x20
|
||||
@@ -65,6 +66,8 @@
|
||||
#define POKEY_CHANNEL4 3
|
||||
#define POKEY_SAMPLE 4
|
||||
|
||||
#define SK_RESET 0x03
|
||||
|
||||
byte pokey_buffer[POKEY_BUFFER_SIZE] = {0};
|
||||
uint pokey_size = 524;
|
||||
|
||||
@@ -90,6 +93,37 @@ 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;
|
||||
|
||||
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
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -120,6 +154,66 @@ void pokey_Reset( ) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
byte pokey_GetRegister(word address) {
|
||||
byte data = 0;
|
||||
|
||||
switch (address) {
|
||||
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;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -128,6 +222,10 @@ void pokey_Reset( ) {
|
||||
void pokey_SetRegister(word address, byte value) {
|
||||
byte channelMask;
|
||||
switch(address) {
|
||||
case POKEY_SKCTLS:
|
||||
SKCTL = value;
|
||||
return;
|
||||
|
||||
case POKEY_AUDF1:
|
||||
pokey_audf[POKEY_CHANNEL1] = value;
|
||||
channelMask = 1 << POKEY_CHANNEL1;
|
||||
|
||||
@@ -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
|
||||
|
||||
+309
-58
@@ -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,6 +46,7 @@ void prosystem_Reset( ) {
|
||||
if(cartridge_IsLoaded( )) {
|
||||
prosystem_paused = false;
|
||||
prosystem_frame = 0;
|
||||
sally_Reset( );
|
||||
region_Reset( );
|
||||
tia_Clear( );
|
||||
tia_Reset( );
|
||||
@@ -48,7 +55,7 @@ void prosystem_Reset( ) {
|
||||
memory_Reset( );
|
||||
maria_Clear( );
|
||||
maria_Reset( );
|
||||
riot_Reset ( );
|
||||
riot_Reset( );
|
||||
if(bios_enabled) {
|
||||
bios_Store( );
|
||||
}
|
||||
@@ -60,57 +67,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) 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) {
|
||||
pokey_Process(2);
|
||||
//}
|
||||
}
|
||||
|
||||
if(cartridge_pokey) pokey_Scanline();
|
||||
}
|
||||
|
||||
prosystem_frame++;
|
||||
if(prosystem_frame >= prosystem_frequency) {
|
||||
prosystem_frame = 0;
|
||||
@@ -127,72 +219,144 @@ 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] = {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;
|
||||
}
|
||||
|
||||
|
||||
// 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 );
|
||||
|
||||
#if 0
|
||||
if(!compress) {
|
||||
#endif
|
||||
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);
|
||||
#if 0
|
||||
}
|
||||
else {
|
||||
if(!archive_Compress(filename.c_str( ), "Save.sav", buffer, size)) {
|
||||
if(!archive_Compress(filename.c_str( ), "Save.sav", loc_buffer, size)) {
|
||||
logger_LogError("Failed to compress the save state data to the file " + filename + ".", PRO_SYSTEM_SOURCE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
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 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Load
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -202,10 +366,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] = {0};
|
||||
|
||||
byte buffer[32829] = {0};
|
||||
uint size = archive_GetUncompressedFileSize(filename);
|
||||
if(size == 0) {
|
||||
FILE* file = fopen(filename.c_str( ), "rb");
|
||||
@@ -214,26 +378,29 @@ 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 &&
|
||||
size != 16453 &&
|
||||
size != 32837 ) {
|
||||
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;
|
||||
@@ -241,7 +408,7 @@ bool prosystem_Load(const std::string filename) {
|
||||
fclose(file);
|
||||
}
|
||||
else if(size == 16445 || size == 32829) {
|
||||
archive_Uncompress(filename, buffer, size);
|
||||
archive_Uncompress(filename, loc_buffer, size);
|
||||
}
|
||||
else {
|
||||
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
|
||||
@@ -251,13 +418,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 +435,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 +443,119 @@ 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 && size != 32837) {
|
||||
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 || size == 32837 )
|
||||
{
|
||||
// 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++];
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool prosystem_Load_buffer(const byte *buffer)
|
||||
{
|
||||
uint size = cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM ? 32837 : 16453;
|
||||
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 && size != 32837) {
|
||||
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;
|
||||
}
|
||||
|
||||
// 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++];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Pause
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
+19
-1
@@ -24,7 +24,6 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef PRO_SYSTEM_H
|
||||
#define PRO_SYSTEM_H
|
||||
//#define NULL 0
|
||||
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
@@ -44,10 +43,21 @@ 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 +66,13 @@ extern word prosystem_frequency;
|
||||
extern byte prosystem_frame;
|
||||
extern word prosystem_scanlines;
|
||||
extern uint prosystem_cycles;
|
||||
extern uint prosystem_extra_cycles;
|
||||
|
||||
// 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
|
||||
|
||||
+18
-1
@@ -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;
|
||||
@@ -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:
|
||||
|
||||
+65
-378
@@ -23,411 +23,98 @@
|
||||
// Sound.cpp
|
||||
// ----------------------------------------------------------------------------
|
||||
#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;
|
||||
typedef struct
|
||||
{
|
||||
uint nSamplesPerSec;
|
||||
word nChannels;
|
||||
word wBitsPerSample;
|
||||
} SOUNDCONFIG;
|
||||
|
||||
static const SOUNDCONFIG soundDefaults = {48000, 1, 8};
|
||||
static SOUNDCONFIG sound_format = soundDefaults;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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 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;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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;
|
||||
static void sound_Resample(const byte *source, byte *target, int length)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
uint sound_Store(byte *out_buffer)
|
||||
{
|
||||
memset(out_buffer, 0, MAX_BUFFER_SIZE);
|
||||
uint length = 48000 / prosystem_frequency; // sound_GetSampleLength(sound_format.nSamplesPerSec, prosystem_frame, prosystem_frequency);
|
||||
sound_Resample(tia_buffer, out_buffer, length);
|
||||
|
||||
// Ballblazer, Commando, various homebrew and hacks
|
||||
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++)
|
||||
{
|
||||
out_buffer[index] += pokeySample[index];
|
||||
out_buffer[index] = out_buffer[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;
|
||||
return length;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// SetSampleRate
|
||||
// ----------------------------------------------------------------------------
|
||||
bool sound_SetSampleRate(uint rate) {
|
||||
sound_format.nSamplesPerSec = rate;
|
||||
sound_format.nAvgBytesPerSec = rate;
|
||||
return sound_SetFormat(sound_format);
|
||||
void sound_SetSampleRate(uint rate)
|
||||
{
|
||||
sound_format.nSamplesPerSec = rate;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// GetSampleRate
|
||||
// ----------------------------------------------------------------------------
|
||||
uint sound_GetSampleRate( ) {
|
||||
return sound_format.nSamplesPerSec;
|
||||
uint sound_GetSampleRate()
|
||||
{
|
||||
return sound_format.nSamplesPerSec;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// SetMuted
|
||||
// ----------------------------------------------------------------------------
|
||||
bool sound_SetMuted(bool muted) {
|
||||
if(sound_muted != muted) {
|
||||
if(!muted) {
|
||||
if(!sound_Play( )) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!sound_Stop( )) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
sound_muted = muted;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// IsMuted
|
||||
// ----------------------------------------------------------------------------
|
||||
bool sound_IsMuted( ) {
|
||||
return sound_muted;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Release
|
||||
// ----------------------------------------------------------------------------
|
||||
void sound_Release( ) {
|
||||
sound_ReleaseBuffer(sound_buffer);
|
||||
sound_ReleaseBuffer(sound_primaryBuffer);
|
||||
sound_ReleaseSound( );
|
||||
}
|
||||
+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
@@ -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-----
|
||||
Reference in New Issue
Block a user