29 Commits

Author SHA1 Message Date
clobber ebcb35c783 Bump version for sparkle updater. 2020-12-21 23:02:01 -07:00
clobber 74a023675d Add undocumented opcodes ASR and ANC from js7800 https://github.com/raz0red/js7800/commit/4d557c45d8806bc6dfbbd1835536332928cfeb21 2020-10-19 17:33:39 -05:00
C.W. Betts d0a5ab88d8 Merge branch 'master' of github.com:OpenEmu/ProSystem-Core into master 2020-10-01 02:04:21 -06:00
C.W. Betts bb87a68e59 Poke the plists: get the development language from Xcode build. 2020-10-01 01:51:37 -06:00
C.W. Betts 9228bbea43 Fix locations of the system plugin headers.
Minor Xcode maintenance.
2020-10-01 01:26:41 -06:00
clobber 56420c3a12 Merge fixes and improvements from Wii7800 0.5 fork by raz0red (https://github.com/raz0red/wii7800/releases/tag/0.5)
Includes:
- Partial Expansion Module (XM) support
  - XRAM
  - XPokey (limited to single Pokey)
- Added support for cartridges with sizes greater than 144k
- Additional bank switching modes and cartridge types
- Multiple bank switching fixes
- Reworked cartridge header detection
  - Now properly detects bank switching, RAM, etc.
  - Detects Expansion Module (XM)
  - Detects High score cartridge
  - Detects Pokey at $0450
- Cartridge database
  - Added several new cartridge properties
    - Pokey at $0450
    - Default difficulty switch settings
    - Expansion Module (XM) enabled/disabled
    - High score cartridge enabled/disabled
  - Database content
    - Fixed incorrect controller settings for Sirius, Crossbow,
        and Alien Brigade
    - Added many homebrew cartridges
- Fixed issue occurring when Kangaroo and Holey were enabled (caused
    background to be displayed, resulting in large black squares)

Missing:
- High Score Cartridge support
2020-08-23 00:36:54 -05:00
C.W. Betts 1742f0be53 Update language resources.
This quiets warnings in newer Xcode releases.

Also update framework locations.
2020-01-07 16:43:14 -07:00
clobber 408b2d3c10 Use -fileSystemRepresentation instead of -UTF8String for file names 2017-08-17 00:42:25 -05:00
Rudy Richter d2ed27ffca Enable direct-render 2017-07-22 11:06:00 -04:00
clobber 63968244dd Bump version for sparkle updater. Core is 1.3e + Wii7800 patches 2016-07-01 12:19:15 -05:00
clobber 9d16f5ef1e Limit rewind buffer to 60 seconds to reduce memory use 2016-06-30 01:36:11 -05:00
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
33 changed files with 3138 additions and 987 deletions
Binary file not shown.
+8 -4
View File
@@ -3,13 +3,13 @@
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>org.openemu.${PRODUCT_NAME:identifier}</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
@@ -17,7 +17,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.3.0.1</string>
<string>1.4.2</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>60</integer>
<key>OEGameCoreRewindInterval</key>
<integer>0</integer>
<key>OEGameCoreSupportsRewinding</key>
<true/>
</dict>
</dict>
Executable → Regular
+1647 -42
View File
File diff suppressed because it is too large Load Diff
+35 -79
View File
@@ -36,6 +36,8 @@
/* Begin PBXBuildFile section */
82EC409F0FD9EC420017FC19 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 82EC409E0FD9EC420017FC19 /* libz.dylib */; };
871EC9A224F08BF700CEC578 /* ExpansionModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 871EC9A124F08BF600CEC578 /* ExpansionModule.cpp */; };
8794D9691B74713300897F57 /* Sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 941F59AF17A6189D0005D7EA /* Sound.cpp */; };
8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };
8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; };
941DFB2715B6425200C6552F /* ProSystemGameCore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 941DFB2615B6425200C6552F /* ProSystemGameCore.mm */; };
@@ -92,11 +94,13 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
089C167EFE841241C02AAC07 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
82EC409E0FD9EC420017FC19 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
871EC9A024F08BF600CEC578 /* ExpansionModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExpansionModule.h; sourceTree = "<group>"; };
871EC9A124F08BF600CEC578 /* ExpansionModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExpansionModule.cpp; sourceTree = "<group>"; };
8D5B49B6048680CD000E48DA /* ProSystem.oecoreplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ProSystem.oecoreplugin; sourceTree = BUILT_PRODUCTS_DIR; };
8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
941DFB2615B6425200C6552F /* ProSystemGameCore.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ProSystemGameCore.mm; sourceTree = "<group>"; };
@@ -156,38 +160,11 @@
941F59BB17A6189D0005D7EA /* Zconf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Zconf.h; sourceTree = "<group>"; };
941F59BC17A6189D0005D7EA /* Zip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Zip.h; sourceTree = "<group>"; };
941F59BD17A6189D0005D7EA /* Zlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Zlib.h; sourceTree = "<group>"; };
941F59DB17A62ADD0005D7EA /* OpenEmuBase.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenEmuBase.framework; path = "../../Library/Developer/Xcode/DerivedData/OpenEmu-dsehantrxgyfywdpbneyslftzzvv/Build/Products/Debug/OpenEmuBase.framework"; sourceTree = "<group>"; };
941F59E017A630990005D7EA /* About.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = About.cpp; sourceTree = "<group>"; };
941F59E117A630990005D7EA /* About.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = About.h; sourceTree = "<group>"; };
941F59E217A630990005D7EA /* Common.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Common.cpp; sourceTree = "<group>"; };
941F59E317A630990005D7EA /* Common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Common.h; sourceTree = "<group>"; };
941F59E417A630990005D7EA /* Configuration.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Configuration.cpp; sourceTree = "<group>"; };
941F59E517A630990005D7EA /* Configuration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Configuration.h; sourceTree = "<group>"; };
941F59E617A630990005D7EA /* Console.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Console.cpp; sourceTree = "<group>"; };
941F59E717A630990005D7EA /* Console.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Console.h; sourceTree = "<group>"; };
941F59E817A630990005D7EA /* Database.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Database.cpp; sourceTree = "<group>"; };
941F59E917A630990005D7EA /* Database.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Database.h; sourceTree = "<group>"; };
941F59EA17A630990005D7EA /* Display.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Display.cpp; sourceTree = "<group>"; };
941F59EB17A630990005D7EA /* Display.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Display.h; sourceTree = "<group>"; };
941F59EC17A630990005D7EA /* Help.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Help.cpp; sourceTree = "<group>"; };
941F59ED17A630990005D7EA /* Help.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Help.h; sourceTree = "<group>"; };
941F59EE17A630990005D7EA /* Input.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Input.cpp; sourceTree = "<group>"; };
941F59EF17A630990005D7EA /* Input.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Input.h; sourceTree = "<group>"; };
941F59F017A630990005D7EA /* Main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Main.cpp; sourceTree = "<group>"; };
941F59F117A630990005D7EA /* Menu.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Menu.cpp; sourceTree = "<group>"; };
941F59F217A630990005D7EA /* Menu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Menu.h; sourceTree = "<group>"; };
941F59F317A630990005D7EA /* ProSystem.aps */ = {isa = PBXFileReference; lastKnownFileType = file; path = ProSystem.aps; sourceTree = "<group>"; };
941F59F417A630990005D7EA /* ProSystem.ico */ = {isa = PBXFileReference; lastKnownFileType = image.ico; path = ProSystem.ico; sourceTree = "<group>"; };
941F59F517A630990005D7EA /* ProSystem.rc */ = {isa = PBXFileReference; lastKnownFileType = text; path = ProSystem.rc; sourceTree = "<group>"; };
941F59F617A630990005D7EA /* resource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = resource.h; sourceTree = "<group>"; };
941F59F717A630990005D7EA /* Sound.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Sound.cpp; sourceTree = "<group>"; };
941F59F817A630990005D7EA /* Sound.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Sound.h; sourceTree = "<group>"; };
941F59F917A630990005D7EA /* Timer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Timer.cpp; sourceTree = "<group>"; };
941F59FA17A630990005D7EA /* Timer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Timer.h; sourceTree = "<group>"; };
941F59DB17A62ADD0005D7EA /* OpenEmuBase.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = OpenEmuBase.framework; sourceTree = BUILT_PRODUCTS_DIR; };
941F59FB17A77CC90005D7EA /* ProSystem.dat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ProSystem.dat; sourceTree = SOURCE_ROOT; };
941F5A2617A78FF20005D7EA /* OE7800SystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OE7800SystemResponderClient.h; path = "../OpenEmu/Atari 7800/OE7800SystemResponderClient.h"; sourceTree = "<group>"; };
941F5A2617A78FF20005D7EA /* OE7800SystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OE7800SystemResponderClient.h; path = "../OpenEmu/SystemPlugins/Atari 7800/OE7800SystemResponderClient.h"; sourceTree = "<group>"; };
B5008DAD0E8BFB3E005AECAF /* ProSystemGameCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProSystemGameCore.h; sourceTree = "<group>"; };
D2F7E65807B2D6F200F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
D2F7E65807B2D6F200F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -216,6 +193,7 @@
);
name = VisualBoyAdvance;
sourceTree = "<group>";
usesTabs = 0;
};
089C1671FE841209C02AAC07 /* Frameworks and Libraries */ = {
isa = PBXGroup;
@@ -294,6 +272,8 @@
941F598917A6189D0005D7EA /* Database.cpp */,
941F598A17A6189D0005D7EA /* Database.h */,
941F598B17A6189D0005D7EA /* Equates.h */,
871EC9A124F08BF600CEC578 /* ExpansionModule.cpp */,
871EC9A024F08BF600CEC578 /* ExpansionModule.h */,
941F598C17A6189D0005D7EA /* Hash.cpp */,
941F598D17A6189D0005D7EA /* Hash.h */,
941F598E17A6189D0005D7EA /* lib */,
@@ -358,47 +338,12 @@
path = Lib;
sourceTree = SOURCE_ROOT;
};
941F59DF17A630990005D7EA /* Win */ = {
isa = PBXGroup;
children = (
941F59E017A630990005D7EA /* About.cpp */,
941F59E117A630990005D7EA /* About.h */,
941F59E217A630990005D7EA /* Common.cpp */,
941F59E317A630990005D7EA /* Common.h */,
941F59E417A630990005D7EA /* Configuration.cpp */,
941F59E517A630990005D7EA /* Configuration.h */,
941F59E617A630990005D7EA /* Console.cpp */,
941F59E717A630990005D7EA /* Console.h */,
941F59E817A630990005D7EA /* Database.cpp */,
941F59E917A630990005D7EA /* Database.h */,
941F59EA17A630990005D7EA /* Display.cpp */,
941F59EB17A630990005D7EA /* Display.h */,
941F59EC17A630990005D7EA /* Help.cpp */,
941F59ED17A630990005D7EA /* Help.h */,
941F59EE17A630990005D7EA /* Input.cpp */,
941F59EF17A630990005D7EA /* Input.h */,
941F59F017A630990005D7EA /* Main.cpp */,
941F59F117A630990005D7EA /* Menu.cpp */,
941F59F217A630990005D7EA /* Menu.h */,
941F59F317A630990005D7EA /* ProSystem.aps */,
941F59F417A630990005D7EA /* ProSystem.ico */,
941F59F517A630990005D7EA /* ProSystem.rc */,
941F59F617A630990005D7EA /* resource.h */,
941F59F717A630990005D7EA /* Sound.cpp */,
941F59F817A630990005D7EA /* Sound.h */,
941F59F917A630990005D7EA /* Timer.cpp */,
941F59FA17A630990005D7EA /* Timer.h */,
);
path = Win;
sourceTree = SOURCE_ROOT;
};
94A9E27F157D637B0083A7DC /* Core */ = {
isa = PBXGroup;
children = (
941F59FB17A77CC90005D7EA /* ProSystem.dat */,
941F598017A6189D0005D7EA /* core */,
941F59B517A6189D0005D7EA /* Lib */,
941F59DF17A630990005D7EA /* Win */,
);
path = Core;
sourceTree = "<group>";
@@ -430,12 +375,11 @@
089C1669FE841209C02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 0500;
LastUpgradeCheck = 0700;
};
buildConfigurationList = 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "ProSystem" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
developmentRegion = en;
hasScannedForEncodings = 1;
knownRegions = (
en,
@@ -497,6 +441,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8794D9691B74713300897F57 /* Sound.cpp in Sources */,
941DFB2715B6425200C6552F /* ProSystemGameCore.mm in Sources */,
941F59BF17A6189D0005D7EA /* Archive.cpp in Sources */,
941F59C017A6189D0005D7EA /* Bios.cpp in Sources */,
@@ -513,6 +458,7 @@
941F59CD17A6189D0005D7EA /* Pokey.cpp in Sources */,
941F59CE17A6189D0005D7EA /* ProSystem.cpp in Sources */,
941F59CF17A6189D0005D7EA /* Region.cpp in Sources */,
871EC9A224F08BF700CEC578 /* ExpansionModule.cpp in Sources */,
941F59D017A6189D0005D7EA /* Riot.cpp in Sources */,
941F59D117A6189D0005D7EA /* Sally.cpp in Sources */,
941F59D317A6189D0005D7EA /* Tia.cpp in Sources */,
@@ -539,7 +485,7 @@
089C167DFE841241C02AAC07 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
089C167EFE841241C02AAC07 /* English */,
089C167EFE841241C02AAC07 /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
@@ -560,6 +506,7 @@
);
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "\"$(USER_LIBRARY_DIR)/Application Support/OpenEmu/Cores\"";
PRODUCT_BUNDLE_IDENTIFIER = "org.openemu.${PRODUCT_NAME:identifier}";
PRODUCT_NAME = ProSystem;
SKIP_INSTALL = YES;
VALID_ARCHS = x86_64;
@@ -580,6 +527,7 @@
);
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "\"$(USER_LIBRARY_DIR)/Application Support/OpenEmu/Cores\"";
PRODUCT_BUNDLE_IDENTIFIER = "org.openemu.${PRODUCT_NAME:identifier}";
PRODUCT_NAME = ProSystem;
SKIP_INSTALL = YES;
VALID_ARCHS = x86_64;
@@ -591,29 +539,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 +573,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;
};
+222 -184
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,119 @@
@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.fileSystemRepresentation))
{
NSString *databasePath = [[[NSBundle bundleForClass:[self class]] resourcePath] stringByAppendingPathComponent:@"ProSystem.dat"];
database_filename = [databasePath UTF8String];
database_filename = databasePath.fileSystemRepresentation;
database_enabled = true;
// BIOS is optional
NSString *biosROM = [[self biosDirectoryPath] stringByAppendingPathComponent:@"7800 BIOS (U).rom"];
if (bios_Load([biosROM UTF8String]))
NSString *biosROM = [self.biosDirectoryPath stringByAppendingPathComponent:@"7800 BIOS (U).rom"];
if (bios_Load(biosROM.fileSystemRepresentation))
bios_enabled = true;
NSLog(@"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");
NSLog(@"[ProSystem] Headerless MD5 hash: %s", cartridge_digest.c_str());
NSLog(@"[ProSystem] Header info (often wrong):\ntitle: %s\ntype: %d\nregion: %s\npokey: %s", cartridge_title.c_str(), cartridge_type, cartridge_region == REGION_NTSC ? "NTSC" : "PAL", cartridge_pokey ? "true" : "false");
database_Load(cartridge_digest);
prosystem_Reset( );
std::string title = common_Trim(cartridge_title);
NSLog(@"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");
prosystem_Reset();
if (cart_in_db) {
std::string title = common_Trim(cartridge_title);
NSLog(@"[ProSystem] Database info:\ntitle: %@\ntype: %d\nregion: %s\npokey: %s", [NSString stringWithUTF8String:title.c_str()], cartridge_type, cartridge_region == REGION_NTSC ? "NTSC" : "PAL", cartridge_pokey ? "true" : "false");
}
//sound_SetSampleRate(48000);
//display_ResetPalette( );
display_ResetPalette32( );
//console_SetZoom(display_zoom);
//sound_Play( );
[self setPalette32];
_isLightgunEnabled = (cartridge_controller[0] & CARTRIDGE_CONTROLLER_LIGHTGUN);
// The light gun 'trigger' is a press on the 'up' button (0x3) and needs the bit toggled
if(_isLightgunEnabled)
_inputState[3] = 1;
// Set switch overrides from database
_inputState[LEFT_DIFF_SWITCH] = cartridge_left_switch;
_inputState[RIGHT_DIFF_SWITCH] = cartridge_right_switch;
return YES;
}
return NO;
}
- (void)executeFrame
{
[self executeFrameSkippingFrame:NO];
}
prosystem_ExecuteFrame(_inputState);
- (void)executeFrameSkippingFrame:(BOOL)skip
{
prosystem_ExecuteFrame(keyboard_data); //wants input
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 +162,26 @@ static void display_ResetPalette32( ) {
prosystem_Reset();
}
#pragma mark Video
- (NSTimeInterval)frameInterval
{
return cartridge_region == REGION_NTSC ? 60 : 50;
}
#pragma mark - Video
- (const void *)getVideoBufferWithHint:(void *)hint
{
return _videoBuffer = (uint32_t*)(hint ?: _videoBuffer);
}
- (OEIntRect)screenRect
{
return OEIntRectMake(0, 0, 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 +189,6 @@ static void display_ResetPalette32( ) {
return OEIntSizeMake(320, 292);
}
- (const void *)videoBuffer
{
return videoBuffer;
}
- (GLenum)pixelFormat
{
return GL_BGRA;
@@ -189,34 +199,86 @@ static void display_ResetPalette32( ) {
return GL_UNSIGNED_INT_8_8_8_8_REV;
}
- (GLenum)internalPixelFormat
{
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;
if(cartridge_xm) {
length += 4 + XM_RAM_SIZE;
}
void *bytes = malloc(length);
if(prosystem_Save_buffer((uint8_t *)bytes))
return [NSData dataWithBytesNoCopy:bytes length:length freeWhenDone:YES];
if(outError) {
*outError = [NSError errorWithDomain:OEGameCoreErrorDomain code:OEGameCoreCouldNotSaveStateError userInfo:@{
NSLocalizedDescriptionKey : @"Save state data could not be written",
NSLocalizedRecoverySuggestionErrorKey : @"The emulator could not write the state data."
}];
}
return nil;
}
- (BOOL)deserializeState:(NSData *)state withError:(NSError **)outError
{
size_t serial_size = cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM ? 32837 : 16453;
if(cartridge_xm) {
serial_size += 4 + XM_RAM_SIZE;
}
if(serial_size != state.length) {
if(outError) {
*outError = [NSError errorWithDomain:OEGameCoreErrorDomain code:OEGameCoreStateHasWrongSizeError userInfo:@{
NSLocalizedDescriptionKey : @"Save state has wrong file size.",
NSLocalizedRecoverySuggestionErrorKey : [NSString stringWithFormat:@"The save state does not have the right size, %ld expected, got: %ld.", serial_size, state.length]
}];
}
return NO;
}
if(prosystem_Load_buffer((uint8_t *)state.bytes))
return YES;
if(outError) {
*outError = [NSError errorWithDomain:OEGameCoreErrorDomain code:OEGameCoreCouldNotLoadStateError userInfo:@{
NSLocalizedDescriptionKey : @"The save state data could not be read"
}];
}
return NO;
}
#pragma mark - Input
// ----------------------------------------------------------------------------
// SetInput
// +----------+--------------+-------------------------------------------------
@@ -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"
+155 -52
View File
@@ -5,7 +5,7 @@
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
@@ -23,6 +23,9 @@
// Cartridge.cpp
// ----------------------------------------------------------------------------
#include "Cartridge.h"
#include "Region.h"
#include <string.h>
#define CARTRIDGE_SOURCE "Cartridge.cpp"
std::string cartridge_title;
@@ -34,9 +37,20 @@ std::string cartridge_filename;
byte cartridge_type;
byte cartridge_region;
bool cartridge_pokey;
byte cartridge_controller[2];
bool cartridge_pokey450;
byte cartridge_controller[2] = {1, 1};
byte cartridge_bank;
uint cartridge_flags;
int cartridge_crosshair_x;
int cartridge_crosshair_y;
bool cartridge_dualanalog = false;
bool cartridge_xm = false;
bool cartridge_disable_bios = false;
uint cartridge_hblank = 34;
byte cartridge_left_switch = 1;
byte cartridge_right_switch = 0;
bool cartridge_swap_buttons = false;
bool cartridge_hsc_enabled = false;
static byte* cartridge_buffer = NULL;
static uint cartridge_size = 0;
@@ -68,16 +82,23 @@ static bool cartridge_CC2(const byte* header) {
}
// ----------------------------------------------------------------------------
// GetBankOffset
// GetBank
// ----------------------------------------------------------------------------
static uint cartridge_GetBankOffset(byte bank) {
static uint cartridge_GetBank(byte bank) {
if ((cartridge_type == CARTRIDGE_TYPE_SUPERCART || cartridge_type == CARTRIDGE_TYPE_SUPERCART_ROM || cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) && cartridge_size <= 65536) {
// for some of these carts, there are only 4 banks. in this case we ignore bit 3
// previously, games of this type had to be doubled. The first 4 banks needed to be duplicated at the end of the ROM
return (bank & 3) * 16384;
return (bank & 3);
}
return bank * 16384;
return bank;
}
// ----------------------------------------------------------------------------
// GetBankOffset
// ----------------------------------------------------------------------------
static uint cartridge_GetBankOffset(byte bank) {
return cartridge_GetBank(bank) * 16384;
}
// ----------------------------------------------------------------------------
@@ -91,17 +112,30 @@ static void cartridge_WriteBank(word address, byte bank) {
}
}
static void cartridge_SetTypeBySize(uint size) {
if (size <= 0x10000) {
cartridge_type = CARTRIDGE_TYPE_NORMAL;
} else if (size == 0x24000 ) {
cartridge_type = CARTRIDGE_TYPE_SUPERCART_LARGE;
} else if (size == 0x20000 ) {
cartridge_type = CARTRIDGE_TYPE_SUPERCART_ROM;
} else {
cartridge_type = CARTRIDGE_TYPE_SUPERCART;
}
}
// ----------------------------------------------------------------------------
// ReadHeader
// ----------------------------------------------------------------------------
static void cartridge_ReadHeader(const byte* header) {
char temp[33] = {0};
for(int index = 0; index < 32; index++) {
temp[index] = header[index + 17];
temp[index] = header[index + 17];
}
cartridge_title = temp;
cartridge_size = header[49] << 32;
cartridge_size = header[49] << 24;
cartridge_size |= header[50] << 16;
cartridge_size |= header[51] << 8;
cartridge_size |= header[52];
@@ -124,22 +158,47 @@ static void cartridge_ReadHeader(const byte* header) {
}
}
else {
if(header[53] == 1) {
if(header[53] == 2 /*1*/) { // Wii: Abs and Act were swapped
cartridge_type = CARTRIDGE_TYPE_ABSOLUTE;
}
else if(header[53] == 2) {
else if(header[53] == 1 /*2*/) { // Wii: Abs and Act were swapped
cartridge_type = CARTRIDGE_TYPE_ACTIVISION;
}
else {
cartridge_type = CARTRIDGE_TYPE_NORMAL;
}
}
cartridge_pokey = (header[54] & 1)? true: false;
cartridge_pokey450 = (header[54] & 0x40)? true : false;
if (cartridge_pokey450) {
cartridge_pokey = true;
}
cartridge_controller[0] = header[55];
cartridge_controller[1] = header[56];
cartridge_region = header[57];
cartridge_flags = 0;
cartridge_xm = (header[63] & 1)? true: false;
cartridge_hsc_enabled = header[58]&0x01;
// Wii: Updates to header interpretation
byte ct1 = header[54];
if(header[53] == 0) {
if ((ct1&0x0a)==0x0a) { // BIT1 and BIT3 (Supercart Large: 2) rom at $4000
cartridge_type = CARTRIDGE_TYPE_SUPERCART_LARGE;
} else if ((ct1&0x12)==0x12) { // BIT1 and BIT4 (Supercart ROM: 4) bank6 at $4000
cartridge_type = CARTRIDGE_TYPE_SUPERCART_ROM;
} else if ((ct1&0x06)==0x06) { // BIT1 and BIT2 (Supercart RAM: 3) ram at $4000
cartridge_type = CARTRIDGE_TYPE_SUPERCART_RAM;
} else if ((ct1&0x02)==0x02) { // BIT1 (Supercart) bank switched
cartridge_type = CARTRIDGE_TYPE_SUPERCART;
} else if (cartridge_size <= 0x10000 && ((ct1&0x04)==0x04)) { // Size < 64k && BIT2 (Normal RAM: ?) ram at $4000 )
cartridge_type = CARTRIDGE_TYPE_NORMAL_RAM;
} else {
// Attempt to determine the cartridge type based on its size
cartridge_SetTypeBySize(cartridge_size);
}
}
}
// ----------------------------------------------------------------------------
@@ -152,7 +211,7 @@ static bool cartridge_Load(const byte* data, uint size) {
}
cartridge_Release( );
byte header[128] = {0};
for(int index = 0; index < 128; index++) {
header[index] = data[index];
@@ -168,19 +227,29 @@ if (cartridge_CC2(header)) {
cartridge_ReadHeader(header);
size -= 128;
offset = 128;
cartridge_size = size;
// Several cartridge headers do not have the proper size. So attempt to use the size
// of the file.
if (cartridge_size != size) {
// Necessary for the following roms:
// Impossible Mission hacks w/ C64 style graphics
if (size % 1024 == 0) {
cartridge_size = size;
}
}
}
else {
cartridge_size = size;
// Attempt to guess the cartridge type based on its size
cartridge_SetTypeBySize(size);
}
cartridge_buffer = new byte[cartridge_size];
for(int index = 0; index < cartridge_size; index++) {
cartridge_buffer[index] = data[index + offset];
}
cartridge_digest = hash_Compute(cartridge_buffer, cartridge_size);
return true;
}
@@ -192,10 +261,10 @@ bool cartridge_Load(std::string filename) {
logger_LogError("Cartridge filename is invalid.", CARTRIDGE_SOURCE);
return false;
}
cartridge_Release( );
logger_LogInfo("Opening cartridge file " + filename + ".", CARTRIDGE_SOURCE);
byte* data = NULL;
//uint size = archive_GetUncompressedFileSize(filename);
uint size = 0;
@@ -204,21 +273,21 @@ bool cartridge_Load(std::string filename) {
FILE *file = fopen(filename.c_str( ), "rb");
if(file == NULL) {
logger_LogError("Failed to open the cartridge file " + filename + " for reading.", CARTRIDGE_SOURCE);
return false;
return false;
}
if(fseek(file, 0, SEEK_END)) {
if(fseek(file, 0L, SEEK_END)) {
fclose(file);
logger_LogError("Failed to find the end of the cartridge file.", CARTRIDGE_SOURCE);
return false;
}
size = ftell(file);
if(fseek(file, 0, SEEK_SET)) {
if(fseek(file, 0L, SEEK_SET)) {
fclose(file);
logger_LogError("Failed to find the size of the cartridge file.", CARTRIDGE_SOURCE);
return false;
}
data = new byte[size];
if(fread(data, 1, size, file) != size && ferror(file)) {
fclose(file);
@@ -226,15 +295,15 @@ bool cartridge_Load(std::string filename) {
cartridge_Release( );
delete [ ] data;
return false;
}
}
fclose(file);
fclose(file);
}
else {
data = new byte[size];
//archive_Uncompress(filename, data, size);
}
if(!cartridge_Load(data, size)) {
logger_LogError("Failed to load the cartridge data into memory.", CARTRIDGE_SOURCE);
delete [ ] data;
@@ -243,7 +312,7 @@ bool cartridge_Load(std::string filename) {
if(data != NULL) {
delete [ ] data;
}
cartridge_filename = filename;
return true;
}
@@ -256,29 +325,37 @@ void cartridge_Store( ) {
case CARTRIDGE_TYPE_NORMAL:
memory_WriteROM(65536 - cartridge_size, cartridge_size, cartridge_buffer);
break;
case CARTRIDGE_TYPE_SUPERCART:
if(cartridge_GetBankOffset(7) < cartridge_size) {
memory_WriteROM(49152, 16384, cartridge_buffer + cartridge_GetBankOffset(7));
}
case CARTRIDGE_TYPE_NORMAL_RAM:
memory_WriteROM(65536 - cartridge_size, cartridge_size, cartridge_buffer);
memory_ClearROM(16384, 16384);
break;
case CARTRIDGE_TYPE_SUPERCART_LARGE:
if(cartridge_GetBankOffset(8) < cartridge_size) {
memory_WriteROM(49152, 16384, cartridge_buffer + cartridge_GetBankOffset(8));
case CARTRIDGE_TYPE_SUPERCART: {
uint offset = cartridge_size - 16384;
if(offset < cartridge_size) {
memory_WriteROM(49152, 16384, cartridge_buffer + offset);
}
} break;
case CARTRIDGE_TYPE_SUPERCART_LARGE: {
uint offset = cartridge_size - 16384;
if(offset < cartridge_size) {
memory_WriteROM(49152, 16384, cartridge_buffer + offset);
memory_WriteROM(16384, 16384, cartridge_buffer + cartridge_GetBankOffset(0));
}
break;
case CARTRIDGE_TYPE_SUPERCART_RAM:
if(cartridge_GetBankOffset(7) < cartridge_size) {
memory_WriteROM(49152, 16384, cartridge_buffer + cartridge_GetBankOffset(7));
} break;
case CARTRIDGE_TYPE_SUPERCART_RAM: {
uint offset = cartridge_size - 16384;
if(offset < cartridge_size) {
memory_WriteROM(49152, 16384, cartridge_buffer + offset);
memory_ClearROM(16384, 16384);
}
break;
case CARTRIDGE_TYPE_SUPERCART_ROM:
if(cartridge_GetBankOffset(7) < cartridge_size && cartridge_GetBankOffset(6) < cartridge_size) {
memory_WriteROM(49152, 16384, cartridge_buffer + cartridge_GetBankOffset(7));
} break;
case CARTRIDGE_TYPE_SUPERCART_ROM: {
uint offset = cartridge_size - 16384;
if(offset < cartridge_size && cartridge_GetBankOffset(6) < cartridge_size) {
memory_WriteROM(49152, 16384, cartridge_buffer + offset);
memory_WriteROM(16384, 16384, cartridge_buffer + cartridge_GetBankOffset(6));
}
break;
} break;
case CARTRIDGE_TYPE_ABSOLUTE:
memory_WriteROM(16384, 16384, cartridge_buffer);
memory_WriteROM(32768, 32768, cartridge_buffer + cartridge_GetBankOffset(2));
@@ -302,16 +379,18 @@ void cartridge_Write(word address, byte data) {
switch(cartridge_type) {
case CARTRIDGE_TYPE_SUPERCART:
case CARTRIDGE_TYPE_SUPERCART_RAM:
case CARTRIDGE_TYPE_SUPERCART_ROM:
if(address >= 32768 && address < 49152 && data < 9) {
case CARTRIDGE_TYPE_SUPERCART_ROM: {
uint maxbank = cartridge_size / 16384;
if(address >= 32768 && address < 49152 && cartridge_GetBank(data) < maxbank /*9*/) {
cartridge_StoreBank(data);
}
break;
case CARTRIDGE_TYPE_SUPERCART_LARGE:
if(address >= 32768 && address < 49152 && data < 9) {
} break;
case CARTRIDGE_TYPE_SUPERCART_LARGE: {
uint maxbank = cartridge_size / 16384;
if(address >= 32768 && address < 49152 && cartridge_GetBank(data) < maxbank /*9*/) {
cartridge_StoreBank(data + 1);
}
break;
} break;
case CARTRIDGE_TYPE_ABSOLUTE:
if(address == 32768 && (data == 1 || data == 2)) {
cartridge_StoreBank(data - 1);
@@ -324,7 +403,8 @@ void cartridge_Write(word address, byte data) {
break;
}
if(cartridge_pokey && address >= 0x4000 && address < 0x4009) {
#if 0 // WIi: Moved to Memory.cpp
if(cartridge_pokey && address >= 0x4000 && address <= 0x400f) {
switch(address) {
case POKEY_AUDF1:
pokey_SetRegister(POKEY_AUDF1, data);
@@ -353,8 +433,12 @@ void cartridge_Write(word address, byte data) {
case POKEY_AUDCTL:
pokey_SetRegister(POKEY_AUDCTL, data);
break;
case POKEY_SKCTLS:
pokey_SetRegister(POKEY_SKCTLS, data);
break;
}
}
#endif
}
// ----------------------------------------------------------------------------
@@ -372,7 +456,7 @@ void cartridge_StoreBank(byte bank) {
cartridge_WriteBank(32768, bank);
break;
case CARTRIDGE_TYPE_SUPERCART_LARGE:
cartridge_WriteBank(32768, bank);
cartridge_WriteBank(32768, bank);
break;
case CARTRIDGE_TYPE_ABSOLUTE:
cartridge_WriteBank(16384, bank);
@@ -380,7 +464,7 @@ void cartridge_StoreBank(byte bank) {
case CARTRIDGE_TYPE_ACTIVISION:
cartridge_WriteBank(40960, bank);
break;
}
}
}
// ----------------------------------------------------------------------------
@@ -398,5 +482,24 @@ void cartridge_Release( ) {
delete [ ] cartridge_buffer;
cartridge_size = 0;
cartridge_buffer = NULL;
cartridge_title = "";
cartridge_type = 0;
cartridge_region = 0;
cartridge_pokey = 0;
cartridge_pokey450 = 0;
cartridge_xm = false;
// Default to joysticks
memset( cartridge_controller, 1, sizeof( cartridge_controller ) );
cartridge_bank = 0;
cartridge_flags = 0;
cartridge_disable_bios = false;
cartridge_crosshair_x = 0;
cartridge_crosshair_y = 0;
cartridge_hblank = HBLANK_DEFAULT;
cartridge_dualanalog = false;
cartridge_left_switch = 1;
cartridge_right_switch = 0;
cartridge_swap_buttons = false;
cartridge_hsc_enabled = false;
}
}
+21 -2
View File
@@ -31,12 +31,14 @@
#define CARTRIDGE_TYPE_SUPERCART_ROM 4
#define CARTRIDGE_TYPE_ABSOLUTE 5
#define CARTRIDGE_TYPE_ACTIVISION 6
#define CARTRIDGE_TYPE_NORMAL_RAM 7
#define CARTRIDGE_CONTROLLER_NONE 0
#define CARTRIDGE_CONTROLLER_JOYSTICK 1
#define CARTRIDGE_CONTROLLER_LIGHTGUN 2
#define CARTRIDGE_WSYNC_MASK 2
#define CARTRIDGE_CYCLE_STEALING_MASK 1
//#define NULL 0
#define HBLANK_DEFAULT 34
#include <stdio.h>
#include <string>
@@ -66,8 +68,25 @@ extern std::string cartridge_filename;
extern byte cartridge_type;
extern byte cartridge_region;
extern bool cartridge_pokey;
extern bool cartridge_pokey450;
extern bool cartridge_xm;
extern byte cartridge_controller[2];
extern byte cartridge_bank;
extern uint cartridge_flags;
extern bool cartridge_disable_bios;
extern byte cartridge_left_switch;
extern byte cartridge_right_switch;
extern bool cartridge_swap_buttons;
#endif
// The x offset for the lightgun crosshair (allows per cartridge adjustments)
extern int cartridge_crosshair_x;
// The y offset for the lightgun crosshair (allows per cartridge adjustments)
extern int cartridge_crosshair_y;
// The hblank prior to DMA
extern uint cartridge_hblank;
// Whether the cartridge supports dual analog
extern bool cartridge_dualanalog;
// Whether the high score cart is enabled
extern bool cartridge_hsc_enabled;
#endif
+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);
+58 -2
View File
@@ -25,6 +25,7 @@
#include "Database.h"
#define DATABASE_SOURCE "Database.cpp"
bool cart_in_db = false;
bool database_enabled = true;
std::string database_filename;
@@ -44,6 +45,7 @@ void database_Initialize( ) {
// Load
// ----------------------------------------------------------------------------
bool database_Load(std::string digest) {
cart_in_db = false;
if(database_enabled) {
logger_LogInfo("Accessing database " + database_filename + ".", DATABASE_SOURCE);
@@ -53,13 +55,22 @@ bool database_Load(std::string digest) {
return false;
}
// max count of items in the database
static int count = 17;
char buffer[256];
while(fgets(buffer, 256, file) != NULL) {
std::string line = buffer;
if(line.compare(1, 32, digest.c_str( )) == 0) {
std::string entry[7];
for(int index = 0; index < 7; index++) {
cart_in_db = true;
std::string entry[count];
for (int index = 0; index < count; index++) {
buffer[0] = '\0';
fgets(buffer, 256, file);
if (strchr(buffer, '[')) {
// Passed the current game in DB
break;
}
entry[index] = common_Remove(buffer, '\n');
entry[index] = common_Remove(entry[index], '\r');
}
@@ -71,6 +82,51 @@ bool database_Load(std::string digest) {
cartridge_controller[1] = common_ParseByte(database_GetValue(entry[4]));
cartridge_region = common_ParseByte(database_GetValue(entry[5]));
cartridge_flags = common_ParseUint(database_GetValue(entry[6]));
// Optionally load the lightgun crosshair offsets, hblank, dual analog
for(int index = 7; index < count; index++)
{
if(entry[index].find("crossx") != std::string::npos)
{
cartridge_crosshair_x = common_ParseInt(database_GetValue(entry[index]));
}
if(entry[index].find("crossy") != std::string::npos)
{
cartridge_crosshair_y = common_ParseInt(database_GetValue(entry[index]));
}
if(entry[index].find("hblank") != std::string::npos)
{
cartridge_hblank = common_ParseInt(database_GetValue(entry[index]));
}
if(entry[index].find("dualanalog") != std::string::npos)
{
cartridge_dualanalog = common_ParseBool(database_GetValue(entry[index]));
}
if (entry[index].find("pokey450") != std::string::npos) {
cartridge_pokey450 = common_ParseBool(database_GetValue(entry[index]));
if (cartridge_pokey450) {
cartridge_pokey = true;
}
}
if (entry[index].find("xm") != std::string::npos) {
cartridge_xm = common_ParseBool(database_GetValue(entry[index]));
}
if (entry[index].find("disablebios") != std::string::npos) {
cartridge_disable_bios = common_ParseBool(database_GetValue(entry[index]));
}
if (entry[index].find("leftswitch") != std::string::npos) {
cartridge_left_switch = common_ParseByte(database_GetValue(entry[index]));
}
if (entry[index].find("rightswitch") != std::string::npos) {
cartridge_right_switch = common_ParseByte(database_GetValue(entry[index]));
}
if (entry[index].find("swapbuttons") != std::string::npos) {
cartridge_swap_buttons = common_ParseBool(database_GetValue(entry[index]));
}
if (entry[index].find("hsc") != std::string::npos) {
cartridge_hsc_enabled = common_ParseBool(database_GetValue(entry[index]));
}
}
break;
}
}
+2 -1
View File
@@ -38,5 +38,6 @@ extern void database_Initialize( );
extern bool database_Load(std::string digest);
extern bool database_enabled;
extern std::string database_filename;
extern bool cart_in_db;
#endif
#endif
+81
View File
@@ -0,0 +1,81 @@
/*
Memory map:
POKEY1 $0450 $045F 16 bytes
POKEY2* $0460 $046F 16 bytes
XCTRL $0470 $047F 1 byte
RAM $4000 $7FFF 16384 bytes
XCTRL Bit Description
+-------------------------------+
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-------------------------------+
| | | | | | | |
| | | | | | | +-- Bank select bit 0 \
| | | | | | +------ Bank select bit 1 | Totally 128 KByte in 16 KByte banks
| | | | | +---------- Bank select bit 3 /
| | | | +-------------- Enable memory bit (1 = Memory enabled, 0 after power on)
| | | +------------------ Enable POKEY bit** (1 = POKEY enabled, 0 after power on)
| | |
NA NA NA = Not Available or Not Used
* = Can be mounted piggy back on the first POKEY. Description how to do this will come when i have tried it out.
** This bit controls both POKEY chip select signals.
The mapping is totally non compatible with pretty much everything.
There is a bank select latch located at $0470 and the POKEY is located at $0450
(There's also a chip select output ($0460) on the PLD which alows you to simply piggy back a second POKEY).
Since the PLD is reconfigurable I could map the POKEY (or the RAM for that matter) to pretty much anything
if you wanted to. However since the PLD is soldered under the POKEY this needs to be configured before delivery.
*/
#include <string.h>
#include "ExpansionModule.h"
byte xm_ram[XM_RAM_SIZE] = {0};
byte xm_reg = 0;
byte xm_bank = 0;
bool xm_pokey_enabled = false;
bool xm_mem_enabled = false;
void xm_Reset() {
memset(xm_ram, 0, XM_RAM_SIZE);
xm_bank = 0;
xm_reg = 0;
xm_pokey_enabled = false;
xm_mem_enabled = false;
}
byte xm_Read(word address) {
if (xm_pokey_enabled && (address >= 0x0450 && address < 0x0460)) {
byte b = pokey_GetRegister(0x4000 + (address - 0x0450));
return b;
} else if (xm_pokey_enabled && (address >= 0x0460 && address < 0x0470)) {
byte b = pokey_GetRegister(0x4000 + (address - 0x0460));
return b;
} else if (xm_mem_enabled && (address >= 0x4000 && address < 0x8000)) {
byte b = xm_ram[(xm_bank * 0x4000) + (address - 0x4000)];
return b;
} else if (address >= 0x0470 && address < 0x0480) {
// TODO: Should the value be returned?
}
return 0;
}
void xm_Write(word address, byte data) {
if (xm_pokey_enabled && (address >= 0x0450 && address < 0x0460)) {
pokey_SetRegister(0x4000 + (address - 0x0450), data);
} else if (xm_pokey_enabled && (address >= 0x0460 && address < 0x0470)) {
pokey_SetRegister(0x4000 + (address - 0x0460), data);
} else if (xm_mem_enabled && (address >= 0x4000 && address < 0x8000)) {
xm_ram[(xm_bank * 0x4000) + (address - 0x4000)] = data;
} else if (address >= 0x0470 && address < 0x0480) {
xm_reg = data;
xm_bank = xm_reg & 7;
xm_pokey_enabled = (xm_reg & 0x10) > 0;
xm_mem_enabled = (xm_reg & 0x08) > 0;
}
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef EXPANSIONMODULE_H
#define EXPANSIONMODULE_H
#include "Cartridge.h"
#include "Memory.h"
#define XM_RAM_SIZE 0x20000
extern byte xm_ram[XM_RAM_SIZE];
extern bool xm_pokey_enabled;
extern bool xm_mem_enabled;
extern byte xm_reg;
extern byte xm_bank;
void xm_Reset();
byte xm_Read(word address);
void xm_Write(word address, byte data);
#endif
-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>
+69 -29
View File
@@ -5,7 +5,7 @@
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
@@ -37,7 +37,7 @@ static pair maria_dp;
static pair maria_pp;
static byte maria_horizontal;
static byte maria_palette;
static char maria_offset;
static signed char maria_offset;
static byte maria_h08;
static byte maria_h16;
static byte maria_wmode;
@@ -45,12 +45,12 @@ static byte maria_wmode;
// ----------------------------------------------------------------------------
// StoreCell
// ----------------------------------------------------------------------------
static void maria_StoreCell(byte data) {
static inline void maria_StoreCell(byte data) {
if(maria_horizontal < MARIA_LINERAM_SIZE) {
if(data) {
maria_lineRAM[maria_horizontal] = maria_palette | data;
}
else {
else {
byte kmode = memory_ram[CTRL] & 4;
if(kmode) {
maria_lineRAM[maria_horizontal] = 0;
@@ -63,12 +63,12 @@ static void maria_StoreCell(byte data) {
// ----------------------------------------------------------------------------
// StoreCell
// ----------------------------------------------------------------------------
static void maria_StoreCell(byte high, byte low) {
static inline void maria_StoreCell(byte high, byte low) {
if(maria_horizontal < MARIA_LINERAM_SIZE) {
if(low || high) {
maria_lineRAM[maria_horizontal] = (maria_palette & 16) | high | low;
}
else {
else {
byte kmode = memory_ram[CTRL] & 4;
if(kmode) {
maria_lineRAM[maria_horizontal] = 0;
@@ -81,7 +81,7 @@ static void maria_StoreCell(byte high, byte low) {
// ----------------------------------------------------------------------------
// IsHolyDMA
// ----------------------------------------------------------------------------
static bool maria_IsHolyDMA( ) {
static inline bool maria_IsHolyDMA( ) {
if(maria_pp.w > 32767) {
if(maria_h16 && (maria_pp.w & 4096)) {
return true;
@@ -96,7 +96,7 @@ static bool maria_IsHolyDMA( ) {
// ----------------------------------------------------------------------------
// GetColor
// ----------------------------------------------------------------------------
static byte maria_GetColor(byte data) {
static inline byte maria_GetColor(byte data) {
if(data & 3) {
return memory_ram[BACKGRND + data];
}
@@ -108,12 +108,15 @@ static byte maria_GetColor(byte data) {
// ----------------------------------------------------------------------------
// StoreGraphic
// ----------------------------------------------------------------------------
static void maria_StoreGraphic( ) {
static inline void maria_StoreGraphic( ) {
byte data = memory_ram[maria_pp.w];
if(maria_wmode) {
if(maria_IsHolyDMA( )) {
#if 0 // Wii: disabled due to rendering in Kangaroo mode
maria_StoreCell(0, 0);
maria_StoreCell(0, 0);
#endif
maria_horizontal+=2;
}
else {
maria_StoreCell((data & 12), (data & 192) >> 6);
@@ -122,10 +125,13 @@ static void maria_StoreGraphic( ) {
}
else {
if(maria_IsHolyDMA( )) {
#if 0 // Wii: disabled due to rendering in Kangaroo mode
maria_StoreCell(0);
maria_StoreCell(0);
maria_StoreCell(0);
maria_StoreCell(0);
#endif
maria_horizontal+=4;
}
else {
maria_StoreCell((data & 192) >> 6);
@@ -140,12 +146,13 @@ static void maria_StoreGraphic( ) {
// ----------------------------------------------------------------------------
// WriteLineRAM
// ----------------------------------------------------------------------------
static void maria_WriteLineRAM(byte* buffer) {
static inline void maria_WriteLineRAM(byte* buffer) {
byte rmode = memory_ram[CTRL] & 3;
if(rmode == 0) {
// 160A/B
int pixel = 0;
for(int index = 0; index < MARIA_LINERAM_SIZE; index += 4) {
byte color;
word color;
color = maria_GetColor(maria_lineRAM[index + 0]);
buffer[pixel++] = color;
buffer[pixel++] = color;
@@ -160,7 +167,8 @@ static void maria_WriteLineRAM(byte* buffer) {
buffer[pixel++] = color;
}
}
else if(rmode == 2) {
else if(rmode == 2) {
// 320B/D
int pixel = 0;
for(int index = 0; index < MARIA_LINERAM_SIZE; index += 4) {
buffer[pixel++] = maria_GetColor((maria_lineRAM[index + 0] & 16) | ((maria_lineRAM[index + 0] & 8) >> 3) | ((maria_lineRAM[index + 0] & 2)));
@@ -174,6 +182,7 @@ static void maria_WriteLineRAM(byte* buffer) {
}
}
else if(rmode == 3) {
// 320A/C
int pixel = 0;
for(int index = 0; index < MARIA_LINERAM_SIZE; index += 4) {
buffer[pixel++] = maria_GetColor((maria_lineRAM[index + 0] & 30));
@@ -191,29 +200,29 @@ static void maria_WriteLineRAM(byte* buffer) {
// ----------------------------------------------------------------------------
// StoreLineRAM
// ----------------------------------------------------------------------------
static void maria_StoreLineRAM( ) {
static inline void maria_StoreLineRAM( ) {
for(int index = 0; index < MARIA_LINERAM_SIZE; index++) {
maria_lineRAM[index] = 0;
}
byte mode = memory_ram[maria_dp.w + 1];
while(mode & 0x5f) {
byte width;
byte indirect = 0;
maria_pp.b.l = memory_ram[maria_dp.w];
maria_pp.b.h = memory_ram[maria_dp.w + 2];
if(mode & 31) {
maria_cycles += 8;
if(mode & 31) {
maria_cycles += 8; // Maria cycles (Header 4 byte)
maria_palette = (memory_ram[maria_dp.w + 1] & 224) >> 3;
maria_horizontal = memory_ram[maria_dp.w + 3];
width = memory_ram[maria_dp.w + 1] & 31;
width = ((~width) & 31) + 1;
maria_dp.w += 4;
}
else {
maria_cycles += 10;
else {
maria_cycles += 12; // Maria cycles (Header 5 byte)
maria_palette = (memory_ram[maria_dp.w + 3] & 224) >> 3;
maria_horizontal = memory_ram[maria_dp.w + 4];
indirect = memory_ram[maria_dp.w + 1] & 32;
@@ -226,7 +235,7 @@ static void maria_StoreLineRAM( ) {
if(!indirect) {
maria_pp.b.h += maria_offset;
for(int index = 0; index < width; index++) {
maria_cycles += 3;
maria_cycles += 3; // Maria cycles (Direct graphic read)
maria_StoreGraphic( );
}
}
@@ -234,14 +243,13 @@ static void maria_StoreLineRAM( ) {
byte cwidth = memory_ram[CTRL] & 16;
pair basePP = maria_pp;
for(int index = 0; index < width; index++) {
maria_cycles += 3;
maria_cycles += 3; // Maria cycles (Indirect)
maria_pp.b.l = memory_ram[basePP.w++];
maria_pp.b.h = memory_ram[CHARBASE] + maria_offset;
maria_cycles += 6;
maria_cycles += 3; // Maria cycles (Indirect, 1 byte)
maria_StoreGraphic( );
if(cwidth) {
maria_cycles += 3;
maria_cycles += 3; // Maria cycles (Indirect, 2 bytes)
maria_StoreGraphic( );
}
}
@@ -258,6 +266,17 @@ void maria_Reset( ) {
for(int index = 0; index < MARIA_SURFACE_SIZE; index++) {
maria_surface[index] = 0;
}
maria_cycles = 0;
maria_dpp.w = 0;
maria_dp.w = 0;
maria_pp.w = 0;
maria_horizontal = 0;
maria_palette = 0;
maria_offset = 0;
maria_h08 = 0;
maria_h16 = 0;
maria_wmode = 0;
}
// ----------------------------------------------------------------------------
@@ -265,10 +284,24 @@ void maria_Reset( ) {
// ----------------------------------------------------------------------------
uint maria_RenderScanline( ) {
maria_cycles = 0;
// lightgun flash
// Displays the background color when Maria is disabled (if applicable)
if( ( ( memory_ram[CTRL] & 96 ) != 64 ) &&
maria_scanline >= maria_visibleArea.top &&
maria_scanline <= maria_visibleArea.bottom ) {
byte bgcolor = maria_GetColor(0);
byte *bgstart = maria_surface + ((maria_scanline - maria_displayArea.top) * maria_displayArea.GetLength());
for(uint index = 0; index < MARIA_LINERAM_SIZE; index++ ) {
*bgstart++ = bgcolor;
*bgstart++ = bgcolor;
}
}
if((memory_ram[CTRL] & 96) == 64 && maria_scanline >= maria_displayArea.top && maria_scanline <= maria_displayArea.bottom) {
maria_cycles += 31;
maria_cycles += 5; // Maria cycles (DMA Startup)
if(maria_scanline == maria_displayArea.top) {
maria_cycles += 7;
maria_cycles += 10; // Maria cycles (End of VBLANK)
maria_dpp.b.l = memory_ram[DPPL];
maria_dpp.b.h = memory_ram[DPPH];
maria_h08 = memory_ram[maria_dpp.w] & 32;
@@ -277,6 +310,7 @@ uint maria_RenderScanline( ) {
maria_dp.b.l = memory_ram[maria_dpp.w + 2];
maria_dp.b.h = memory_ram[maria_dpp.w + 1];
if(memory_ram[maria_dpp.w] & 128) {
maria_cycles += 20; // Maria cycles (NMI) /*29, 16, 20*/
sally_ExecuteNMI( );
}
}
@@ -289,15 +323,21 @@ uint maria_RenderScanline( ) {
maria_StoreLineRAM( );
maria_offset--;
if(maria_offset < 0) {
maria_cycles += 10; // Maria cycles (Last line of zone) /*20*/
maria_dpp.w += 3;
maria_h08 = memory_ram[maria_dpp.w] & 32;
maria_h16 = memory_ram[maria_dpp.w] & 64;
maria_offset = memory_ram[maria_dpp.w] & 15;
if(memory_ram[maria_dpp.w] & 128) {
maria_cycles += 20; // Maria cycles (NMI) /*29, 16, 20*/
sally_ExecuteNMI( );
}
}
}
else
{
maria_cycles += 4; // Maria cycles (Other lines of zone)
}
}
}
return maria_cycles;
}
@@ -309,4 +349,4 @@ void maria_Clear( ) {
for(int index = 0; index < MARIA_SURFACE_SIZE; index++) {
maria_surface[index] = 0;
}
}
}
+41 -10
View File
@@ -5,7 +5,7 @@
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
@@ -23,6 +23,7 @@
// Memory.cpp
// ----------------------------------------------------------------------------
#include "Memory.h"
#include "ExpansionModule.h"
byte memory_ram[MEMORY_SIZE] = {0};
byte memory_rom[MEMORY_SIZE] = {0};
@@ -46,17 +47,32 @@ void memory_Reset( ) {
byte memory_Read(word address) {
byte tmp_byte;
if (cartridge_xm) {
if ((address >= 0x0470 && address < 0x0480) ||
(xm_pokey_enabled && (address >= 0x0450 && address < 0x0470)) ||
(xm_mem_enabled && (address >= 0x4000 && address < 0x8000))) {
return xm_Read(address);
}
}
if (cartridge_pokey && (
(!cartridge_pokey450 && (address >= 0x4000 && address <= 0x400f)) ||
(cartridge_pokey450 && (address >= 0x0450 && address < 0x0470)))) {
return pokey_GetRegister(
cartridge_pokey450 ? 0x4000 + (address - 0x0450) : address);
}
switch ( address ) {
case INTIM:
case INTIM | 0x2:
memory_ram[INTFLG] &= 0x7f;
memory_ram[INTFLG] &= 0x7f;
return memory_ram[INTIM];
break;
break;
case INTFLG:
case INTFLG | 0x2:
tmp_byte = memory_ram[INTFLG];
memory_ram[INTFLG] &= 0x7f;
return tmp_byte;
tmp_byte = memory_ram[INTFLG];
memory_ram[INTFLG] &= 0x7f;
return tmp_byte;
break;
default:
return memory_ram[address];
@@ -68,6 +84,21 @@ byte memory_Read(word address) {
// Write
// ----------------------------------------------------------------------------
void memory_Write(word address, byte data) {
if (cartridge_xm &&
((address >= 0x0470 && address < 0x0480) ||
((xm_pokey_enabled && (address >= 0x0450 && address < 0x0470)) ||
(xm_mem_enabled && (address >= 0x4000 && address < 0x8000))))) {
xm_Write(address, data);
return;
}
if (cartridge_pokey && (
(!cartridge_pokey450 && (address >= 0x4000 && address <= 0x400f)) ||
(cartridge_pokey450 && (address >= 0x0450 && address < 0x0470)))) {
pokey_SetRegister(
(cartridge_pokey450 ? 0x4000 + (address - 0x0450) : address), data);
return;
}
if(!memory_rom[address]) {
switch(address) {
@@ -77,8 +108,8 @@ void memory_Write(word address, byte data) {
}
break;
case INPTCTRL:
if(data == 22 && cartridge_IsLoaded( )) {
cartridge_Store( );
if(data == 22 && cartridge_IsLoaded( )) {
cartridge_Store( );
}
else if(data == 2 && bios_enabled) {
bios_Store( );
@@ -163,7 +194,7 @@ void memory_Write(word address, byte data) {
// ----------------------------------------------------------------------------
// WriteROM
// ----------------------------------------------------------------------------
void memory_WriteROM(word address, word size, const byte* data) {
void memory_WriteROM(word address, uint size, const byte* data) {
if((address + size) <= MEMORY_SIZE && data != NULL) {
for(uint index = 0; index < size; index++) {
memory_ram[address + index] = data[index];
@@ -175,7 +206,7 @@ void memory_WriteROM(word address, word size, const byte* data) {
// ----------------------------------------------------------------------------
// ClearROM
// ----------------------------------------------------------------------------
void memory_ClearROM(word address, word size) {
void memory_ClearROM(word address, uint size) {
if((address + size) <= MEMORY_SIZE) {
for(uint index = 0; index < size; index++) {
memory_ram[address + index] = 0;
+3 -4
View File
@@ -5,7 +5,7 @@
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
@@ -25,7 +25,6 @@
#ifndef MEMORY_H
#define MEMORY_H
#define MEMORY_SIZE 65536
//#define NULL 0
#include "Equates.h"
#include "Bios.h"
@@ -40,8 +39,8 @@ typedef unsigned int uint;
extern void memory_Reset( );
extern byte memory_Read(word address);
extern void memory_Write(word address, byte data);
extern void memory_WriteROM(word address, word size, const byte* data);
extern void memory_ClearROM(word address, word size);
extern void memory_WriteROM(word address, uint size, const byte* data);
extern void memory_ClearROM(word address, uint size);
extern byte memory_ram[MEMORY_SIZE];
extern byte memory_rom[MEMORY_SIZE];
+5 -5
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"
+182 -35
View File
@@ -5,7 +5,7 @@
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
@@ -21,31 +21,33 @@
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// PokeySound is Copyright(c) 1997 by Ron Fries
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of version 2 of the GNU Library General Public License
// as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
// General Public License for more details.
// To obtain a copy of the GNU Library General Public License, write to the
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// Any permitted reproduction of these routines, in whole or in part, must
// bear this legend.
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of version 2 of the GNU Library General Public License
// as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
// General Public License for more details.
// To obtain a copy of the GNU Library General Public License, write to the
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// Any permitted reproduction of these routines, in whole or in part, must
// bear this legend.
// ----------------------------------------------------------------------------
// Pokey.cpp
// ----------------------------------------------------------------------------
#include <stdlib.h>
#include "Pokey.h"
#include "ProSystem.h"
#define POKEY_NOTPOLY5 0x80
#define POKEY_POLY4 0x40
#define POKEY_PURE 0x20
#define POKEY_VOLUME_ONLY 0x10
#define POKEY_VOLUME_MASK 0x0f
#define POKEY_POLY9 0x80
#define POKEY_POLY9 0x80
#define POKEY_CH1_179 0x40
#define POKEY_CH3_179 0x20
#define POKEY_CH1_CH2 0x10
@@ -65,8 +67,10 @@
#define POKEY_CHANNEL4 3
#define POKEY_SAMPLE 4
#define SK_RESET 0x03
byte pokey_buffer[POKEY_BUFFER_SIZE] = {0};
uint pokey_size = 524;
uint pokey_size = (POKEY_BUFFER_SIZE - 512); // 524 previously
static uint pokey_frequency = 1787520;
static uint pokey_sampleRate = 31440;
@@ -90,10 +94,47 @@ static uint pokey_sampleMax;
static uint pokey_sampleCount[2];
static uint pokey_baseMultiplier;
static byte rand9[0x1ff];
static byte rand17[0x1ffff];
static uint r9;
static uint r17;
static byte SKCTL;
byte RANDOM;
byte POT_input[8] = {228, 228, 228, 228, 228, 228, 228, 228};
static int pot_scanline;
static ulong random_scanline_counter;
static ulong prev_random_scanline_counter;
static void rand_init(byte *rng, int size, int left, int right, int add)
{
int mask = (1 << size) - 1;
int i, x = 0;
for( i = 0; i < mask; i++ )
{
if (size == 17)
*rng = x >> 6; /* use bits 6..13 */
else
*rng = x; /* use bits 0..7 */
rng++;
/* calculate next bit */
x = ((x << left) + (x >> right) + add) & mask;
}
}
void pokey_setSampleRate( uint rate ) {
pokey_sampleRate = rate;
}
// ----------------------------------------------------------------------------
// Reset
// ----------------------------------------------------------------------------
void pokey_Reset( ) {
pot_scanline = 0;
pokey_soundCntr = 0;
for(int index = 0; index < POKEY_POLY17_SIZE; index++) {
pokey_poly17[index] = rand( ) & 1;
}
@@ -118,16 +159,108 @@ void pokey_Reset( ) {
pokey_audf[channel] = 0;
}
for(int i = 0; i < 8; i++) {
POT_input[i] = 228;
}
pokey_audctl = 0;
pokey_baseMultiplier = POKEY_DIV_64;
}
/* initialize the random arrays */
rand_init(rand9, 9, 8, 1, 0x00180);
rand_init(rand17, 17,16, 1, 0x1c000);
SKCTL = SK_RESET;
RANDOM = 0;
r9 = 0;
r17 = 0;
random_scanline_counter = 0;
prev_random_scanline_counter = 0;
}
/* Called prior to each frame */
void pokey_Frame() {
}
/* Called prior to each scanline */
void pokey_Scanline() {
random_scanline_counter += CYCLES_PER_SCANLINE;
if (pot_scanline < 228)
pot_scanline++;
}
byte pokey_GetRegister(word address) {
byte data = 0;
byte addr = address & 0x0f;
if (addr < 8) {
byte b = POT_input[addr];
if (b <= pot_scanline)
return b;
return pot_scanline;
}
switch (address) {
case POKEY_ALLPOT: {
byte b = 0;
for (int i = 0; i < 8; i++)
if (POT_input[addr] <= pot_scanline)
b &= ~(1 << i); /* reset bit if pot value known */
return b;
}
case POKEY_RANDOM:
ulong curr_scanline_counter =
( random_scanline_counter + prosystem_cycles + prosystem_extra_cycles );
if( SKCTL & SK_RESET )
{
ulong adjust = ( ( curr_scanline_counter - prev_random_scanline_counter ) >> 2 );
r9 = (uint)((adjust + r9) % 0x001ff);
r17 = (uint)((adjust + r17) % 0x1ffff);
}
else
{
r9 = 0;
r17 = 0;
}
if( pokey_audctl & POKEY_POLY9 )
{
RANDOM = rand9[r9];
}
else
{
RANDOM = rand17[r17];
}
prev_random_scanline_counter = curr_scanline_counter;
RANDOM = RANDOM ^ 0xff;
data = RANDOM;
break;
}
return data;
}
// ----------------------------------------------------------------------------
// SetRegister
// ----------------------------------------------------------------------------
void pokey_SetRegister(word address, byte value) {
byte channelMask;
byte channelMask;
switch(address) {
case POKEY_POTGO:
if (!(SKCTL & 4))
pot_scanline = 0; /* slow pot mode */
return;
case POKEY_SKCTLS:
SKCTL = value;
if (value & 4)
pot_scanline = 228; /* fast pot mode - return results immediately */
return;
case POKEY_AUDF1:
pokey_audf[POKEY_CHANNEL1] = value;
channelMask = 1 << POKEY_CHANNEL1;
@@ -135,7 +268,7 @@ void pokey_SetRegister(word address, byte value) {
channelMask |= 1 << POKEY_CHANNEL2;
}
break;
case POKEY_AUDC1:
pokey_audc[POKEY_CHANNEL1] = value;
channelMask = 1 << POKEY_CHANNEL1;
@@ -196,7 +329,7 @@ void pokey_SetRegister(word address, byte value) {
channelMask = 0;
break;
}
uint newValue = 0;
if(channelMask & (1 << POKEY_CHANNEL1)) {
@@ -244,7 +377,7 @@ void pokey_SetRegister(word address, byte value) {
}
if(newValue!= pokey_divideMax[POKEY_CHANNEL3]) {
pokey_divideMax[POKEY_CHANNEL3] = newValue;
if(pokey_divideCount[POKEY_CHANNEL3] > newValue) {
if(pokey_divideCount[POKEY_CHANNEL3] > newValue) {
pokey_divideCount[POKEY_CHANNEL3] = newValue;
}
}
@@ -266,19 +399,25 @@ void pokey_SetRegister(word address, byte value) {
pokey_divideMax[POKEY_CHANNEL4] = newValue;
if(pokey_divideCount[POKEY_CHANNEL4] > newValue) {
pokey_divideCount[POKEY_CHANNEL4] = newValue;
}
}
}
}
for(byte channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) {
if(channelMask & (1 << channel)) {
if((pokey_audc[channel] & POKEY_VOLUME_ONLY) || ((pokey_audc[channel] & POKEY_VOLUME_MASK) == 0) || (pokey_divideMax[channel] < (pokey_sampleMax >> 8))) {
if((pokey_audc[channel] & POKEY_VOLUME_ONLY) ||
((pokey_audc[channel] & POKEY_VOLUME_MASK) == 0) ||
(pokey_divideMax[channel] < (pokey_sampleMax >> 8))) {
#if 1 // WII
pokey_outVol[channel] = 1;
#else
pokey_outVol[channel] = pokey_audc[channel] & POKEY_VOLUME_MASK;
#endif
pokey_divideCount[channel] = 0x7fffffff;
pokey_divideMax[channel] = 0x7fffffff;
}
}
}
}
}
// ----------------------------------------------------------------------------
@@ -286,13 +425,18 @@ void pokey_SetRegister(word address, byte value) {
// ----------------------------------------------------------------------------
void pokey_Process(uint length) {
byte* buffer = pokey_buffer + pokey_soundCntr;
uint* sampleCntrPtr = (uint*)((byte*)(&pokey_sampleCount[0]) + 1);
//#ifdef BIG_ENDIAN
// uint* sampleCntrPtrB = (uint*)((byte*)&pokey_sampleCount[0] + 3);
//#else
uint* sampleCntrPtrB = (uint*)((byte*)&pokey_sampleCount[0] + 1);
//#endif
uint size = length;
while(length) {
byte currentValue;
byte nextEvent = POKEY_SAMPLE;
uint eventMin = *sampleCntrPtr;
uint eventMin = *sampleCntrPtrB;
byte channel;
for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) {
@@ -301,12 +445,12 @@ void pokey_Process(uint length) {
nextEvent = channel;
}
}
for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) {
pokey_divideCount[channel] -= eventMin;
}
*sampleCntrPtr -= eventMin;
*sampleCntrPtrB -= eventMin;
pokey_polyAdjust += eventMin;
if(nextEvent != POKEY_SAMPLE) {
@@ -336,7 +480,11 @@ void pokey_Process(uint length) {
}
}
else {
//#ifdef BIG_ENDIAN
// *(pokey_sampleCount + 1) += pokey_sampleMax;
//#else
*pokey_sampleCount += pokey_sampleMax;
//#endif
currentValue = 0;
for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) {
@@ -347,8 +495,8 @@ void pokey_Process(uint length) {
*buffer++ = currentValue;
length--;
}
}
}
pokey_soundCntr += size;
if(pokey_soundCntr >= pokey_size) {
pokey_soundCntr = 0;
@@ -359,7 +507,6 @@ void pokey_Process(uint length) {
// Clear
// ----------------------------------------------------------------------------
void pokey_Clear( ) {
for(int index = 0; index < POKEY_BUFFER_SIZE; index++) {
pokey_buffer[index] = 0;
}
}
pokey_soundCntr = 0;
memset(pokey_buffer, 0, POKEY_BUFFER_SIZE);
}
+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
+377 -66
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,15 +46,17 @@ void prosystem_Reset( ) {
if(cartridge_IsLoaded( )) {
prosystem_paused = false;
prosystem_frame = 0;
sally_Reset( );
region_Reset( );
tia_Clear( );
tia_Reset( );
pokey_Clear( );
pokey_Reset( );
xm_Reset( );
memory_Reset( );
maria_Clear( );
maria_Reset( );
riot_Reset ( );
riot_Reset( );
if(bios_enabled) {
bios_Store( );
}
@@ -60,57 +68,142 @@ void prosystem_Reset( ) {
}
}
/*
* Strobe based on the current lightgun location
*/
static void prosystem_FireLightGun()
{
if( ( ( maria_scanline >= lightgun_scanline ) &&
( maria_scanline <= ( lightgun_scanline + 3 ) ) ) &&
( prosystem_cycles >= ((int)lightgun_cycle ) - 1 ) )
{
memory_ram[INPT4] &= 0x7f;
}
else
{
memory_ram[INPT4] |= 0x80;
}
}
uint prosystem_extra_cycles = 0;
// ----------------------------------------------------------------------------
// ExecuteFrame
// ----------------------------------------------------------------------------
void prosystem_ExecuteFrame(const byte* input) {
// Is WSYNC enabled for the current frame?
bool wsync = !(cartridge_flags & CARTRIDGE_WSYNC_MASK);
// Is Maria cycle stealing enabled for the current frame?
bool cycle_stealing = !(cartridge_flags & CARTRIDGE_CYCLE_STEALING_MASK);
// Is the lightgun enabled for the current frame?
bool lightgun = ((cartridge_controller[0] & CARTRIDGE_CONTROLLER_LIGHTGUN) && (memory_ram[CTRL] & 96) != 64);
riot_SetInput(input);
prosystem_extra_cycles = 0;
if(cartridge_pokey || cartridge_xm) pokey_Frame();
for(maria_scanline = 1; maria_scanline <= prosystem_scanlines; maria_scanline++) {
if(maria_scanline == maria_displayArea.top) {
memory_ram[MSTAT] = 0;
}
if(maria_scanline == maria_displayArea.bottom) {
else if(maria_scanline == maria_displayArea.bottom) {
memory_ram[MSTAT] = 128;
}
uint cycles;
prosystem_cycles %= 456;
while(prosystem_cycles < 28) {
// Was a WSYNC performed withing the current scanline?
bool wsync_scanline = false;
uint cycles = 0;
if(!cycle_stealing || (memory_ram[CTRL] & 96 ) != 64) {
// Exact cycle counts when Maria is disabled
prosystem_cycles %= CYCLES_PER_SCANLINE;
prosystem_extra_cycles = 0;
}
else
{
prosystem_extra_cycles = (prosystem_cycles % CYCLES_PER_SCANLINE);
// Some fudge for Maria cycles. Unfortunately Maria cycle counting
// isn't exact (This adds some extra cycles).
prosystem_cycles = 0;
}
// If lightgun is enabled, check to see if it should be fired
if(lightgun) prosystem_FireLightGun();
while(prosystem_cycles < cartridge_hblank) {
cycles = sally_ExecuteInstruction( );
prosystem_cycles += (cycles << 2);
if(half_cycle) prosystem_cycles += 2;
if(riot_timing) {
riot_UpdateTimer(cycles);
}
if(memory_ram[WSYNC] && !(cartridge_flags & CARTRIDGE_WSYNC_MASK)) {
prosystem_cycles = 456;
// If lightgun is enabled, check to see if it should be fired
if(lightgun) prosystem_FireLightGun();
if(memory_ram[WSYNC] && wsync) {
memory_ram[WSYNC] = false;
wsync_scanline = true;
break;
}
}
}
cycles = maria_RenderScanline( );
if(cartridge_flags & CARTRIDGE_CYCLE_STEALING_MASK) {
if(cycle_stealing) {
prosystem_cycles += cycles;
if(riot_timing) {
riot_UpdateTimer(cycles >> 2);
}
}
while(prosystem_cycles < 456) {
while(!wsync_scanline && prosystem_cycles < CYCLES_PER_SCANLINE) {
cycles = sally_ExecuteInstruction( );
prosystem_cycles += (cycles << 2);
if(half_cycle) prosystem_cycles += 2;
// If lightgun is enabled, check to see if it should be fired
if(lightgun) prosystem_FireLightGun();
if(riot_timing) {
riot_UpdateTimer(cycles);
}
if(memory_ram[WSYNC] && !(cartridge_flags & CARTRIDGE_WSYNC_MASK)) {
prosystem_cycles = 456;
if(memory_ram[WSYNC] && wsync) {
memory_ram[WSYNC] = false;
wsync_scanline = true;
break;
}
}
// If a WSYNC was performed and the current cycle count is less than
// the cycles per scanline, add those cycles to current timers.
if(wsync_scanline && prosystem_cycles < CYCLES_PER_SCANLINE) {
if(riot_timing)
{
riot_UpdateTimer((CYCLES_PER_SCANLINE - prosystem_cycles) >> 2);
}
prosystem_cycles = CYCLES_PER_SCANLINE;
}
// If lightgun is enabled, check to see if it should be fired
if(lightgun) prosystem_FireLightGun();
tia_Process(2);
if(cartridge_pokey) {
if(cartridge_pokey || cartridge_xm) {
pokey_Process(2);
}
if(cartridge_pokey || cartridge_xm) pokey_Scanline();
}
prosystem_frame++;
if(prosystem_frame >= prosystem_frequency) {
prosystem_frame = 0;
@@ -127,72 +220,158 @@ bool prosystem_Save(std::string filename, bool compress) {
}
logger_LogInfo("Saving game state to file " + filename + ".", PRO_SYSTEM_SOURCE);
byte buffer[32829] = {0};
byte loc_buffer[33000 + XM_RAM_SIZE + 4] = {0};
uint size = 0;
uint index;
for(index = 0; index < 16; index++) {
buffer[size + index] = PRO_SYSTEM_STATE_HEADER[index];
loc_buffer[size + index] = PRO_SYSTEM_STATE_HEADER[index];
}
size += 16;
buffer[size++] = 1;
loc_buffer[size++] = 1;
for(index = 0; index < 4; index++) {
buffer[size + index] = 0;
loc_buffer[size + index] = 0;
}
size += 4;
for(index = 0; index < 32; index++) {
buffer[size + index] = cartridge_digest[index];
loc_buffer[size + index] = cartridge_digest[index];
}
size += 32;
buffer[size++] = sally_a;
buffer[size++] = sally_x;
buffer[size++] = sally_y;
buffer[size++] = sally_p;
buffer[size++] = sally_s;
buffer[size++] = sally_pc.b.l;
buffer[size++] = sally_pc.b.h;
buffer[size++] = cartridge_bank;
loc_buffer[size++] = sally_a;
loc_buffer[size++] = sally_x;
loc_buffer[size++] = sally_y;
loc_buffer[size++] = sally_p;
loc_buffer[size++] = sally_s;
loc_buffer[size++] = sally_pc.b.l;
loc_buffer[size++] = sally_pc.b.h;
loc_buffer[size++] = cartridge_bank;
for(index = 0; index < 16384; index++) {
buffer[size + index] = memory_ram[index];
loc_buffer[size + index] = memory_ram[index];
}
size += 16384;
if(cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) {
for(index = 0; index < 16384; index++) {
buffer[size + index] = memory_ram[16384 + index];
loc_buffer[size + index] = memory_ram[16384 + index];
}
size += 16384;
}
if(!compress) {
// RIOT state
loc_buffer[size++] = riot_dra;
loc_buffer[size++] = riot_drb;
loc_buffer[size++] = riot_timing;
loc_buffer[size++] = ( 0xff & ( riot_timer >> 8 ) );
loc_buffer[size++] = ( 0xff & riot_timer );
loc_buffer[size++] = riot_intervals;
loc_buffer[size++] = ( 0xff & ( riot_clocks >> 8 ) );
loc_buffer[size++] = ( 0xff & riot_clocks );
// XM (if applicable)
if (cartridge_xm) {
loc_buffer[size++] = xm_reg;
loc_buffer[size++] = xm_bank;
loc_buffer[size++] = xm_pokey_enabled;
loc_buffer[size++] = xm_mem_enabled;
for (index = 0; index < XM_RAM_SIZE; index++) {
loc_buffer[size + index] = xm_ram[index];
}
size += XM_RAM_SIZE;
}
FILE* file = fopen(filename.c_str( ), "wb");
if(file == NULL) {
logger_LogError("Failed to open the file " + filename + " for writing.", PRO_SYSTEM_SOURCE);
return false;
}
if(fwrite(buffer, 1, size, file) != size) {
if(fwrite(loc_buffer, 1, size, file) != size) {
fclose(file);
logger_LogError("Failed to write the save state data to the file " + filename + ".", PRO_SYSTEM_SOURCE);
return false;
}
fflush(file);
fclose(file);
}
else {
if(!archive_Compress(filename.c_str( ), "Save.sav", buffer, size)) {
logger_LogError("Failed to compress the save state data to the file " + filename + ".", PRO_SYSTEM_SOURCE);
return false;
}
}
return true;
}
bool prosystem_Save_buffer(byte *buffer)
{
uint size = 0;
uint index;
for(index = 0; index < 16; index++) {
buffer[size + index] = PRO_SYSTEM_STATE_HEADER[index];
}
size += 16;
buffer[size++] = 1;
for(index = 0; index < 4; index++) {
buffer[size + index] = 0;
}
size += 4;
for(index = 0; index < 32; index++) {
buffer[size + index] = cartridge_digest[index];
}
size += 32;
buffer[size++] = sally_a;
buffer[size++] = sally_x;
buffer[size++] = sally_y;
buffer[size++] = sally_p;
buffer[size++] = sally_s;
buffer[size++] = sally_pc.b.l;
buffer[size++] = sally_pc.b.h;
buffer[size++] = cartridge_bank;
for(index = 0; index < 16384; index++) {
buffer[size + index] = memory_ram[index];
}
size += 16384;
if(cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) {
for(index = 0; index < 16384; index++) {
buffer[size + index] = memory_ram[16384 + index];
}
size += 16384;
}
// RIOT state
buffer[size++] = riot_dra;
buffer[size++] = riot_drb;
buffer[size++] = riot_timing;
buffer[size++] = ( 0xff & ( riot_timer >> 8 ) );
buffer[size++] = ( 0xff & riot_timer );
buffer[size++] = riot_intervals;
buffer[size++] = ( 0xff & ( riot_clocks >> 8 ) );
buffer[size++] = ( 0xff & riot_clocks );
// XM (if applicable)
if (cartridge_xm) {
buffer[size++] = xm_reg;
buffer[size++] = xm_bank;
buffer[size++] = xm_pokey_enabled;
buffer[size++] = xm_mem_enabled;
for (index = 0; index < XM_RAM_SIZE; index++) {
buffer[size + index] = xm_ram[index];
}
size += XM_RAM_SIZE;
}
return true;
}
// ----------------------------------------------------------------------------
// Load
// ----------------------------------------------------------------------------
@@ -202,10 +381,10 @@ bool prosystem_Load(const std::string filename) {
return false;
}
logger_LogInfo("Loading game state from file " + filename + ".", PRO_SYSTEM_SOURCE);
byte loc_buffer[33000 + XM_RAM_SIZE + 4] = {0};
byte buffer[32829] = {0};
uint size = archive_GetUncompressedFileSize(filename);
if(size == 0) {
FILE* file = fopen(filename.c_str( ), "rb");
@@ -214,34 +393,35 @@ bool prosystem_Load(const std::string filename) {
return false;
}
if(fseek(file, 0, SEEK_END)) {
if(fseek(file, 0L, SEEK_END)) {
fclose(file);
logger_LogError("Failed to find the end of the file.", PRO_SYSTEM_SOURCE);
return false;
}
size = ftell(file);
if(fseek(file, 0, SEEK_SET)) {
if(fseek(file, 0L, SEEK_SET)) {
fclose(file);
logger_LogError("Failed to find the size of the file.", PRO_SYSTEM_SOURCE);
return false;
}
if(size != 16445 && size != 32829) {
if( size != 16445 && size != 32829 && /* no RIOT */
size != 16453 && size != 32837 && /* with RIOT */
size != (16453 + 4 + XM_RAM_SIZE) && /* XM without supercart ram */
size != (32837 + 4 + XM_RAM_SIZE)) /* XM with supercart ram */
{
fclose(file);
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
return false;
}
if(fread(buffer, 1, size, file) != size && ferror(file)) {
if(fread(loc_buffer, 1, size, file) != size && ferror(file)) {
fclose(file);
logger_LogError("Failed to read the file data.", PRO_SYSTEM_SOURCE);
return false;
}
fclose(file);
}
else if(size == 16445 || size == 32829) {
archive_Uncompress(filename, buffer, size);
}
else {
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
@@ -251,13 +431,13 @@ bool prosystem_Load(const std::string filename) {
uint offset = 0;
uint index;
for(index = 0; index < 16; index++) {
if(buffer[offset + index] != PRO_SYSTEM_STATE_HEADER[index]) {
if(loc_buffer[offset + index] != PRO_SYSTEM_STATE_HEADER[index]) {
logger_LogError("File is not a valid ProSystem save state.", PRO_SYSTEM_SOURCE);
return false;
}
}
offset += 16;
byte version = buffer[offset++];
byte version = loc_buffer[offset++];
uint date = 0;
for(index = 0; index < 4; index++) {
@@ -268,7 +448,7 @@ bool prosystem_Load(const std::string filename) {
char digest[33] = {0};
for(index = 0; index < 32; index++) {
digest[index] = buffer[offset + index];
digest[index] = loc_buffer[offset + index];
}
offset += 32;
if(cartridge_digest != std::string(digest)) {
@@ -276,35 +456,166 @@ bool prosystem_Load(const std::string filename) {
return false;
}
sally_a = buffer[offset++];
sally_x = buffer[offset++];
sally_y = buffer[offset++];
sally_p = buffer[offset++];
sally_s = buffer[offset++];
sally_pc.b.l = buffer[offset++];
sally_pc.b.h = buffer[offset++];
sally_a = loc_buffer[offset++];
sally_x = loc_buffer[offset++];
sally_y = loc_buffer[offset++];
sally_p = loc_buffer[offset++];
sally_s = loc_buffer[offset++];
sally_pc.b.l = loc_buffer[offset++];
sally_pc.b.h = loc_buffer[offset++];
cartridge_StoreBank(buffer[offset++]);
cartridge_StoreBank(loc_buffer[offset++]);
for(index = 0; index < 16384; index++) {
memory_ram[index] = buffer[offset + index];
memory_ram[index] = loc_buffer[offset + index];
}
offset += 16384;
if(cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) {
if(size != 32829) {
if (size != 32829 && /* no RIOT */
size != 32837 && /* with RIOT */
size != (32837 + 4 + XM_RAM_SIZE)) /* XM */ {
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
return false;
}
for(index = 0; index < 16384; index++) {
memory_ram[16384 + index] = buffer[offset + index];
memory_ram[16384 + index] = loc_buffer[offset + index];
}
offset += 16384;
}
if (size == 16453 || /* no supercart ram */
size == 32837 || /* supercart ram */
size == (16453 + 4 + XM_RAM_SIZE) || /* xm, no supercart ram */
size == (32837 + 4 + XM_RAM_SIZE)) /* xm, supercart ram */ {
// RIOT state
riot_dra = loc_buffer[offset++];
riot_drb = loc_buffer[offset++];
riot_timing = loc_buffer[offset++];
riot_timer = ( loc_buffer[offset++] << 8 );
riot_timer |= loc_buffer[offset++];
riot_intervals = loc_buffer[offset++];
riot_clocks = ( loc_buffer[offset++] << 8 );
riot_clocks |= loc_buffer[offset++];
}
// XM (if applicable)
if (cartridge_xm) {
if ((size != (16453 + 4 + XM_RAM_SIZE)) &&
(size != (32837 + 4 + XM_RAM_SIZE))) {
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
return false;
}
xm_reg = loc_buffer[offset++];
xm_bank = loc_buffer[offset++];
xm_pokey_enabled = loc_buffer[offset++];
xm_mem_enabled = loc_buffer[offset++];
for (index = 0; index < XM_RAM_SIZE; index++) {
xm_ram[index] = loc_buffer[offset++];
}
}
return true;
}
bool prosystem_Load_buffer(const byte *buffer)
{
uint size = cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM ? 32837 : 16453;
if(cartridge_xm) {
size += 4 + XM_RAM_SIZE;
}
uint offset = 0;
uint index;
for(index = 0; index < 16; index++) {
if(buffer[offset + index] != PRO_SYSTEM_STATE_HEADER[index]) {
logger_LogError("File is not a valid ProSystem save state.", PRO_SYSTEM_SOURCE);
return false;
}
}
offset += 16;
byte version = buffer[offset++];
//uint date = 0;
offset += 4;
//prosystem_Reset(); // TODO doesn't seem necessary but needs investigation
char digest[33] = {0};
for(index = 0; index < 32; index++) {
digest[index] = buffer[offset + index];
}
offset += 32;
if(cartridge_digest != std::string(digest)) {
logger_LogError("Load state digest [" + std::string(digest) + "] does not match loaded cartridge digest [" + cartridge_digest + "].", PRO_SYSTEM_SOURCE);
return false;
}
sally_a = buffer[offset++];
sally_x = buffer[offset++];
sally_y = buffer[offset++];
sally_p = buffer[offset++];
sally_s = buffer[offset++];
sally_pc.b.l = buffer[offset++];
sally_pc.b.h = buffer[offset++];
cartridge_StoreBank(buffer[offset++]);
for(index = 0; index < 16384; index++) {
memory_ram[index] = buffer[offset + index];
}
offset += 16384;
if(cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) {
if (size != 32829 && /* no RIOT */
size != 32837 && /* with RIOT */
size != (32837 + 4 + XM_RAM_SIZE)) /* XM */ {
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
return false;
}
for(index = 0; index < 16384; index++) {
memory_ram[16384 + index] = buffer[offset + index];
}
offset += 16384;
}
if (size == 16453 || /* no supercart ram */
size == 32837 || /* supercart ram */
size == (16453 + 4 + XM_RAM_SIZE) || /* xm, no supercart ram */
size == (32837 + 4 + XM_RAM_SIZE)) /* xm, supercart ram */ {
// RIOT state
riot_dra = buffer[offset++];
riot_drb = buffer[offset++];
riot_timing = buffer[offset++];
riot_timer = ( buffer[offset++] << 8 );
riot_timer |= buffer[offset++];
riot_intervals = buffer[offset++];
riot_clocks = ( buffer[offset++] << 8 );
riot_clocks |= buffer[offset++];
}
// XM (if applicable)
if (cartridge_xm) {
if ((size != (16453 + 4 + XM_RAM_SIZE)) &&
(size != (32837 + 4 + XM_RAM_SIZE))) {
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
return false;
}
xm_reg = buffer[offset++];
xm_bank = buffer[offset++];
xm_pokey_enabled = buffer[offset++];
xm_mem_enabled = buffer[offset++];
for (index = 0; index < XM_RAM_SIZE; index++) {
xm_ram[index] = buffer[offset++];
}
}
return true;
}
// ----------------------------------------------------------------------------
// Pause
// ----------------------------------------------------------------------------
+21 -2
View File
@@ -24,7 +24,6 @@
// ----------------------------------------------------------------------------
#ifndef PRO_SYSTEM_H
#define PRO_SYSTEM_H
//#define NULL 0
#include <string>
#include <stdio.h>
@@ -39,15 +38,27 @@
#include "Archive.h"
#include "Tia.h"
#include "Pokey.h"
#include "ExpansionModule.h"
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned int uint;
// The number of cycles per scan line
#define CYCLES_PER_SCANLINE 454
// The number of cycles for HBLANK
#define HBLANK_CYCLES 136
// The number of cycles per scanline that the 7800 checks for a hit
#define LG_CYCLES_PER_SCANLINE 318
// The number of cycles indented (after HBLANK) prior to checking for a hit
#define LG_CYCLES_INDENT 52
extern void prosystem_Reset( );
extern void prosystem_ExecuteFrame(const byte* input);
extern bool prosystem_Save(std::string filename, bool compress);
extern bool prosystem_Load(std::string filename);
extern bool prosystem_Save_buffer(byte *buffer);
extern bool prosystem_Load_buffer(const byte *buffer);
extern void prosystem_Pause(bool pause);
extern void prosystem_Close( );
extern bool prosystem_active;
@@ -56,5 +67,13 @@ extern word prosystem_frequency;
extern byte prosystem_frame;
extern word prosystem_scanlines;
extern uint prosystem_cycles;
extern uint prosystem_extra_cycles;
#endif
// The scanline that the lightgun shot occurred at
extern int lightgun_scanline;
// The cycle that the lightgun shot occurred at
extern float lightgun_cycle;
// Whether the lightgun is enabled for the current cartridge
//extern bool lightgun_enabled;
#endif
+10 -8
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
+41 -4
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;
@@ -58,11 +64,11 @@ static const Vector SALLY_NMI = {65531, 65530};
static const Vector SALLY_IRQ = {65535, 65534};
static const byte SALLY_CYCLES[256] = {
7,6,0,0,0,3,5,0,3,2,2,0,0,4,6,0,
7,6,0,0,0,3,5,0,3,2,2,2,0,4,6,0,
2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0,
6,6,0,0,3,3,5,0,4,2,2,0,4,4,6,0,
6,6,0,0,3,3,5,0,4,2,2,2,4,4,6,0,
2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0,
6,6,0,0,0,3,5,0,3,2,2,0,3,4,6,0,
6,6,0,0,0,3,5,0,3,2,2,2,3,4,6,0,
2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0,
6,6,0,0,0,3,5,0,4,2,2,0,5,4,6,0,
2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0,
@@ -116,7 +122,7 @@ static void sally_Flags(byte data) {
static void sally_Branch(byte branch) {
if(branch) {
pair temp = sally_pc;
sally_pc.w += (char)sally_address.b.l;
sally_pc.w += (signed char)sally_address.b.l;
if(temp.b.h != sally_pc.b.h) {
sally_cycles += 2;
@@ -935,6 +941,9 @@ void sally_Reset( ) {
// ExecuteInstruction
// ----------------------------------------------------------------------------
uint sally_ExecuteInstruction( ) {
// Reset half cycle flag
half_cycle = false;
sally_opcode = memory_Read(sally_pc.w++);
sally_cycles = SALLY_CYCLES[sally_opcode];
@@ -1036,6 +1045,14 @@ uint sally_ExecuteInstruction( ) {
case 0x24:
sally_ZeroPage( );
sally_BIT( );
// Add a half cycle if RIOT/TIA location is accessed. We only track
// INPT4 since it is the only one that is accessed during the lightgun
// hit detection loop. This should be extended to take into consideration
// all RIOT and TIA accesses.
if( sally_address.w == INPT4 )
{
half_cycle = true;
}
break;
case 0x25:
@@ -1688,6 +1705,26 @@ uint sally_ExecuteInstruction( ) {
sally_INC( );
break;
case 0x4b: // ALR (ASR)
sally_Immediate();
sally_AND();
sally_LSRA();
break;
case 0x0b: // ANC
case 0x2b: { // ANC
sally_Immediate();
sally_AND();
if (sally_a & 128) {
sally_p |= SALLY_FLAG.C;
}
else {
//sally_p &= ~SALLY_FLAG.C;
sally_p = (sally_p & ~SALLY_FLAG.C) & 0xFF;
}
break;
}
default:
break;
}
+54 -400
View File
@@ -1,11 +1,12 @@
// ----------------------------------------------------------------------------
// ___ ___ ___ ___ ___ ____ ___ _ _
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ /
// / / \ /__/ ___/ ___/ ___/ / /__ / / emulator
// ___ ___ ___ ___ ___ ____ ___ _ _ __ ___
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ / / / _
// / / \ /__/ ___/ ___/ ___/ / /__ / / ___/ /__/
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
// Copyright 2020 Rupert Carmichael
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
@@ -20,414 +21,67 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// Sound.cpp
// Sound.c
// ----------------------------------------------------------------------------
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "Sound.h"
#define SOUND_LATENCY_SCALE 4
byte sound_latency = SOUND_LATENCY_VERY_LOW;
#define MAX_BUFFER_SIZE 8192
static const WAVEFORMATEX SOUND_DEFAULT_FORMAT = {WAVE_FORMAT_PCM, 1, 44100, 44100, 1, 8, 0};
static LPDIRECTSOUND sound_dsound = NULL;
static LPDIRECTSOUNDBUFFER sound_primaryBuffer = NULL;
static LPDIRECTSOUNDBUFFER sound_buffer = NULL;
static WAVEFORMATEX sound_format = SOUND_DEFAULT_FORMAT;
static uint sound_counter = 0;
static bool sound_muted = false;
static uint32_t nSamplesPerSec = 48000;
// ----------------------------------------------------------------------------
// GetSampleLength
// ----------------------------------------------------------------------------
static uint sound_GetSampleLength(uint length, uint unit, uint unitMax) {
uint sampleLength = length / unitMax;
uint sampleRemain = length % unitMax;
if(sampleRemain != 0 && sampleRemain >= unit) {
sampleLength++;
}
return sampleLength;
static void sound_Resample(const uint8_t *source, uint8_t *target, int length) {
int measurement = nSamplesPerSec;
int sourceIndex = 0;
int targetIndex = 0;
int max = ((prosystem_frequency * prosystem_scanlines) << 1);
while (targetIndex < length) {
if (measurement >= max) {
target[targetIndex++] = source[sourceIndex];
measurement -= max;
}
else {
sourceIndex++;
measurement += nSamplesPerSec;
}
}
}
// ----------------------------------------------------------------------------
// Resample
// ----------------------------------------------------------------------------
static void sound_Resample(const byte* source, byte* target, int length) {
int measurement = sound_format.nSamplesPerSec;
int sourceIndex = 0;
int targetIndex = 0;
while(targetIndex < length) {
if(measurement >= 31440) {
target[targetIndex++] = source[sourceIndex];
measurement -= 31440;
uint32_t sound_Store(uint8_t *out_buffer) {
memset(out_buffer, 0, MAX_BUFFER_SIZE);
uint32_t length = nSamplesPerSec / prosystem_frequency;
sound_Resample(tia_buffer, out_buffer, length);
tia_Clear();
// Ballblazer, Commando, various homebrew and hacks
if(cartridge_pokey || xm_pokey_enabled) {
uint8_t pokeySample[MAX_BUFFER_SIZE];
memset(pokeySample, 0, MAX_BUFFER_SIZE);
sound_Resample(pokey_buffer, pokeySample, length);
for(uint32_t index = 0; index < length; index++) {
uint32_t sound = out_buffer[index] + pokeySample[index];
out_buffer[index] = sound >> 1;
}
}
else {
sourceIndex++;
measurement += sound_format.nSamplesPerSec;
}
}
}
// ----------------------------------------------------------------------------
// RestoreBuffer
// ----------------------------------------------------------------------------
static bool sound_RestoreBuffer( ) {
if(sound_buffer != NULL) {
HRESULT hr = sound_buffer->Restore( );
if(FAILED(hr)) {
logger_LogError(IDS_SOUND1,"");
logger_LogError("",common_Format(hr));
return false;
}
}
return true;
}
// ----------------------------------------------------------------------------
// ReleaseBuffer
// ----------------------------------------------------------------------------
static bool sound_ReleaseBuffer(LPDIRECTSOUNDBUFFER buffer) {
if(buffer != NULL) {
HRESULT hr = buffer->Release( );
sound_buffer = NULL;
if(FAILED(hr)) {
logger_LogError(IDS_SOUND2,"");
logger_LogError("",common_Format(hr));
return false;
}
}
return true;
}
// ----------------------------------------------------------------------------
// ReleaseSound
// ----------------------------------------------------------------------------
static bool sound_ReleaseSound( ) {
if(sound_dsound != NULL) {
HRESULT hr = sound_dsound->Release( );
sound_dsound = NULL;
if(FAILED(hr)) {
logger_LogError(IDS_SOUND3,"");
logger_LogError("",common_Format(hr));
return false;
}
}
return true;
}
// ----------------------------------------------------------------------------
// Initialize
// ----------------------------------------------------------------------------
bool sound_Initialize(HWND hWnd) {
if(hWnd == NULL) {
logger_LogError(IDS_INPUT1,"");
return false;
}
HRESULT hr = DirectSoundCreate(NULL, &sound_dsound, NULL);
if(FAILED(hr) || sound_dsound == NULL) {
logger_LogError(IDS_SOUND4,"");
logger_LogError("",common_Format(hr));
return false;
}
hr = sound_dsound->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
if(FAILED(hr)) {
logger_LogError(IDS_INPUT6,"");
logger_LogError("",common_Format(hr));
return false;
}
DSBUFFERDESC primaryDesc;
primaryDesc.dwReserved = 0;
primaryDesc.dwSize = sizeof(DSBUFFERDESC);
primaryDesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
primaryDesc.dwBufferBytes = 0;
primaryDesc.lpwfxFormat = NULL;
hr = sound_dsound->CreateSoundBuffer(&primaryDesc, &sound_primaryBuffer, NULL);
if(FAILED(hr) || sound_primaryBuffer == NULL) {
logger_LogError(IDS_SOUND5,"");
logger_LogError("",common_Format(hr));
return false;
}
if(!sound_SetFormat(SOUND_DEFAULT_FORMAT)) {
logger_LogError(IDS_SOUND6,"");
return false;
}
//Leonis
sound_SetSampleRate(samplerate);
return true;
}
// ----------------------------------------------------------------------------
// SetFormat
// ----------------------------------------------------------------------------
bool sound_SetFormat(WAVEFORMATEX format) {
if(sound_dsound == NULL) {
logger_LogError(IDS_SOUND7,"");
return false;
}
if(sound_primaryBuffer == NULL) {
logger_LogError(IDS_SOUND8,"");
return false;
}
HRESULT hr = sound_primaryBuffer->SetFormat(&format);
if(FAILED(hr)) {
logger_LogError(IDS_SOUND9,"");
logger_LogError("",common_Format(hr));
return false;
}
DSBUFFERDESC secondaryDesc;
secondaryDesc.dwReserved = 0;
secondaryDesc.dwSize = sizeof(DSBUFFERDESC);
secondaryDesc.dwFlags = DSBCAPS_GLOBALFOCUS;
secondaryDesc.dwBufferBytes = format.nSamplesPerSec;
secondaryDesc.lpwfxFormat = &format;
hr = sound_dsound->CreateSoundBuffer(&secondaryDesc, &sound_buffer, NULL);
if(FAILED(hr) || sound_buffer == NULL) {
logger_LogError(IDS_SOUND10,"");
logger_LogError("",common_Format(hr));
return false;
}
sound_format = format;
return true;
}
// ----------------------------------------------------------------------------
// Store
// ----------------------------------------------------------------------------
bool sound_Store( ) {
if(sound_dsound == NULL) {
logger_LogError(IDS_SOUND7,"");
return false;
}
if(sound_primaryBuffer == NULL) {
logger_LogError(IDS_SOUND8,"");
return false;
}
if(sound_buffer == NULL) {
logger_LogError(IDS_SOUND11,"");
return false;
}
byte sample[1920];
uint length = sound_GetSampleLength(sound_format.nSamplesPerSec, prosystem_frame, prosystem_frequency);
sound_Resample(tia_buffer, sample, length);
if(cartridge_pokey) {
byte pokeySample[1920];
sound_Resample(pokey_buffer, pokeySample, length);
for(int index = 0; index < length; index++) {
sample[index] += pokeySample[index];
sample[index] = sample[index] / 2;
}
}
DWORD lockCount = 0;
byte* lockStream = NULL;
DWORD wrapCount = 0;
byte* wrapStream = NULL;
HRESULT hr = sound_buffer->Lock(sound_counter, length, (void**)&lockStream, &lockCount, (void**)&wrapStream, &wrapCount, 0);
if(FAILED(hr) || lockStream == NULL) {
logger_LogError(IDS_SOUND12,"");
logger_LogError("",common_Format(hr));
if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) {
return false;
}
}
uint bufferCounter = 0;
for(uint lockIndex = 0; lockIndex < lockCount; lockIndex++) {
lockStream[lockIndex] = sample[bufferCounter++];
}
for(uint wrapIndex = 0; wrapIndex < wrapCount; wrapIndex++) {
wrapStream[wrapIndex] = sample[bufferCounter++];
}
hr = sound_buffer->Unlock(lockStream, lockCount, wrapStream, wrapCount);
if(FAILED(hr)) {
logger_LogError(IDS_SOUND13,"");
logger_LogError("",common_Format(hr));
if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) {
return false;
}
}
sound_counter += length;
if(sound_counter >= sound_format.nSamplesPerSec) {
sound_counter -= sound_format.nSamplesPerSec;
}
return true;
}
// ----------------------------------------------------------------------------
// Clear
// ----------------------------------------------------------------------------
bool sound_Clear( ) {
if(sound_dsound == NULL) {
logger_LogError(IDS_SOUND7,"");
return false;
}
if(sound_primaryBuffer == NULL) {
logger_LogError(IDS_SOUND8,"");
return false;
}
if(sound_buffer == NULL) {
logger_LogError(IDS_SOUND11,"");
return false;
}
byte* lockStream = NULL;
DWORD lockCount = 0;
HRESULT hr = sound_buffer->Lock(0, sound_format.nSamplesPerSec, (void**)&lockStream, &lockCount, NULL, NULL, DSBLOCK_ENTIREBUFFER);
if(FAILED(hr) || lockStream == NULL) {
logger_LogError(IDS_SOUND12,"");
logger_LogError("",common_Format(hr));
if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) {
return false;
}
}
for(uint lockIndex = 0; lockIndex < lockCount; lockIndex++) {
lockStream[lockIndex] = 0;
}
hr = sound_buffer->Unlock(lockStream, lockCount, NULL, NULL);
if(FAILED(hr)) {
logger_LogError(IDS_SOUND13,"");
logger_LogError("",common_Format(hr));
if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) {
return false;
}
}
return true;
}
// ----------------------------------------------------------------------------
// Play
// ----------------------------------------------------------------------------
bool sound_Play( ) {
if(sound_dsound == NULL) {
logger_LogError(IDS_SOUND7,"");
return false;
}
if(sound_primaryBuffer == NULL) {
logger_LogError(IDS_SOUND8,"");
return false;
}
if(sound_buffer == NULL) {
logger_LogError(IDS_SOUND11,"");
return false;
}
if(!sound_muted) {
HRESULT hr = sound_buffer->SetCurrentPosition(0);
if(FAILED(hr)) {
logger_LogError(IDS_SOUND14,"");
logger_LogError("",common_Format(hr));
return false;
}
hr = sound_buffer->Play(0, 0, DSBPLAY_LOOPING);
if(FAILED(hr)) {
logger_LogError(IDS_SOUND15,"");
logger_LogError("",common_Format(hr));
if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) {
return false;
}
}
sound_counter = (sound_format.nSamplesPerSec / prosystem_frequency) * (sound_latency * SOUND_LATENCY_SCALE);
}
return true;
}
// ----------------------------------------------------------------------------
// Stop
// ----------------------------------------------------------------------------
bool sound_Stop( ) {
if(sound_dsound == NULL) {
logger_LogError(IDS_SOUND7,"");
return false;
}
if(sound_primaryBuffer == NULL) {
logger_LogError(IDS_SOUND8,"");
return false;
}
if(sound_buffer == NULL) {
logger_LogError(IDS_SOUND11,"");
return false;
}
HRESULT hr = sound_buffer->Stop( );
if(FAILED(hr)) {
logger_LogError(IDS_SOUND16,"");
logger_LogError("",common_Format(hr));
if(hr != DSERR_BUFFERLOST || !sound_RestoreBuffer( )) {
return false;
}
}
return true;
}
// ----------------------------------------------------------------------------
// SetSampleRate
// ----------------------------------------------------------------------------
bool sound_SetSampleRate(uint rate) {
sound_format.nSamplesPerSec = rate;
sound_format.nAvgBytesPerSec = rate;
return sound_SetFormat(sound_format);
}
// ----------------------------------------------------------------------------
// GetSampleRate
// ----------------------------------------------------------------------------
uint sound_GetSampleRate( ) {
return sound_format.nSamplesPerSec;
}
// ----------------------------------------------------------------------------
// SetMuted
// ----------------------------------------------------------------------------
bool sound_SetMuted(bool muted) {
if(sound_muted != muted) {
if(!muted) {
if(!sound_Play( )) {
return false;
for(uint32_t index = 0; index < length; index++) {
out_buffer[index] = out_buffer[index] * 0.75; //>> 1;
}
}
else {
if(!sound_Stop( )) {
return false;
}
}
sound_muted = muted;
}
return true;
pokey_Clear();
return length;
}
// ----------------------------------------------------------------------------
// IsMuted
// ----------------------------------------------------------------------------
bool sound_IsMuted( ) {
return sound_muted;
void sound_SetSampleRate(uint32_t rate) {
nSamplesPerSec = rate;
}
// ----------------------------------------------------------------------------
// Release
// ----------------------------------------------------------------------------
void sound_Release( ) {
sound_ReleaseBuffer(sound_buffer);
sound_ReleaseBuffer(sound_primaryBuffer);
sound_ReleaseSound( );
}
uint32_t sound_GetSampleRate(void) {
return nSamplesPerSec;
}
+4 -24
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
+20 -20
View File
@@ -5,7 +5,7 @@
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
@@ -21,30 +21,31 @@
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// TiaSound is Copyright(c) 1997 by Ron Fries
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of version 2 of the GNU Library General Public License
// as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
// General Public License for more details.
// To obtain a copy of the GNU Library General Public License, write to the
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of version 2 of the GNU Library General Public License
// as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
// General Public License for more details.
// To obtain a copy of the GNU Library General Public License, write to the
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// Any permitted reproduction of these routines, in whole or in part, must
// bear this legend.
// bear this legend.
// ----------------------------------------------------------------------------
// Tia.cpp
// ----------------------------------------------------------------------------
#include "Tia.h"
#include <string.h>
#define TIA_POLY4_SIZE 15
#define TIA_POLY5_SIZE 31
#define TIA_POLY9_SIZE 511
byte tia_buffer[TIA_BUFFER_SIZE] = {0};
uint tia_size = 524;
uint tia_size = TIA_BUFFER_SIZE; // previously was 524
static const byte TIA_POLY4[ ] = {1,1,0,1,1,1,0,0,0,0,1,0,1,0,0};
static const byte TIA_POLY5[ ] = {0,0,1,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,0,0,0,1};
@@ -119,9 +120,8 @@ void tia_Reset( ) {
// Clear
// ----------------------------------------------------------------------------
void tia_Clear( ) {
for(int index = 0; index < TIA_BUFFER_SIZE; index++) {
tia_buffer[index] = 0;
}
tia_soundCntr = 0;
memset(tia_buffer, 0, TIA_BUFFER_SIZE);
}
// ----------------------------------------------------------------------------
@@ -130,7 +130,7 @@ void tia_Clear( ) {
void tia_SetRegister(word address, byte data) {
byte channel;
byte frequency;
switch(address) {
case AUDC0:
tia_audc[0] = data & 15;
@@ -203,4 +203,4 @@ void tia_Process(uint length) {
tia_soundCntr = 0;
}
}
}
}
+2
View File
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */