18 Commits

Author SHA1 Message Date
clobber 1660bd3992 Bump version. Core is based off of 1.3e + Wii7800 patches 2015-12-22 19:59:02 -07:00
clobber 6b71d9c58c Clean up deprecated methods. 2015-12-12 17:06:54 -08:00
Alexander Strange 5a02e16589 Update projects - fix debug builds, make deployment 10.11, enable objc-arc properly, build faster 2015-10-17 13:04:19 -07:00
clobber c5b4b1166d Turn off GCC_NO_COMMON_BLOCKS 2015-10-09 19:40:21 -05:00
Christoph Leimbrock c5efc99e31 Fix some warning and adjust project settings. 2015-10-06 22:04:33 +02:00
clobber 76e280cf65 Set some difficulty switch defaults 2015-08-26 02:34:31 -05:00
clobber 8712f18b46 Fix PAR 2015-08-15 18:37:35 -05:00
clobber 7dabdd6fbd Support light gun 2015-08-15 18:37:10 -05:00
clobber e30fdfec8e Update internal ROM database
* Barnyard Blaster does not use POKEY
* Sirius does not use light gun
2015-08-15 14:42:58 -05:00
clobber 2ed73c7f79 Add plist keys to support rewinding 2015-08-10 01:10:29 -05:00
clobber 0fb71b683b Add state serialization/deserialization 2015-08-10 01:10:10 -05:00
clobber e6d22582c7 Clean up 2015-08-09 02:53:20 -05:00
clobber ec17ea864f Refactor sound 2015-08-07 03:44:38 -05:00
clobber 0010a37c60 Enable save/load state support 2015-08-06 15:14:10 -05:00
clobber ec2a8c68e5 Fix bit shift overflow warning and enable -O3
With optimization on, cartridge_size will result in garbage/undefined behavior and break loading of games not found in the database
2015-08-06 01:11:14 -05:00
clobber 8518f32fbb Project file clean up 2015-08-05 22:49:26 -05:00
clobber cd21ca7a04 Merge fixes and improvements from Wii7800 0.3 fork by Raz0red
Includes:
* MARIA - increased accuracy of cycle timing, games now run at close to intended speed (One on One, Tower Toppler, Summer Games, KLAX, Karateka, etc).
* Timers now properly take into consideration cycles generated via MARIA and during WSYNC.
* POKEY - implemented RANDOM (read) and SKCTLS (write), Ballblazer now plays all sounds.
* MARIA cycle stealing and WSYNC now enabled by default.
* Database - flags=0 (enable both), flags=1 (disable MARIA cycle stealing), flags=2 (disable WSYNC), flags=3 (disable both).
* Database - Ability to adjust HBLANK period prior to DMA (Ballblazer hack), lightgun crosshair x/y offset (frontend) and whether cart supports dual analog (Robotron, frontend).
* Increased compatibility for PAL games (Ballblazer, Commando, and Food Fight).
* Compatibility and graphical glitches fixed in various games (including Ballblazer, Kung Fu Master, Midnight Mutants, Summer Games, Plutos).
* States now save/restore state of RIOT timers for games using them.
* Updated palette (Underball).

Missing:
* Lightgun support
* High Score Cartridge support
2015-08-05 22:48:49 -05:00
clobber 3dd30d8179 ProSystem.dat is not an executable file 2014-08-09 17:10:36 -05:00
27 changed files with 993 additions and 770 deletions
+7 -3
View File
@@ -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,7 +17,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.3.0.1</string>
<string>1.4</string>
<key>NSPrincipalClass</key>
<string>OEGameCoreController</string>
<key>OEGameCoreClass</key>
@@ -26,7 +26,11 @@
<dict>
<key>openemu.system.7800</key>
<dict>
<key>OEGameCoreSaveStatesNotSupported</key>
<key>OEGameCoreRewindBufferSeconds</key>
<integer>3600</integer>
<key>OEGameCoreRewindInterval</key>
<integer>0</integer>
<key>OEGameCoreSupportsRewinding</key>
<true/>
</dict>
</dict>
Executable → Regular
+68 -21
View File
@@ -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,7 @@ pokey=false
controller1=1
controller2=1
region=1
flags=1
flags=0
[017066f522908081ec3ee624f5e4a8aa]
title=Missing in Action
type=2
@@ -565,7 +607,7 @@ pokey=false
controller1=1
controller2=1
region=0
flags=2
flags=3
[3bc8f554cf86f8132a623cc2201a564b]
title=Motor Psycho
type=4
@@ -669,7 +711,7 @@ pokey=false
controller1=1
controller2=1
region=0
flags=1
flags=0
[2837a8fd49b7fc7ccd70fd45b69c5099]
title=Planet Smashers
type=4
@@ -758,6 +800,7 @@ controller1=1
controller2=1
region=0
flags=0
dualanalog=true
[980c35ae9625773a450aa7ef51751c04]
title=Scrapyard Dog
type=4
@@ -782,6 +825,8 @@ controller1=2
controller2=2
region=0
flags=0
crossx=13
crossy=-13
[5469b4de0608f23a5c4f98f331c9e75f]
title=Sentinel
type=4
@@ -790,12 +835,14 @@ controller1=2
controller2=2
region=1
flags=0
crossx=20
crossy=25
[2d643ac548c40e58c99d0fe433ba4ba0]
title=Sirius
type=3
pokey=false
controller1=2
controller2=2
controller1=1
controller2=1
region=0
flags=0
[cbb0746192540a13b4c7775c7ce2021f]
@@ -965,7 +1012,7 @@ pokey=false
controller1=1
controller2=1
region=0
flags=1
flags=0
[b1a9f196ce5f47ca8caf8fa7bc4ca46c]
title=Xevious
type=0
+19 -69
View File
@@ -36,6 +36,7 @@
/* Begin PBXBuildFile section */
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 */; };
@@ -157,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>"; };
@@ -358,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>";
@@ -431,7 +370,7 @@
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 0500;
LastUpgradeCheck = 0700;
};
buildConfigurationList = 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "ProSystem" */;
compatibilityVersion = "Xcode 3.2";
@@ -497,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 +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;
@@ -580,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;
@@ -591,29 +533,33 @@
isa = XCBuildConfiguration;
buildSettings = {
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_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;
};
@@ -621,29 +567,33 @@
isa = XCBuildConfiguration;
buildSettings = {
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_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;
};
+210 -172
View File
@@ -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,119 +42,120 @@
@interface ProSystemGameCore () <OE7800SystemResponderClient>
{
uint32_t *videoBuffer;
int videoWidth, videoHeight;
uint display_palette32[256];
byte keyboard_data[17];
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);
videoWidth = 320;
videoHeight = 240;
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 error:(NSError **)error
{
memset(keyboard_data, 0, sizeof(keyboard_data));
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"
keyboard_data[15] = 1;
_inputState[LEFT_DIFF_SWITCH] = LEFT_POSITION;
// Right difficulty switch defaults to right position, "(A)dvanced", which fixes Tower Toppler
keyboard_data[16] = 0;
if(cartridge_Load([path UTF8String])) {
//sound_Stop( );
//display_Clear( );
_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(@"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
current->videoWidth = maria_visibleArea.GetLength();
current->videoHeight = maria_visibleArea.GetHeight();
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 < current->videoHeight; indexY++) {
for(uint indexX = 0; indexX < current->videoWidth; 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 += current->videoWidth;
buffer += _videoWidth;
}
sound_Store();
int length = sound_Store(_soundBuffer);
[[self ringBufferAtIndex:0] write:_soundBuffer maxLength:length];
}
- (void)resetEmulation
@@ -162,11 +163,26 @@ 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, current->videoWidth, current->videoHeight);
return OEIntRectMake(0, 0, maria_visibleArea.GetLength(), maria_visibleArea.GetHeight());
}
- (OEIntSize)aspectSize
{
return OEIntSizeMake(maria_visibleArea.GetLength(), maria_visibleArea.GetHeight());
}
- (OEIntSize)bufferSize
@@ -174,11 +190,6 @@ static void display_ResetPalette32( ) {
return OEIntSizeMake(320, 292);
}
- (const void *)videoBuffer
{
return videoBuffer;
}
- (GLenum)pixelFormat
{
return GL_BGRA;
@@ -194,29 +205,80 @@ static void display_ResetPalette32( ) {
return GL_RGB8;
}
- (NSTimeInterval)frameInterval
{
return cartridge_region == REGION_NTSC ? 60 : 50;
}
#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
// +----------+--------------+-------------------------------------------------
@@ -244,28 +306,31 @@ const int ProSystemMap[] = { 3, 2, 1, 0, 4, 5, 9, 8, 7, 6, 10, 11, 13, 14, 12, 1
- (oneway void)didPush7800Button:(OE7800Button)button forPlayer:(NSUInteger)player;
{
int playerShift = player != 1 ? 6 : 0;
switch (button) {
switch(button)
{
case OE7800ButtonUp:
_inputState[ProSystemMap[button + playerShift]] ^= 1;
break;
case OE7800ButtonDown:
case OE7800ButtonLeft:
case OE7800ButtonRight:
case OE7800ButtonFire1:
case OE7800ButtonFire2:
keyboard_data[ProSystemMap[button + playerShift]] = 1;
_inputState[ProSystemMap[button + playerShift]] = 1;
break;
case OE7800ButtonSelect:
case OE7800ButtonPause:
case OE7800ButtonReset:
keyboard_data[ProSystemMap[button + 6]] = 1;
_inputState[ProSystemMap[button + 6]] = 1;
break;
case OE7800ButtonLeftDiff:
case OE7800ButtonRightDiff:
keyboard_data[ProSystemMap[button + 6]] ^= (1 << 0);
_inputState[ProSystemMap[button + 6]] ^= (1 << 0);
break;
default:
break;
}
@@ -274,109 +339,82 @@ const int ProSystemMap[] = { 3, 2, 1, 0, 4, 5, 9, 8, 7, 6, 10, 11, 13, 14, 12, 1
- (oneway void)didRelease7800Button:(OE7800Button)button forPlayer:(NSUInteger)player;
{
int playerShift = player != 1 ? 6 : 0;
switch (button) {
switch(button)
{
case OE7800ButtonUp:
_inputState[ProSystemMap[button + playerShift]] ^= 1;
break;
case OE7800ButtonDown:
case OE7800ButtonLeft:
case OE7800ButtonRight:
case OE7800ButtonFire1:
case OE7800ButtonFire2:
keyboard_data[ProSystemMap[button + playerShift]] = 0;
_inputState[ProSystemMap[button + playerShift]] = 0;
break;
case OE7800ButtonSelect:
case OE7800ButtonPause:
case OE7800ButtonReset:
keyboard_data[ProSystemMap[button + 6]] = 0;
_inputState[ProSystemMap[button + 6]] = 0;
break;
default:
break;
}
}
- (BOOL)saveStateToFileAtPath:(NSString *)fileName
- (oneway void)mouseMovedAtPoint:(OEIntPoint)aPoint
{
//return prosystem_Save([fileName UTF8String], false) ? YES : NO;
return NO;
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;
}
}
}
- (BOOL)loadStateFromFileAtPath:(NSString *)fileName
- (oneway void)leftMouseDownAtPoint:(OEIntPoint)aPoint
{
//return prosystem_Load([fileName UTF8String]) ? YES : NO;
return NO;
}
if(_isLightgunEnabled)
{
[self mouseMovedAtPoint:aPoint];
static uint sound_GetSampleLength(uint length, uint unit, uint unitMax) {
uint sampleLength = length / unitMax;
uint sampleRemain = length % unitMax;
if(sampleRemain != 0 && sampleRemain >= unit) {
sampleLength++;
}
return sampleLength;
}
static void sound_Resample(const 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;
}
_inputState[3] = 0;
}
}
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, 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++) {
sample[index] += pokeySample[index];
sample[index] = sample[index] / 2;
}
- (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;
}
[[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];
// }
}
@end
+2 -2
View File
@@ -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;
-1
View File
@@ -24,7 +24,6 @@
// ----------------------------------------------------------------------------
#ifndef BIOS_H
#define BIOS_H
//#define NULL 0
#include <string>
#include "Memory.h"
+22 -4
View File
@@ -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;
@@ -101,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];
@@ -207,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;
@@ -324,7 +328,7 @@ void cartridge_Write(word address, byte data) {
break;
}
if(cartridge_pokey && address >= 0x4000 && address < 0x4009) {
if(cartridge_pokey && address >= 0x4000 && address <= 0x400f) {
switch(address) {
case POKEY_AUDF1:
pokey_SetRegister(POKEY_AUDF1, data);
@@ -353,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;
}
}
}
@@ -398,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
View File
@@ -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
+7
View File
@@ -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
// ----------------------------------------------------------------------------
+1
View File
@@ -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);
+24 -2
View File
@@ -57,8 +57,8 @@ 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');
@@ -71,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;
}
}
-1
View File
@@ -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>
+42 -10
View File
@@ -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;
@@ -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;
+5
View File
@@ -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:
-1
View File
@@ -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
View File
@@ -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,
-1
View File
@@ -25,7 +25,6 @@
#ifndef PALETTE_H
#define PALETTE_H
#define PALETTE_SIZE 768
//#define NULL 0
#include <string>
#include "Logger.h"
+98
View File
@@ -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;
+27
View File
@@ -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
+307 -56
View File
@@ -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) {
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
View File
@@ -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
View File
@@ -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);
}
+21 -9
View File
@@ -28,15 +28,23 @@ bool riot_timing = false;
word riot_timer = TIM64T;
byte riot_intervals;
static byte riot_dra = 0;
static byte riot_drb = 0;
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;
}
// ----------------------------------------------------------------------------
@@ -104,12 +112,16 @@ void riot_SetInput(const byte* input) {
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*/
/*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;
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;
}
/*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)
+3
View File
@@ -41,5 +41,8 @@ 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
View File
@@ -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
View File
@@ -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
View File
@@ -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