21 Commits

Author SHA1 Message Date
Stuart Carnie d2f745873a chore: Updated SDK APIs 2023-04-01 10:20:33 +11:00
C.W. Betts 30217f1573 Poke the plists: get the development language from Xcode build. 2020-10-01 01:51:37 -06:00
C.W. Betts 99b00cb506 Fix locations of the system plugin headers.
Minor Xcode maintenance.
2020-10-01 01:26:42 -06:00
C.W. Betts d5ada05caa Update language resources.
This quiets warnings in newer Xcode releases.

Also update framework locations.
2020-01-07 16:34:00 -07:00
clobber a44d58c3f2 Use -fileSystemRepresentation instead of -UTF8String for file names 2017-08-16 23:31:42 -05:00
clobber ffa7f54c7b Enable direct-rendering 2017-07-21 22:32:40 -05:00
Rudy Richter 9bfc60ba63 Use spaces 2017-07-20 08:49:14 -04:00
mrvacbob e67fec4d66 Remove internalPixelFormat 2017-07-20 00:48:08 -07:00
clobber 34d0634d33 Bump version in order for sparkle updater to work. Core is still 3.1.0 2015-12-22 19:12:39 -07:00
clobber 0b0cb4efa1 Fix screen 2015-12-22 19:11:52 -07:00
clobber b8fded2733 Rework cart loading to support Atari 8-bit computer 2015-11-27 17:37:53 -06:00
clobber 9edbc12ada Initial Atari 8-bit computer support 2015-11-26 23:13:24 -06:00
clobber 99aa528027 Cleanup in preparation for Atari 8-bit computer support 2015-11-26 04:08:23 -06:00
Alexander Strange d0ff1ae969 Update projects - fix debug builds, make deployment 10.11, enable objc-arc properly, build faster 2015-10-17 13:04:19 -07:00
clobber 85ff87c8df Turn off GCC_NO_COMMON_BLOCKS 2015-10-09 19:29:58 -05:00
Christoph Leimbrock 85a1a68886 Fix some warning and adjust project settings. 2015-10-06 22:04:33 +02:00
clobber eb317a7914 Enable synchronized sound 2014-08-05 20:05:35 -05:00
clobber 3b9eaf63b9 Fix audio chirping distortion at high pitches.
For NTSC, can't divide the sample rate by 60 or by the precise internal fps, but 59.9 works.
Sample size too low = click/pops, too high = chirps.
2014-08-05 20:04:34 -05:00
clobber 66d5fbcaa0 Disable POKEY stereo flag
Fixes Bounty Bob Strikes Back (Merged) (Big Five Software).a52 title screen freeze for some reason
2014-08-03 20:59:31 -05:00
clobber 268551a95e Keypad buttons support 2014-08-02 14:37:02 -05:00
clobber f657e9b60e Update Atari800 to 3.1.0
Implementation fixes: correct palette is set, save/load states enabled, sound should be better but may need more investigation
2014-08-02 01:08:11 -05:00
49 changed files with 3544 additions and 1841 deletions
+69 -12
View File
@@ -22,7 +22,6 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
02669C761435806A0002A11B /* sound_oss.c in Sources */ = {isa = PBXBuildFile; fileRef = 02669C741435806A0002A11B /* sound_oss.c */; };
02695365143169EB003A07D4 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02695364143169EB003A07D4 /* Cocoa.framework */; };
0269536F143169EB003A07D4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0269536D143169EB003A07D4 /* InfoPlist.strings */; };
026953E714317379003A07D4 /* afile.c in Sources */ = {isa = PBXBuildFile; fileRef = 026953E214317379003A07D4 /* afile.c */; };
@@ -64,8 +63,15 @@
0269545714318515003A07D4 /* colours.c in Sources */ = {isa = PBXBuildFile; fileRef = 0269545214318515003A07D4 /* colours.c */; };
02E763B1143194CF008050EA /* statesav.c in Sources */ = {isa = PBXBuildFile; fileRef = 02E763AF143194CF008050EA /* statesav.c */; };
02E763C414319545008050EA /* ui_basic.c in Sources */ = {isa = PBXBuildFile; fileRef = 02E763C014319545008050EA /* ui_basic.c */; };
02E763C514319545008050EA /* ui.c in Sources */ = {isa = PBXBuildFile; fileRef = 02E763C214319545008050EA /* ui.c */; };
02E763C81431958E008050EA /* input.c in Sources */ = {isa = PBXBuildFile; fileRef = 02E763C61431958E008050EA /* input.c */; };
9491E45E1989B1CA0075135C /* artifact.c in Sources */ = {isa = PBXBuildFile; fileRef = 9491E45C1989B1CA0075135C /* artifact.c */; };
9491E462198B0A8C0075135C /* cycle_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 9491E460198B0A8C0075135C /* cycle_map.c */; };
9491E46A198C11A10075135C /* default.act in Resources */ = {isa = PBXBuildFile; fileRef = 9491E465198C11A10075135C /* default.act */; };
9491E46B198C11A10075135C /* gray.act in Resources */ = {isa = PBXBuildFile; fileRef = 9491E466198C11A10075135C /* gray.act */; };
9491E46C198C11A10075135C /* jakub.act in Resources */ = {isa = PBXBuildFile; fileRef = 9491E467198C11A10075135C /* jakub.act */; };
9491E46D198C11A10075135C /* Real.act in Resources */ = {isa = PBXBuildFile; fileRef = 9491E468198C11A10075135C /* Real.act */; };
9491E46E198C11A10075135C /* XFormer.act in Resources */ = {isa = PBXBuildFile; fileRef = 9491E469198C11A10075135C /* XFormer.act */; };
9491E46F198CAEB50075135C /* sound.c in Sources */ = {isa = PBXBuildFile; fileRef = 9491E45A1989AF050075135C /* sound.c */; };
94DEA00D1719186F00073397 /* img_tape.c in Sources */ = {isa = PBXBuildFile; fileRef = 94DEA0091719186E00073397 /* img_tape.c */; };
94DEA00E1719186F00073397 /* sysrom.c in Sources */ = {isa = PBXBuildFile; fileRef = 94DEA00B1719186E00073397 /* sysrom.c */; };
94DEA011171918A300073397 /* crc32.c in Sources */ = {isa = PBXBuildFile; fileRef = 94DEA00F171918A200073397 /* crc32.c */; };
@@ -93,7 +99,7 @@
02695368143169EB003A07D4 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
02695369143169EB003A07D4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
0269536C143169EB003A07D4 /* Atari800-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Atari800-Info.plist"; sourceTree = "<group>"; };
0269536E143169EB003A07D4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
0269536E143169EB003A07D4 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
026953E214317379003A07D4 /* afile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = afile.c; path = "atari800-src/afile.c"; sourceTree = SOURCE_ROOT; };
026953E314317379003A07D4 /* afile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = afile.h; path = "atari800-src/afile.h"; sourceTree = SOURCE_ROOT; };
026953E414317379003A07D4 /* akey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = akey.h; path = "atari800-src/akey.h"; sourceTree = SOURCE_ROOT; };
@@ -178,7 +184,18 @@
02E763C314319545008050EA /* ui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ui.h; path = "atari800-src/ui.h"; sourceTree = SOURCE_ROOT; };
02E763C61431958E008050EA /* input.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = input.c; path = "atari800-src/input.c"; sourceTree = SOURCE_ROOT; };
02E763C71431958E008050EA /* input.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = input.h; path = "atari800-src/input.h"; sourceTree = SOURCE_ROOT; };
94619CA315C4D2B10019AC8E /* OE5200SystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OE5200SystemResponderClient.h; path = "../../OpenEmu/Atari 5200/OE5200SystemResponderClient.h"; sourceTree = "<group>"; };
87FBC0A71C079E4800AECF5A /* OEA8SystemResponderClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OEA8SystemResponderClient.h; path = "../../OpenEmu/SystemPlugins/Atari 8-bit/OEA8SystemResponderClient.h"; sourceTree = "<group>"; };
94619CA315C4D2B10019AC8E /* OE5200SystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OE5200SystemResponderClient.h; path = "../../OpenEmu/SystemPlugins/Atari 5200/OE5200SystemResponderClient.h"; sourceTree = "<group>"; };
9491E45A1989AF050075135C /* sound.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sound.c; path = "atari800-src/sound.c"; sourceTree = SOURCE_ROOT; };
9491E45C1989B1CA0075135C /* artifact.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = artifact.c; path = "atari800-src/artifact.c"; sourceTree = SOURCE_ROOT; };
9491E45D1989B1CA0075135C /* artifact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = artifact.h; path = "atari800-src/artifact.h"; sourceTree = SOURCE_ROOT; };
9491E460198B0A8C0075135C /* cycle_map.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cycle_map.c; path = "atari800-src/cycle_map.c"; sourceTree = SOURCE_ROOT; };
9491E461198B0A8C0075135C /* cycle_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cycle_map.h; path = "atari800-src/cycle_map.h"; sourceTree = SOURCE_ROOT; };
9491E465198C11A10075135C /* default.act */ = {isa = PBXFileReference; lastKnownFileType = file; path = default.act; sourceTree = "<group>"; };
9491E466198C11A10075135C /* gray.act */ = {isa = PBXFileReference; lastKnownFileType = file; path = gray.act; sourceTree = "<group>"; };
9491E467198C11A10075135C /* jakub.act */ = {isa = PBXFileReference; lastKnownFileType = file; path = jakub.act; sourceTree = "<group>"; };
9491E468198C11A10075135C /* Real.act */ = {isa = PBXFileReference; lastKnownFileType = file; path = Real.act; sourceTree = "<group>"; };
9491E469198C11A10075135C /* XFormer.act */ = {isa = PBXFileReference; lastKnownFileType = file; path = XFormer.act; sourceTree = "<group>"; };
94DEA0091719186E00073397 /* img_tape.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = img_tape.c; path = "atari800-src/img_tape.c"; sourceTree = SOURCE_ROOT; };
94DEA00A1719186E00073397 /* img_tape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = img_tape.h; path = "atari800-src/img_tape.h"; sourceTree = SOURCE_ROOT; };
94DEA00B1719186E00073397 /* sysrom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sysrom.c; path = "atari800-src/sysrom.c"; sourceTree = SOURCE_ROOT; };
@@ -186,7 +203,7 @@
94DEA00F171918A200073397 /* crc32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = crc32.c; path = "atari800-src/crc32.c"; sourceTree = SOURCE_ROOT; };
94DEA010171918A200073397 /* crc32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = crc32.h; path = "atari800-src/crc32.h"; sourceTree = SOURCE_ROOT; };
94DEA012171918D200073397 /* emuos.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = emuos.c; path = "atari800-src/emuos.c"; sourceTree = SOURCE_ROOT; };
94DEA018171951AD00073397 /* OpenEmuBase.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenEmuBase.framework; path = "../OpenEmu-SDK/build/Release/OpenEmuBase.framework"; sourceTree = "<group>"; };
94DEA018171951AD00073397 /* OpenEmuBase.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = OpenEmuBase.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -213,6 +230,7 @@
02695362143169EB003A07D4 /* Products */,
);
sourceTree = "<group>";
usesTabs = 0;
};
02695362143169EB003A07D4 /* Products */ = {
isa = PBXGroup;
@@ -265,6 +283,7 @@
026953E91431737E003A07D4 /* atari800 */ = {
isa = PBXGroup;
children = (
9491E464198C11A10075135C /* act */,
94DEA012171918D200073397 /* emuos.c */,
94DEA00F171918A200073397 /* crc32.c */,
94DEA010171918A200073397 /* crc32.h */,
@@ -275,6 +294,8 @@
026953EA143175F0003A07D4 /* config.h */,
0269541814317864003A07D4 /* antic.c */,
0269541914317864003A07D4 /* antic.h */,
9491E45C1989B1CA0075135C /* artifact.c */,
9491E45D1989B1CA0075135C /* artifact.h */,
026953E214317379003A07D4 /* afile.c */,
026953E314317379003A07D4 /* afile.h */,
026953E414317379003A07D4 /* akey.h */,
@@ -300,6 +321,8 @@
0269544014317B21003A07D4 /* compfile.h */,
0269541B1431793F003A07D4 /* cpu.c */,
0269541C1431793F003A07D4 /* cpu.h */,
9491E460198B0A8C0075135C /* cycle_map.c */,
9491E461198B0A8C0075135C /* cycle_map.h */,
0269541E1431797A003A07D4 /* devices.c */,
0269541F1431797A003A07D4 /* devices.h */,
02252B371437A377001F3BF4 /* emuos.h */,
@@ -345,6 +368,7 @@
02695449143184CD003A07D4 /* screen.c */,
0269544A143184CD003A07D4 /* screen.h */,
02669C741435806A0002A11B /* sound_oss.c */,
9491E45A1989AF050075135C /* sound.c */,
02669C751435806A0002A11B /* sound.h */,
0269540F143177DF003A07D4 /* rtime.c */,
02695410143177DF003A07D4 /* rtime.h */,
@@ -363,6 +387,7 @@
children = (
0269536A143169EB003A07D4 /* Core */,
0269544514317B62003A07D4 /* platform.h */,
87FBC0A71C079E4800AECF5A /* OEA8SystemResponderClient.h */,
94619CA315C4D2B10019AC8E /* OE5200SystemResponderClient.h */,
0269544614317D34003A07D4 /* ATR800GameCore.h */,
0269544714317D34003A07D4 /* ATR800GameCore.m */,
@@ -371,6 +396,19 @@
path = Atari800Core;
sourceTree = "<group>";
};
9491E464198C11A10075135C /* act */ = {
isa = PBXGroup;
children = (
9491E465198C11A10075135C /* default.act */,
9491E466198C11A10075135C /* gray.act */,
9491E467198C11A10075135C /* jakub.act */,
9491E468198C11A10075135C /* Real.act */,
9491E469198C11A10075135C /* XFormer.act */,
);
name = act;
path = "atari800-src/act";
sourceTree = SOURCE_ROOT;
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -397,11 +435,11 @@
02695358143169EA003A07D4 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0500;
LastUpgradeCheck = 0700;
};
buildConfigurationList = 0269535B143169EA003A07D4 /* Build configuration list for PBXProject "Atari800" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
@@ -422,7 +460,12 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9491E46C198C11A10075135C /* jakub.act in Resources */,
9491E46A198C11A10075135C /* default.act in Resources */,
0269536F143169EB003A07D4 /* InfoPlist.strings in Resources */,
9491E46B198C11A10075135C /* gray.act in Resources */,
9491E46E198C11A10075135C /* XFormer.act in Resources */,
9491E46D198C11A10075135C /* Real.act in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -450,6 +493,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9491E46F198CAEB50075135C /* sound.c in Sources */,
9491E45E1989B1CA0075135C /* artifact.c in Sources */,
0269544814317D34003A07D4 /* ATR800GameCore.m in Sources */,
026953E714317379003A07D4 /* afile.c in Sources */,
026953E814317379003A07D4 /* atari.c in Sources */,
@@ -485,11 +530,10 @@
0269545514318515003A07D4 /* colours_ntsc.c in Sources */,
0269545614318515003A07D4 /* colours_pal.c in Sources */,
0269545714318515003A07D4 /* colours.c in Sources */,
9491E462198B0A8C0075135C /* cycle_map.c in Sources */,
02E763B1143194CF008050EA /* statesav.c in Sources */,
02E763C414319545008050EA /* ui_basic.c in Sources */,
02E763C514319545008050EA /* ui.c in Sources */,
02E763C81431958E008050EA /* input.c in Sources */,
02669C761435806A0002A11B /* sound_oss.c in Sources */,
94DEA00D1719186F00073397 /* img_tape.c in Sources */,
94DEA00E1719186F00073397 /* sysrom.c in Sources */,
94DEA011171918A300073397 /* crc32.c in Sources */,
@@ -538,15 +582,19 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = 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;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
@@ -556,13 +604,15 @@
);
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_MISSING_PROTOTYPES = 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;
MACOSX_DEPLOYMENT_TARGET = 10.7;
LD_NO_PIE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
@@ -573,27 +623,32 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = 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;
COPY_PHASE_STRIP = 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_ENABLE_OBJC_EXCEPTIONS = YES;
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_MISSING_PROTOTYPES = 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;
MACOSX_DEPLOYMENT_TARGET = 10.7;
LD_NO_PIE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11;
SDKROOT = macosx;
};
name = Release;
@@ -610,6 +665,7 @@
INFOPLIST_FILE = "Atari800Core/Atari800-Info.plist";
INSTALL_PATH = "\"$(USER_LIBRARY_DIR)/Application Support/OpenEmu/Cores\"";
LD_RUNPATH_SEARCH_PATHS = "\"/Library/Graphics/Quartz Composer Plug-Ins/OpenEmuQC.plugin/Contents/Frameworks/\" \"~/Library/Graphics/Quartz Composer Plug-Ins/OpenEmuQC.plugin/Contents/Frameworks/\" ~/Library/Frameworks /Library/Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "org.openemu.${PRODUCT_NAME:identifier}";
PRODUCT_NAME = Atari800;
SKIP_INSTALL = YES;
WRAPPER_EXTENSION = oecoreplugin;
@@ -628,6 +684,7 @@
INFOPLIST_FILE = "Atari800Core/Atari800-Info.plist";
INSTALL_PATH = "\"$(USER_LIBRARY_DIR)/Application Support/OpenEmu/Cores\"";
LD_RUNPATH_SEARCH_PATHS = "\"/Library/Graphics/Quartz Composer Plug-Ins/OpenEmuQC.plugin/Contents/Frameworks/\" \"~/Library/Graphics/Quartz Composer Plug-Ins/OpenEmuQC.plugin/Contents/Frameworks/\" ~/Library/Frameworks /Library/Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "org.openemu.${PRODUCT_NAME:identifier}";
PRODUCT_NAME = Atari800;
SKIP_INSTALL = YES;
WRAPPER_EXTENSION = oecoreplugin;
+42 -3
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>3.0.1</string>
<string>3.1.1</string>
<key>NSPrincipalClass</key>
<string>OEGameCoreController</string>
<key>OEGameCoreClass</key>
@@ -42,6 +42,44 @@
</dict>
</array>
</dict>
<key>openemu.system.atari8bit</key>
<dict>
<key>OEGameCoreRequiresFiles</key>
<true/>
<key>OERequiredFiles</key>
<array>
<dict>
<key>Description</key>
<string>Atari XL/XE BASIC rev. C ROM</string>
<key>MD5</key>
<string>0bac0c6a50104045d902df4503a4c30b</string>
<key>Name</key>
<string>ataribas.rom</string>
<key>Size</key>
<integer>8192</integer>
</dict>
<dict>
<key>Description</key>
<string>Atari 400/800 OS rev. B ROM (known incorrect dump)</string>
<key>MD5</key>
<string>a3e8d617c95d08031fe1b20d541434b2</string>
<key>Name</key>
<string>atariosb.rom</string>
<key>Size</key>
<integer>10240</integer>
</dict>
<dict>
<key>Description</key>
<string>Atari XL/XE OS rev. 2 ROM</string>
<key>MD5</key>
<string>06daac977823773a3eea3422fd26a703</string>
<key>Name</key>
<string>atarixl.rom</string>
<key>Size</key>
<integer>16384</integer>
</dict>
</array>
</dict>
</dict>
<key>OEGameCorePlayerCount</key>
<string>1</string>
@@ -50,6 +88,7 @@
<key>OESystemIdentifiers</key>
<array>
<string>openemu.system.5200</string>
<string>openemu.system.atari8bit</string>
</array>
<key>SUEnableAutomaticChecks</key>
<string>1</string>
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -234,8 +234,8 @@ int AFILE_OpenFile(const char *filename, int reboot, int diskno, int readonly)
#else
if (!StateSav_ReadAtariState(filename, "rb"))
return AFILE_ERROR;
/* Don't press Option */
GTIA_consol_table[1] = GTIA_consol_table[2] = 0xf;
/* Don't press Start nor Option */
GTIA_consol_override = 0;
break;
#endif
default:
+3
View File
@@ -35,6 +35,9 @@
#define AKEY_CX85_DELETE -29
#define AKEY_CX85_YES -30
#define AKEY_TURBO -31
#ifdef USE_UI_BASIC_ONSCREEN_KEYBOARD
#define AKEY_KEYB -32
#endif
#ifdef DIRECTX
/* special menu directives */
#define AKEY32_MENU_SAVE_CONFIG -107
+34 -129
View File
@@ -65,23 +65,10 @@ static UBYTE delayed_DMACTL;
static int draw_antic_ptr_changed = 0;
static UBYTE need_load;
static int dmactl_bug_chdata;
#ifndef NO_GTIA11_DELAY
/* the position in the ring buffer where the last change before */
/* the previous line occurred to PRIOR */
static int prevline_prior_pos = 0;
/* the position in the ring buffer where the last change before */
/* the current line occurred to PRIOR */
static int curline_prior_pos = 0;
/* the current position in the ring buffer where the most recent */
/* change to PRIOR occurred */
int ANTIC_prior_curpos = 0;
/* ring buffer to hold the previous values of PRIOR */
UBYTE ANTIC_prior_val_buf[ANTIC_PRIOR_BUF_SIZE];
/* can be negative, leave as signed ints */
/* ring buffer to hold the positions where PRIOR changed */
int ANTIC_prior_pos_buf[ANTIC_PRIOR_BUF_SIZE];
#endif /* NO_GTIA11_DELAY */
#endif /* NEW_CYCLE_EXACT */
#ifndef NO_SIMPLE_PAL_BLENDING
int ANTIC_pal_blending = 0;
#endif /* NO_SIMPLE_PAL_BLENDING */
/* Video memory access is hidden behind these macros. It allows to track dirty video memory
to improve video system performance */
@@ -2875,17 +2862,6 @@ void ANTIC_Frame(int draw_display)
#ifdef NEW_CYCLE_EXACT
int cpu2antic_index;
#endif /* NEW_CYCLE_EXACT */
#ifndef NO_GTIA11_DELAY
#ifdef NEW_CYCLE_EXACT
int stop = FALSE;
/* can be negative, leave as signed ints */
int old_curline_prior_pos;
int last_pos;
int change_pos;
#else
int delayed_gtia11 = 250;
#endif /* NEW_CYCLE_EXACT */
#endif /* NO_GTIA11_DELAY */
ANTIC_ypos = 0;
do {
@@ -3159,108 +3135,6 @@ void ANTIC_Frame(int draw_display)
scrn_ptr + x_min[md],
(ULONG *) &GTIA_pm_scanline[x_min[md]]);
#endif /* NEW_CYCLE_EXACT */
#ifndef NO_GTIA11_DELAY
#ifndef NEW_CYCLE_EXACT
if (GTIA_PRIOR >= 0xc0)
delayed_gtia11 = ANTIC_ypos + 1;
else
if (ANTIC_ypos == delayed_gtia11) {
ULONG *ptr = (ULONG *) (scrn_ptr + 4 * LCHOP);
int k = 2 * (48 - LCHOP - RCHOP);
do {
WRITE_VIDEO_LONG(ptr, READ_VIDEO_LONG(ptr) | READ_VIDEO_LONG(ptr - Screen_WIDTH / 4));
ptr++;
} while (--k);
}
#else /* NEW_CYCLE_EXACT defined */
/* Basic explaination: */
/* the ring buffer ANTIC_prior_pos_buf has three pointers: */
/* A B C D E F G */
/* ^ ^ ^ */
/* prevline_prior_pos curline_prior_pos ANTIC_prior_curpos */
/* G would be the most recent change which occurred during drawing */
/* of the current line, D is the most recent */
/* change before the current line was drawn, and A is the most recent */
/* change before the previous line was drawn */
/* curline_prior_pos is saved in old_curline_prior_pos */
/* then the code will increase either curline_prior_pos or */
/* prevline_prior_pos depending if the change at B or E occurred */
/* earlier in the scanline ignoring which scanline it was */
/* eg: */
/* A occurs on some previous scanline */
/* prev: B C D */
/* current: E F G */
/* so from the left end of the screen, the changes occurred in the order */
/* B,E,C,F,D,G */
/* then the code will read the values in that order, and each time it will */
/* update prev_prior_val and cur_prior_val to be equal the the PRIOR values */
/* "in effect" *before* those changes occurred. If those PRIOR values */
/* should cause a GTIA11_DELAY effect to occur then this is processed */
/* for that portion of the scanline */
/* At the end of processing, the buffer would look like: */
/* the ring buffer ANTIC_prior_pos_buf has three pointers: */
/* A B C D E F G */
/* ^ ^ */
/* prevline_prior_pos curline_prior_pos==ANTIC_prior_curpos */
stop = FALSE;
last_pos = LBORDER_START;
old_curline_prior_pos = curline_prior_pos;
do {
UBYTE prev_prior_val;
UBYTE cur_prior_val;
prev_prior_val = ANTIC_prior_val_buf[prevline_prior_pos];
cur_prior_val = ANTIC_prior_val_buf[curline_prior_pos];
if (prevline_prior_pos == old_curline_prior_pos &&
curline_prior_pos == ANTIC_prior_curpos) {
/* no more changes */
change_pos = RBORDER_END;
stop = TRUE;
}
else if (prevline_prior_pos != old_curline_prior_pos &&
curline_prior_pos != ANTIC_prior_curpos) {
/* find leftmost change */
int pnext = (prevline_prior_pos + 1) % ANTIC_PRIOR_BUF_SIZE;
int cnext = (curline_prior_pos + 1) % ANTIC_PRIOR_BUF_SIZE;
if (ANTIC_prior_pos_buf[pnext] < ANTIC_prior_pos_buf[cnext]) {
change_pos = ANTIC_prior_pos_buf[pnext];
prevline_prior_pos = pnext;
}
else {
change_pos = ANTIC_prior_pos_buf[cnext];
curline_prior_pos = cnext;
}
}
else if (prevline_prior_pos != old_curline_prior_pos) {
/* only have prevline change */
prevline_prior_pos = (prevline_prior_pos + 1) % ANTIC_PRIOR_BUF_SIZE;
change_pos = ANTIC_prior_pos_buf[prevline_prior_pos];
}
else {
/* must only have curline change */
curline_prior_pos = (curline_prior_pos + 1) % ANTIC_PRIOR_BUF_SIZE;
change_pos = ANTIC_prior_pos_buf[curline_prior_pos];
}
if (prev_prior_val >= 0xc0 && cur_prior_val < 0xc0 &&
change_pos > LBORDER_START &&
change_pos > last_pos && last_pos < RBORDER_END) {
int adj_change_pos = (change_pos > RBORDER_END) ? RBORDER_END : change_pos;
UWORD *ptr = (scrn_ptr + last_pos);
int k = adj_change_pos - last_pos;
do {
WRITE_VIDEO(ptr, *ptr | *(ptr - Screen_WIDTH / 2));
ptr++;
} while (--k);
}
last_pos = (change_pos > last_pos) ? change_pos: last_pos;
} while (!stop);
#endif /* NEW_CYCLE_EXACT */
#endif /* NO_GTIA11_DELAY */
#ifndef NEW_CYCLE_EXACT
GOEOL;
#endif /* NEW_CYCLE_EXACT */
YPOS_BREAK_FLICKER;
@@ -3269,6 +3143,37 @@ void ANTIC_Frame(int draw_display)
dctr &= 0xf;
} while (ANTIC_ypos < (Screen_HEIGHT + 8));
#ifndef NO_SIMPLE_PAL_BLENDING
/* Simple PAL blending, using only the base 256 color palette. */
if (ANTIC_pal_blending)
{
int ypos = ANTIC_ypos - 1;
/* Start at the last screen line (248). */
ULONG *ptr = (ULONG *) (scrn_ptr - 4 * RCHOP);
do {
int k = 2 * (48 - LCHOP - RCHOP);
do {
/* For each grayscale pixel (colors $00..$0f) blend it with
chrominance of a pixel from the previous line. */
ULONG pix = READ_VIDEO_LONG(--ptr);
ULONG mask = 0xf0f0f0f0;
/* Take advantage of the fact that chrominance can change only
every two pixels. This way we may test only two pixels in a
quadruplet instead of four. */
if (pix & 0x0000f0f0)
/* Two LSBs are non-grayscale */
mask &= 0xf0f00000;
if (pix & 0xf0f00000)
/* Two MSBs are non-grayscale */
mask &= 0x0000f0f0;
WRITE_VIDEO_LONG(ptr, (READ_VIDEO_LONG(ptr - Screen_WIDTH / 4) & mask) | pix);
} while (--k);
ptr -= 2 * (LCHOP + RCHOP); /* Move one line up */
} while (--ypos > 8); /* Stop after line 9 */
}
#endif /* NO_SIMPLE_PAL_BLENDING */
/* TODO: cycle-exact overscreen lines */
POKEY_Scanline(); /* check and generate IRQ */
CPU_GO(ANTIC_NMIST_C);
+6 -6
View File
@@ -122,16 +122,16 @@ extern const int *ANTIC_cpu2antic_ptr;
extern const int *ANTIC_antic2cpu_ptr;
void ANTIC_UpdateScanline(void);
void ANTIC_UpdateScanlinePrior(UBYTE byte);
#ifndef NO_GTIA11_DELAY
extern int ANTIC_prior_curpos;
#define ANTIC_PRIOR_BUF_SIZE 40
extern UBYTE ANTIC_prior_val_buf[ANTIC_PRIOR_BUF_SIZE];
extern int ANTIC_prior_pos_buf[ANTIC_PRIOR_BUF_SIZE];
#endif /* NO_GTIA11_DELAY */
#define ANTIC_XPOS ( ANTIC_DRAWING_SCREEN ? ANTIC_cpu2antic_ptr[ANTIC_xpos] : ANTIC_xpos )
#else
#define ANTIC_XPOS ANTIC_xpos
#endif /* NEW_CYCLE_EXACT */
#ifndef NO_SIMPLE_PAL_BLENDING
/* Set to 1 to enable simplified emulation of PAL blending, that uses only
the standard 8-bit palette. */
extern int ANTIC_pal_blending;
#endif /* NO_SIMPLE_PAL_BLENDING */
#endif /* ANTIC_H_ */
+217
View File
@@ -0,0 +1,217 @@
/*
* artifact.c - management of video artifacting settings
*
* Copyright (C) 2013 Tomasz Krasuski
* Copyright (C) 2013 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
* Atari800 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Atari800 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 General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with Atari800; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <string.h>
#include "artifact.h"
#include "antic.h"
#include "atari.h"
#include "cfg.h"
#include "log.h"
#ifdef PAL_BLENDING
#include "pal_blending.h"
#endif /* PAL_BLENDING */
#include "util.h"
#if SUPPORTS_CHANGE_VIDEOMODE
#include "videomode.h"
#endif /* SUPPORTS_CHANGE_VIDEOMODE */
ARTIFACT_t ARTIFACT_mode = ARTIFACT_NONE;
static ARTIFACT_t mode_ntsc = ARTIFACT_NONE;
static ARTIFACT_t mode_pal = ARTIFACT_NONE;
static char const * const mode_cfg_strings[ARTIFACT_SIZE] = {
"NONE",
"NTSC-OLD",
"NTSC-NEW",
#if NTSC_FILTER
"NTSC-FULL",
#endif /* NTSC_FILTER */
#ifndef NO_SIMPLE_PAL_BLENDING
"PAL-SIMPLE",
#endif /* NO_SIMPLE_PAL_BLENDING */
#ifdef PAL_BLENDING
"PAL-BLEND"
#endif /* PAL_BLENDING */
};
static void UpdateMode(int old_mode, int reinit)
{
#if (NTSC_FILTER && SUPPORTS_CHANGE_VIDEOMODE) || defined(PAL_BLENDING)
int need_reinit = FALSE;
#endif /* (NTSC_FILTER && SUPPORTS_CHANGE_VIDEOMODE) || defined(PAL_BLENDING) */
if (ARTIFACT_mode == old_mode)
return;
/* TV effect has changed. */
#if NTSC_FILTER && SUPPORTS_CHANGE_VIDEOMODE
/* If switched between non-filter and NTSC filter, video mode needs update. */
if (ARTIFACT_mode == ARTIFACT_NTSC_FULL ||
old_mode == ARTIFACT_NTSC_FULL)
need_reinit = TRUE;
#endif /* NTSC_FILTER && SUPPORTS_CHANGE_VIDEOMODE */
#ifdef PAL_BLENDING
/* If PAL blending was enabled/disabled, video mode needs update. */
if (ARTIFACT_mode == ARTIFACT_PAL_BLEND ||
old_mode == ARTIFACT_PAL_BLEND)
need_reinit = TRUE;
#endif /* PAL_BLENDING */
#ifndef NO_SIMPLE_PAL_BLENDING
ANTIC_pal_blending = ARTIFACT_mode == ARTIFACT_PAL_SIMPLE;
#endif /* NO_SIMPLE_PAL_BLENDING */
if (ARTIFACT_mode != ARTIFACT_NTSC_OLD &&
ARTIFACT_mode != ARTIFACT_NTSC_NEW) {
ANTIC_artif_new = ANTIC_artif_mode = 0;
} else {
if (ANTIC_artif_mode == 0)
/* ANTIC new or old artifacting is being enabled */
ANTIC_artif_mode = 1;
ANTIC_artif_new = ARTIFACT_mode == ARTIFACT_NTSC_NEW;
}
ANTIC_UpdateArtifacting();
#if SUPPORTS_CHANGE_VIDEOMODE
if (need_reinit && reinit) {
if (!VIDEOMODE_Update()) {
ARTIFACT_t tmp = ARTIFACT_mode;
/* Updating display failed, restore previous setting. */
ARTIFACT_mode = old_mode;
UpdateMode(tmp, FALSE);
}
}
#endif /* SUPPORTS_CHANGE_VIDEOMODE */
}
static void UpdateFromTVMode(int tv_mode)
{
if (tv_mode == Atari800_TV_NTSC)
ARTIFACT_mode = mode_ntsc;
else /* tv_mode == Atari800_TV_PAL */
ARTIFACT_mode = mode_pal;
}
void ARTIFACT_Set(ARTIFACT_t mode)
{
ARTIFACT_t old_effect = ARTIFACT_mode;
ARTIFACT_mode = mode;
if (Atari800_tv_mode == Atari800_TV_NTSC)
mode_ntsc = mode;
else /* Atari800_tv_mode == Atari800_TV_PAL */
mode_pal = mode;
UpdateMode(old_effect, TRUE);
}
void ARTIFACT_SetTVMode(int tv_mode)
{
ARTIFACT_t old_mode = ARTIFACT_mode;
UpdateFromTVMode(tv_mode);
UpdateMode(old_mode, TRUE);
}
int ARTIFACT_ReadConfig(char *option, char *ptr)
{
if (strcmp(option, "ARTIFACT_NTSC") == 0) {
int i = CFG_MatchTextParameter(ptr, mode_cfg_strings, ARTIFACT_SIZE);
if (i < 0)
return FALSE;
mode_ntsc = i;
}
else if (strcmp(option, "ARTIFACT_PAL") == 0) {
int i = CFG_MatchTextParameter(ptr, mode_cfg_strings, ARTIFACT_SIZE);
if (i < 0)
return FALSE;
mode_pal = i;
}
else if (strcmp(option, "ARTIFACT_NTSC_MODE") == 0) {
int i = Util_sscandec(ptr);
if (i < 0 || i > 4)
return FALSE;
ANTIC_artif_mode = i;
}
else
return FALSE;
return TRUE;
}
void ARTIFACT_WriteConfig(FILE *fp)
{
fprintf(fp, "ARTIFACT_NTSC=%s\n", mode_cfg_strings[mode_ntsc]);
fprintf(fp, "ARTIFACT_PAL=%s\n", mode_cfg_strings[mode_pal]);
fprintf(fp, "ARTIFACT_NTSC_MODE=%i\n", ANTIC_artif_mode);
}
int ARTIFACT_Initialise(int *argc, char *argv[])
{
int i;
int j;
for (i = j = 1; i < *argc; i++) {
int i_a = (i + 1 < *argc); /* is argument available? */
int a_m = FALSE; /* error, argument missing! */
if (strcmp(argv[i], "-ntsc-artif") == 0) {
if (i_a) {
int idx = CFG_MatchTextParameter(argv[++i], mode_cfg_strings, ARTIFACT_SIZE);
if (idx < 0) {
Log_print("Invalid value for -ntsc-artif");
return FALSE;
}
mode_ntsc = idx;
} else a_m = TRUE;
}
else if (strcmp(argv[i], "-pal-artif") == 0) {
if (i_a) {
int idx = CFG_MatchTextParameter(argv[++i], mode_cfg_strings, ARTIFACT_SIZE);
if (idx < 0) {
Log_print("Invalid value for -pal-artif");
return FALSE;
}
mode_pal = idx;
} else a_m = TRUE;
}
else {
if (strcmp(argv[i], "-help") == 0) {
Log_print("\t-ntsc-artif none|ntsc-old|ntsc-new|ntsc-full");
Log_print("\t Select video artifacts for NTSC");
Log_print("\t-pal-artif none|pal-simple|pal-accu");
Log_print("\t Select video artifacts for PAL");
}
argv[j++] = argv[i];
}
if (a_m) {
Log_print("Missing argument for '%s'", argv[i]);
return FALSE;
}
}
*argc = j;
/* Assume that Atari800_tv_mode has been already initialised. */
UpdateFromTVMode(Atari800_tv_mode);
UpdateMode(ARTIFACT_NONE, FALSE);
return TRUE;
}
+40
View File
@@ -0,0 +1,40 @@
#ifndef ARTIFACT_H_
#define ARTIFACT_H_
#include <stdio.h>
#include "config.h"
typedef enum ARTIFACT_t {
ARTIFACT_NONE, /* Artifacting disabled */
ARTIFACT_NTSC_OLD, /* Original NTSC artifacting */
ARTIFACT_NTSC_NEW, /* New NTSC artifacting */
#if NTSC_FILTER
ARTIFACT_NTSC_FULL, /* NTSC filter */
#endif /* NTSC_FILTER */
#ifndef NO_SIMPLE_PAL_BLENDING
ARTIFACT_PAL_SIMPLE, /* ANTIC-level simple PAL blending */
#endif /* NO_SIMPLE_PAL_BLENDING */
#ifdef PAL_BLENDING
ARTIFACT_PAL_BLEND, /* Accurate PAL blending */
#endif /* PAL_BLENDING */
ARTIFACT_SIZE
} ARTIFACT_t;
/* The currently used artifact emulation mode. Use ARTIFACT_Set to change this value. */
extern ARTIFACT_t ARTIFACT_mode;
/* Set artifacting mode for the current TV system. */
void ARTIFACT_Set(ARTIFACT_t mode);
/* Call after updating Atari800_tv_mode to update the artifacting mode accordingly. */
void ARTIFACT_SetTVMode(int tv_mode);
/* Read/write to configuration file. */
void ARTIFACT_WriteConfig(FILE *fp);
int ARTIFACT_ReadConfig(char *option, char *ptr);
/* Module initialisation and processing of command-line arguments. */
int ARTIFACT_Initialise(int *argc, char *argv[]);
#endif /* ARTIFACT_H_ */
+55 -114
View File
@@ -2,7 +2,7 @@
* atari.c - main high-level routines
*
* Copyright (c) 1995-1998 David Firth
* Copyright (c) 1998-2008 Atari800 development team (see DOC/CREDITS)
* Copyright (c) 1998-2014 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
@@ -32,16 +32,6 @@
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# elif defined(HAVE_TIME_H)
# include <time.h>
# endif
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -67,6 +57,7 @@
#include "akey.h"
#include "antic.h"
#include "artifact.h"
#include "atari.h"
#include "binload.h"
#include "cartridge.h"
@@ -177,7 +168,6 @@ int Atari800_auto_frameskip = FALSE;
#ifdef BENCHMARK
static double benchmark_start_time;
static double Atari_time(void);
#endif
int emuos_mode = 1; /* 0 = never use EmuOS, 1 = use EmuOS if real OS not available, 2 = always use EmuOS */
@@ -264,17 +254,7 @@ void Atari800_Coldstart(void)
MEMORY_dPutByte(0x244, 1);
/* handle Option key (disable BASIC in XL/XE)
and Start key (boot from cassette) */
GTIA_consol_index = 2;
GTIA_consol_table[2] = 0x0f;
if (Atari800_builtin_basic && Atari800_disable_basic && !BINLOAD_loading_basic) {
/* Only for XL/XE - hold Option during reboot. */
GTIA_consol_table[2] &= ~INPUT_CONSOL_OPTION;
}
if (CASSETTE_hold_start && Atari800_machine_type != Atari800_MACHINE_5200) {
/* Only for the computers - hold Start during reboot */
GTIA_consol_table[2] &= ~INPUT_CONSOL_START;
}
GTIA_consol_table[1] = GTIA_consol_table[2];
GTIA_consol_override = 2;
#ifdef AF80
if (AF80_enabled) {
AF80_Reset();
@@ -735,6 +715,7 @@ int Atari800_Initialise(int *argc, char *argv[])
if (!SYSROM_Initialise(argc, argv)
#if !defined(BASIC) && !defined(CURSES_BASIC)
|| !Colours_Initialise(argc, argv)
|| !ARTIFACT_Initialise(argc, argv)
#endif
|| !Devices_Initialise(argc, argv)
|| !RTIME_Initialise(argc, argv)
@@ -870,8 +851,8 @@ int Atari800_Initialise(int *argc, char *argv[])
/* Load state file */
if (state_file != NULL) {
if (StateSav_ReadAtariState(state_file, "rb"))
/* Don't press Option */
GTIA_consol_table[1] = GTIA_consol_table[2] = 0x0f;
/* Don't press Start nor Option */
GTIA_consol_override = 0;
}
#endif
@@ -891,8 +872,25 @@ int Atari800_Initialise(int *argc, char *argv[])
#endif /* __PLUS */
#ifdef BENCHMARK
benchmark_start_time = Atari_time();
benchmark_start_time = Util_time();
#endif
#if defined (SOUND) && defined(SOUND_THIN_API)
if (Sound_enabled) {
/* Up to this point the Sound_enabled flag indicated that we _want_ to
enable sound. From now on, the flag will indicate whether audio
output is enabled and working. So, since the sound output was not
yet initiated, we set the flag accordingly. */
Sound_enabled = FALSE;
/* Don't worry, Sound_Setup() will set Sound_enabled back to TRUE if
it opens audio output successfully. But Sound_Setup() relies on the
flag being set if and only if audio output is active. */
if (Sound_Setup())
/* Start sound if opening audio output was successful. */
Sound_Continue();
}
#endif /* defined (SOUND) && defined(SOUND_THIN_API) */
return TRUE;
}
@@ -948,6 +946,9 @@ int Atari800_Exit(int run_monitor)
/* Cleanup functions, in reverse order as the init functions in
Atari800_Initialise(). */
#ifdef SOUND
Sound_Exit();
#endif
#if SUPPORTS_CHANGE_VIDEOMODE
VIDEOMODE_Exit();
#endif
@@ -987,80 +988,6 @@ void Atari800_ErrExit(void)
}
#ifndef __PLUS
#ifdef PS2
double Atari_time(void);
void Atari_sleep(double s);
#else /* PS2 */
static double Atari_time(void)
{
#ifdef SDL
return SDL_GetTicks() * 1e-3;
#elif defined(HAVE_WINDOWS_H)
return GetTickCount() * 1e-3;
#elif defined(DJGPP)
/* DJGPP has gettimeofday, but it's not more accurate than uclock */
return uclock() * (1.0 / UCLOCKS_PER_SEC);
#elif defined(HAVE_GETTIMEOFDAY)
struct timeval tp;
gettimeofday(&tp, NULL);
return tp.tv_sec + 1e-6 * tp.tv_usec;
#elif defined(HAVE_UCLOCK)
return uclock() * (1.0 / UCLOCKS_PER_SEC);
#elif defined(HAVE_CLOCK)
return clock() * (1.0 / CLK_TCK);
#else
#error No function found for Atari_time()
#endif
}
/* FIXME: Ports should use SUPPORTS_PLATFORM_SLEEP and SUPPORTS_PLATFORM_TIME */
/* and not this mess */
#ifndef SUPPORTS_PLATFORM_SLEEP
static void Atari_sleep(double s)
{
if (s > 0) {
#ifdef HAVE_WINDOWS_H
Sleep((DWORD) (s * 1e3));
#elif defined(DJGPP)
/* DJGPP has usleep and select, but they don't work that good */
/* XXX: find out why */
double curtime = Atari_time();
while ((curtime + s) > Atari_time());
#elif defined(HAVE_NANOSLEEP)
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = s * 1e9;
nanosleep(&ts, NULL);
#elif defined(HAVE_USLEEP)
usleep(s * 1e6);
#elif defined(__BEOS__)
/* added by Walter Las for BeOS */
snooze(s * 1e6);
#elif defined(__EMX__)
/* added by Brian Smith for os/2 */
DosSleep(s);
#elif defined(HAVE_SELECT)
/* linux */
struct timeval tp;
tp.tv_sec = 0;
tp.tv_usec = s * 1e6;
select(1, NULL, NULL, NULL, &tp);
#else
double curtime = Atari_time();
while ((curtime + s) > Atari_time());
#endif
}
}
#endif /* SUPPORTS_PLATFORM_SLEEP */
#endif /* PS2 */
static void autoframeskip(double curtime, double lasttime)
{
static int afs_lastframe = 0, afs_discard = 0;
@@ -1091,7 +1018,7 @@ static void autoframeskip(double curtime, double lasttime)
afs_sleeptime = 0.0;
afs_lastframe = Atari800_nframes;
afs_lasttime = Atari_time();
afs_lasttime = Util_time();
}
}
@@ -1102,22 +1029,18 @@ void Atari800_Sync(void)
double curtime;
#ifdef SYNCHRONIZED_SOUND
deltatime *= PLATFORM_AdjustSpeed();
deltatime *= Sound_AdjustSpeed();
#endif
#ifdef ALTERNATE_SYNC_WITH_HOST
if (! UI_is_active)
deltatime *= Atari800_refresh_rate;
#endif
lasttime += deltatime;
curtime = Atari_time();
curtime = Util_time();
if (Atari800_auto_frameskip)
autoframeskip(curtime, lasttime);
#ifdef SUPPORTS_PLATFORM_SLEEP
PLATFORM_Sleep(lasttime - curtime);
#else
Atari_sleep(lasttime - curtime);
#endif
curtime = Atari_time();
Util_sleep(lasttime - curtime);
curtime = Util_time();
if ((lasttime + deltatime) < curtime)
lasttime = curtime;
@@ -1352,7 +1275,7 @@ void Atari800_Frame(void)
#else
ANTIC_Frame(TRUE);
INPUT_DrawMousePointer();
Screen_DrawAtariSpeed(Atari_time());
Screen_DrawAtariSpeed(Util_time());
Screen_DrawDiskLED();
Screen_Draw1200LED();
#endif /* CURSES_BASIC */
@@ -1378,7 +1301,7 @@ void Atari800_Frame(void)
Atari800_nframes++;
#ifdef BENCHMARK
if (Atari800_nframes >= BENCHMARK) {
double benchmark_time = Atari_time() - benchmark_start_time;
double benchmark_time = Util_time() - benchmark_start_time;
Atari800_ErrExit();
printf("%d frames emulated in %.2f seconds\n", BENCHMARK, benchmark_time);
exit(0);
@@ -1388,7 +1311,20 @@ void Atari800_Frame(void)
#ifdef ALTERNATE_SYNC_WITH_HOST
if (refresh_counter == 0)
#endif
if (Atari800_turbo == FALSE) Atari800_Sync();
if (Atari800_turbo) {
/* No need to draw Atari frames with frequency higher than display
refresh rate. */
static double last_display_screen_time = 0.0;
static double const limit = 1.0 / 60.0; /* refresh every 1/60 s */
/* TODO Actually sync the limit with the display refresh rate. */
double cur_time = Util_time();
if (cur_time - last_display_screen_time > limit)
last_display_screen_time = cur_time;
else
Atari800_display_screen = FALSE;
}
else
Atari800_Sync();
#endif /* BENCHMARK */
}
@@ -1527,13 +1463,18 @@ void Atari800_SetTVMode(int mode)
Atari800_tv_mode = mode;
#if !defined(BASIC) && !defined(CURSES_BASIC)
Colours_SetVideoSystem(mode);
ARTIFACT_SetTVMode(mode);
#endif
#if SUPPORTS_CHANGE_VIDEOMODE
VIDEOMODE_SetVideoSystem(mode);
#endif
#if defined(SOUND) && defined(SUPPORTS_SOUND_REINIT)
#ifdef SOUND
#ifdef SOUND_THIN_API
POKEYSND_Init(POKEYSND_FREQ_17_EXACT, Sound_out.freq, Sound_out.channels, Sound_out.sample_size == 2 ? POKEYSND_BIT16 : 0);
#elif defined(SUPPORTS_SOUND_REINIT)
Sound_Reinit();
#endif
#endif /* defined(SUPPORTS_SOUND_REINIT) */
#endif /* SOUND */
#if defined(DIRECTX)
SetTVModeMenuItem(mode);
#endif
+1 -1
View File
@@ -9,7 +9,7 @@
/* Fundamental declarations ---------------------------------------------- */
#define Atari800_TITLE "Atari 800 Emulator, Version 3.0.0"
#define Atari800_TITLE "Atari 800 Emulator, Version 3.1.0"
#ifndef FALSE
#define FALSE 0
+1 -5
View File
@@ -2,7 +2,7 @@
* atari_basic.c - Text-only specific port code
*
* Copyright (c) 1995-1998 David Firth
* Copyright (c) 1998-2005 Atari800 development team (see DOC/CREDITS)
* Copyright (c) 1998-2014 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
@@ -48,10 +48,6 @@ int PLATFORM_Exit(int run_monitor)
if (run_monitor && MONITOR_Run())
return TRUE;
#ifdef SOUND
Sound_Exit();
#endif
return FALSE;
}
+1 -4
View File
@@ -2,7 +2,7 @@
* atari_curses.c - Curses based port code
*
* Copyright (c) 1995-1998 David Firth
* Copyright (c) 1998-2005 Atari800 development team (see DOC/CREDITS)
* Copyright (c) 1998-2014 Atari800 development team (see DOC/CREDITS)
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
@@ -110,9 +110,6 @@ int PLATFORM_Exit(int run_monitor)
curs_set(0);
return TRUE;
}
#ifdef SOUND
Sound_Exit();
#endif
return FALSE;
}
+1 -5
View File
@@ -2,7 +2,7 @@
* atari_falcon.c - Atari Falcon specific port code
*
* Copyright (c) 1997-1998 Petr Stehlik and Karel Rous
* Copyright (c) 1998-2005 Atari800 development team (see DOC/CREDITS)
* Copyright (c) 1998-2014 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
@@ -469,10 +469,6 @@ int PLATFORM_Exit(int run_monitor)
}
}
#ifdef SOUND
Sound_Exit();
#endif
if (new_videoram)
free(new_videoram);
+12 -7
View File
@@ -2,7 +2,7 @@
* atari_ps2.c - Sony PlayStation 2 port code
*
* Copyright (c) 2005 Troy Ayers and Piotr Fusik
* Copyright (c) 2005 Atari800 development team (see DOC/CREDITS)
* Copyright (c) 2005-2014 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
@@ -91,7 +91,7 @@ static char padBuf[256] __attribute__((aligned(64)));
#ifdef USE_TIMERS
/* We use T0 for Atari_time() and T1 for Atari_sleep().
/* We use T0 for PLATFORM_Time() and T1 for PLATFORM_Sleep().
Note that both timers are just 16-bit. */
#define T0_COUNT (*(volatile unsigned long *) 0x10000000)
@@ -162,7 +162,7 @@ static void timer_shutdown(void)
#endif /* USE_TIMERS */
double Atari_time(void)
double PLATFORM_Time(void)
{
#ifdef USE_TIMERS
/* AFAIK, multiplication is faster than division,
@@ -174,10 +174,10 @@ double Atari_time(void)
#endif
}
/* this Atari_sleep() supports times only up to 0.11 sec,
/* this PLATFORM_Sleep() supports times only up to 0.11 sec,
which is enough for Atari800 purposes */
/* void Atari_sleep(double s)
/* void PLATFORM_Sleep(double s)
{
#ifdef USE_TIMERS
unsigned long count = 65536 - (unsigned long) (s * 576000);
@@ -200,7 +200,7 @@ double Atari_time(void)
// locked = 0;
//}
//
//void Atari_sleep(double s)
//void PLATFORM_Sleep(double s)
//{
//
// /* 15734 is around 1 second on NTSC */
@@ -209,7 +209,7 @@ double Atari_time(void)
// while (locked);
// locked = 1;
//}
void Atari_sleep(double s)
void PLATFORM_Sleep(double s)
{
if (UI_is_active){
@@ -327,6 +327,11 @@ int PLATFORM_Exit(int run_monitor)
#ifdef USE_TIMERS
timer_shutdown();
#endif
/* TODO Sound_Exit should not be called here! It only stays here now because
the next step restarts the PS2 without ever returning from this function to
Atari800_Exit, so the call to Sound_Exit located in the latter function is
never invoked. So, should the LoadExecPS2call below get removed, so should
this call to Sound_Exit. */
#ifdef SOUND
Sound_Exit();
#endif
+3 -6
View File
@@ -2,7 +2,7 @@
* atari_x11.c - X11 specific port code
*
* Copyright (c) 1995-1998 David Firth
* Copyright (C) 1998-2008 Atari800 development team (see DOC/CREDITS)
* Copyright (C) 1998-2014 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
@@ -238,7 +238,7 @@ static void autorepeat_restore(void)
static void segmentationfault(int x)
{
PLATFORM_Exit(0);
Atari800_ErrExit();
exit(0);
}
@@ -959,7 +959,7 @@ static void remove_rom_callback(void)
static void exit_callback(void)
{
PLATFORM_Exit(FALSE);
Atari800_Exit(FALSE);
exit(1);
}
@@ -2356,9 +2356,6 @@ int PLATFORM_Exit(int run_monitor)
close(js1);
#endif
#ifdef SOUND
Sound_Exit();
#endif
}
return restart;
}
+2 -2
View File
@@ -167,13 +167,13 @@ int BINLOAD_Loader(const char *filename)
}
else if (buf[0] == 0 && buf[1] == 0) {
BINLOAD_loading_basic = BINLOAD_LOADING_BASIC_SAVED;
Devices_PatchOS();
ESC_UpdatePatches();
Atari800_Coldstart();
return TRUE;
}
else if (buf[0] >= '0' && buf[0] <= '9') {
BINLOAD_loading_basic = BINLOAD_LOADING_BASIC_LISTED;
Devices_PatchOS();
ESC_UpdatePatches();
Atari800_Coldstart();
return TRUE;
}
+174 -138
View File
@@ -47,129 +47,75 @@
/* #define DEBUG 1 */
int CARTRIDGE_kb[CARTRIDGE_LAST_SUPPORTED + 1] = {
int const CARTRIDGE_kb[CARTRIDGE_LAST_SUPPORTED + 1] = {
0,
8, /* CARTRIDGE_STD_8 */
16, /* CARTRIDGE_STD_16 */
16, /* CARTRIDGE_OSS_034M_16 */
32, /* CARTRIDGE_5200_32 */
32, /* CARTRIDGE_DB_32 */
16, /* CARTRIDGE_5200_EE_16 */
40, /* CARTRIDGE_5200_40 */
64, /* CARTRIDGE_WILL_64 */
64, /* CARTRIDGE_EXP_64 */
64, /* CARTRIDGE_DIAMOND_64 */
64, /* CARTRIDGE_SDX */
32, /* CARTRIDGE_XEGS_32 */
64, /* CARTRIDGE_XEGS_64 */
128, /* CARTRIDGE_XEGS_128 */
16, /* CARTRIDGE_OSS_M091_16 */
16, /* CARTRIDGE_5200_NS_16 */
128, /* CARTRIDGE_ATRAX_128 */
40, /* CARTRIDGE_BBSB_40 */
8, /* CARTRIDGE_5200_8 */
4, /* CARTRIDGE_5200_4 */
8, /* CARTRIDGE_RIGHT_8 */
32, /* CARTRIDGE_WILL_32 */
256, /* CARTRIDGE_XEGS_256 */
512, /* CARTRIDGE_XEGS_512 */
1024, /* CARTRIDGE_XEGS_1024 */
16, /* CARTRIDGE_MEGA_16 */
32, /* CARTRIDGE_MEGA_32 */
64, /* CARTRIDGE_MEGA_64 */
128, /* CARTRIDGE_MEGA_128 */
256, /* CARTRIDGE_MEGA_256 */
512, /* CARTRIDGE_MEGA_512 */
1024, /* CARTRIDGE_MEGA_1024 */
32, /* CARTRIDGE_SWXEGS_32 */
64, /* CARTRIDGE_SWXEGS_64 */
128, /* CARTRIDGE_SWXEGS_128 */
256, /* CARTRIDGE_SWXEGS_256 */
512, /* CARTRIDGE_SWXEGS_512 */
1024, /* CARTRIDGE_SWXEGS_1024 */
8, /* CARTRIDGE_PHOENIX_8 */
16, /* CARTRIDGE_BLIZZARD_16 */
128, /* CARTRIDGE_ATMAX_128 */
1024, /* CARTRIDGE_ATMAX_1024 */
128, /* CARTRIDGE_SDX_128 */
8, /* CARTRIDGE_OSS_8 */
16, /* CARTRIDGE_OSS_043M_16 */
4, /* CARTRIDGE_BLIZZARD_4 */
32, /* CARTRIDGE_AST_32 */
64, /* CARTRIDGE_ATRAX_SDX_64 */
128, /* CARTRIDGE_ATRAX_SDX_128 */
64, /* CARTRIDGE_TURBOSOFT_64 */
128, /* CARTRIDGE_TURBOSOFT_128 */
32, /* CARTRIDGE_ULTRACART_32 */
8, /* CARTRIDGE_LOW_BANK_8 */
128, /* CARTRIDGE_SIC_128 */
256, /* CARTRIDGE_SIC_256 */
512, /* CARTRIDGE_SIC_512 */
2, /* CARTRIDGE_STD_2 */
4, /* CARTRIDGE_STD_4 */
4 /* CARTRIDGE_RIGHT_4 */
};
char *CARTRIDGE_TextDesc[CARTRIDGE_LAST_SUPPORTED + 1] = {
[CARTRIDGE_STD_8] = "Standard 8 KB cartridge",
[CARTRIDGE_STD_16] = "Standard 16 KB cartridge",
[CARTRIDGE_OSS_034M_16] = "OSS two chip 16 KB cartridge (034M)",
[CARTRIDGE_5200_32] = "Standard 32 KB 5200 cartridge",
[CARTRIDGE_DB_32] = "DB 32 KB cartridge",
[CARTRIDGE_5200_EE_16] = "Two chip 16 KB 5200 cartridge",
[CARTRIDGE_5200_40] = "Bounty Bob 40 KB 5200 cartridge",
[CARTRIDGE_WILL_64] = "64 KB Williams cartridge",
[CARTRIDGE_EXP_64] = "Express 64 KB cartridge",
[CARTRIDGE_DIAMOND_64] = "Diamond 64 KB cartridge",
[CARTRIDGE_SDX_64] = "SpartaDOS X 64 KB cartridge",
[CARTRIDGE_XEGS_32] = "XEGS 32 KB cartridge",
[CARTRIDGE_XEGS_64] = "XEGS 64 KB cartridge",
[CARTRIDGE_XEGS_128] = "XEGS 128 KB cartridge",
[CARTRIDGE_OSS_M091_16] = "OSS one chip 16 KB cartridge",
[CARTRIDGE_5200_NS_16] = "One chip 16 KB 5200 cartridge",
[CARTRIDGE_ATRAX_128] = "Atrax 128 KB cartridge",
[CARTRIDGE_BBSB_40] = "Bounty Bob 40 KB cartridge",
[CARTRIDGE_5200_8] = "Standard 8 KB 5200 cartridge",
[CARTRIDGE_5200_4] = "Standard 4 KB 5200 cartridge",
[CARTRIDGE_RIGHT_8] = "Right slot 8 KB cartridge",
[CARTRIDGE_WILL_32] = "32 KB Williams cartridge",
[CARTRIDGE_XEGS_256] = "XEGS 256 KB cartridge",
[CARTRIDGE_XEGS_512] = "XEGS 512 KB cartridge",
[CARTRIDGE_XEGS_1024] = "XEGS 1 MB cartridge",
[CARTRIDGE_MEGA_16] = "MegaCart 16 KB cartridge",
[CARTRIDGE_MEGA_32] = "MegaCart 32 KB cartridge",
[CARTRIDGE_MEGA_64] = "MegaCart 64 KB cartridge",
[CARTRIDGE_MEGA_128] = "MegaCart 128 KB cartridge",
[CARTRIDGE_MEGA_256] = "MegaCart 256 KB cartridge",
[CARTRIDGE_MEGA_512] = "MegaCart 512 KB cartridge",
[CARTRIDGE_MEGA_1024] = "MegaCart 1 MB cartridge",
[CARTRIDGE_SWXEGS_32] = "Switchable XEGS 32 KB cartridge",
[CARTRIDGE_SWXEGS_64] = "Switchable XEGS 64 KB cartridge",
[CARTRIDGE_SWXEGS_128] = "Switchable XEGS 128 KB cartridge",
[CARTRIDGE_SWXEGS_256] = "Switchable XEGS 256 KB cartridge",
[CARTRIDGE_SWXEGS_512] = "Switchable XEGS 512 KB cartridge",
[CARTRIDGE_SWXEGS_1024] = "Switchable XEGS 1 MB cartridge",
[CARTRIDGE_PHOENIX_8] = "Phoenix 8 KB cartridge",
[CARTRIDGE_BLIZZARD_16] = "Blizzard 16 KB cartridge",
[CARTRIDGE_ATMAX_128] = "Atarimax 128 KB Flash cartridge",
[CARTRIDGE_ATMAX_1024] = "Atarimax 1 MB Flash cartridge",
[CARTRIDGE_SDX_128] = "SpartaDOS X 128 KB cartridge",
[CARTRIDGE_OSS_8] = "OSS 8 KB cartridge",
[CARTRIDGE_OSS_043M_16] = "OSS two chip 16 KB cartridge (043M)",
[CARTRIDGE_BLIZZARD_4] = "Blizzard 4 KB cartridge",
[CARTRIDGE_AST_32] = "AST 32 KB cartridge",
[CARTRIDGE_ATRAX_SDX_64] = "Atrax SDX 64 KB cartridge",
[CARTRIDGE_ATRAX_SDX_128] = "Atrax SDX 128 KB cartridge",
[CARTRIDGE_TURBOSOFT_64] = "Turbosoft 64 KB cartridge",
[CARTRIDGE_TURBOSOFT_128] = "Turbosoft 128 KB cartridge",
[CARTRIDGE_ULTRACART_32] = "Ultracart 32 KB cartridge",
[CARTRIDGE_LOW_BANK_8] = "Low bank 8 KB cartridge",
[CARTRIDGE_SIC_128] = "SIC! 128 KB cartridge",
[CARTRIDGE_SIC_256] = "SIC! 256 KB cartridge",
[CARTRIDGE_SIC_512] = "SIC! 512 KB cartridge",
[CARTRIDGE_STD_2] = "Standard 2 KB cartridge",
[CARTRIDGE_STD_4] = "Standard 4 KB cartridge",
[CARTRIDGE_RIGHT_4] = "Right slot 4 KB cartridge"
8, /* CARTRIDGE_STD_8 */
16, /* CARTRIDGE_STD_16 */
16, /* CARTRIDGE_OSS_034M_16 */
32, /* CARTRIDGE_5200_32 */
32, /* CARTRIDGE_DB_32 */
16, /* CARTRIDGE_5200_EE_16 */
40, /* CARTRIDGE_5200_40 */
64, /* CARTRIDGE_WILL_64 */
64, /* CARTRIDGE_EXP_64 */
64, /* CARTRIDGE_DIAMOND_64 */
64, /* CARTRIDGE_SDX_64 */
32, /* CARTRIDGE_XEGS_32 */
64, /* CARTRIDGE_XEGS_64_07 */
128, /* CARTRIDGE_XEGS_128 */
16, /* CARTRIDGE_OSS_M091_16 */
16, /* CARTRIDGE_5200_NS_16 */
128, /* CARTRIDGE_ATRAX_128 */
40, /* CARTRIDGE_BBSB_40 */
8, /* CARTRIDGE_5200_8 */
4, /* CARTRIDGE_5200_4 */
8, /* CARTRIDGE_RIGHT_8 */
32, /* CARTRIDGE_WILL_32 */
256, /* CARTRIDGE_XEGS_256 */
512, /* CARTRIDGE_XEGS_512 */
1024, /* CARTRIDGE_XEGS_1024 */
16, /* CARTRIDGE_MEGA_16 */
32, /* CARTRIDGE_MEGA_32 */
64, /* CARTRIDGE_MEGA_64 */
128, /* CARTRIDGE_MEGA_128 */
256, /* CARTRIDGE_MEGA_256 */
512, /* CARTRIDGE_MEGA_512 */
1024, /* CARTRIDGE_MEGA_1024 */
32, /* CARTRIDGE_SWXEGS_32 */
64, /* CARTRIDGE_SWXEGS_64 */
128, /* CARTRIDGE_SWXEGS_128 */
256, /* CARTRIDGE_SWXEGS_256 */
512, /* CARTRIDGE_SWXEGS_512 */
1024, /* CARTRIDGE_SWXEGS_1024 */
8, /* CARTRIDGE_PHOENIX_8 */
16, /* CARTRIDGE_BLIZZARD_16 */
128, /* CARTRIDGE_ATMAX_128 */
1024, /* CARTRIDGE_ATMAX_1024 */
128, /* CARTRIDGE_SDX_128 */
8, /* CARTRIDGE_OSS_8 */
16, /* CARTRIDGE_OSS_043M_16 */
4, /* CARTRIDGE_BLIZZARD_4 */
32, /* CARTRIDGE_AST_32 */
64, /* CARTRIDGE_ATRAX_SDX_64 */
128, /* CARTRIDGE_ATRAX_SDX_128 */
64, /* CARTRIDGE_TURBOSOFT_64 */
128, /* CARTRIDGE_TURBOSOFT_128 */
32, /* CARTRIDGE_ULTRACART_32 */
8, /* CARTRIDGE_LOW_BANK_8 */
128, /* CARTRIDGE_SIC_128 */
256, /* CARTRIDGE_SIC_256 */
512, /* CARTRIDGE_SIC_512 */
2, /* CARTRIDGE_STD_2 */
4, /* CARTRIDGE_STD_4 */
4, /* CARTRIDGE_RIGHT_4 */
32, /* CARTRIDGE_TURBO_HIT_32 */
2048, /* CARTRIDGE_MEGA_2048 */
128*1024, /* CARTRIDGE_THECART_128M */
4096, /* CARTRIDGE_MEGA_4096 */
2048, /* CARTRIDGE_MEGA_2048 */
32*1024, /* CARTRIDGE_THECART_32M */
64*1024, /* CARTRIDGE_THECART_64M */
64 /* CARTRIDGE_XEGS_64_8F */
};
int CARTRIDGE_autoreboot = TRUE;
@@ -204,7 +150,7 @@ CARTRIDGE_image_t CARTRIDGE_piggyback = { CARTRIDGE_NONE, 0, 0, NULL, "" }; /* P
cartridge is a SpartaDOS X. */
static CARTRIDGE_image_t *active_cart = &CARTRIDGE_main;
/* DB_32, XEGS_32, XEGS_64, XEGS_128, XEGS_256, XEGS_512, XEGS_1024,
/* DB_32, XEGS_32, XEGS_07_64, XEGS_128, XEGS_256, XEGS_512, XEGS_1024,
SWXEGS_32, SWXEGS_64, SWXEGS_128, SWXEGS_256, SWXEGS_512, SWXEGS_1024 */
static void set_bank_809F(int main, int old_state)
{
@@ -221,6 +167,16 @@ static void set_bank_809F(int main, int old_state)
}
}
/* XEGS_8F_64 */
static void set_bank_XEGS_8F_64(void)
{
if (active_cart->state & 0x08)
MEMORY_CopyROM(0x8000, 0x9fff, active_cart->image + (active_cart->state & ~0x08) * 0x2000);
else
/* $8000-$9FFF is left unconnected. */
MEMORY_dFillMem(0x8000, 0xff, 0x2000);
}
/* OSS_034M_16, OSS_043M_16, OSS_M091_16, OSS_8 */
static void set_bank_A0AF(int main, int old_state)
{
@@ -239,18 +195,20 @@ static void set_bank_A0AF(int main, int old_state)
}
/* WILL_64, EXP_64, DIAMOND_64, SDX_64, WILL_32, ATMAX_128, ATMAX_1024,
ATRAX_128, ATRAX_SDX_64, TURBOSOFT_64, TURBOSOFT_128 */
static void set_bank_A0BF(int n)
ATRAX_128, ATRAX_SDX_64, TURBOSOFT_64, TURBOSOFT_128, ULTRACART_32,
TURBO_HIT_32, THECART_128M, THECART_32M, THECART_64M */
static void set_bank_A0BF(int disable_mask, int bank_mask)
{
if (active_cart->state & n)
if (active_cart->state & disable_mask)
MEMORY_CartA0bfDisable();
else {
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0xa000, 0xbfff, active_cart->image + (active_cart->state & (n - 1)) * 0x2000);
MEMORY_CopyROM(0xa000, 0xbfff, active_cart->image + (active_cart->state & bank_mask) * 0x2000);
}
}
/* MEGA_16, MEGA_32, MEGA_64, MEGA_128, MEGA_256, MEGA_512, MEGA_1024 */
/* MEGA_16, MEGA_32, MEGA_64, MEGA_128, MEGA_256, MEGA_512, MEGA_1024,
MEGAMAX_2048, MEGA_2048 */
static void set_bank_80BF(void)
{
if (active_cart->state & 0x80) {
@@ -260,7 +218,7 @@ static void set_bank_80BF(void)
else {
MEMORY_Cart809fEnable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0x8000, 0xbfff, active_cart->image + active_cart->state * 0x4000);
MEMORY_CopyROM(0x8000, 0xbfff, active_cart->image + (active_cart->state & 0x7f) * 0x4000);
}
}
@@ -292,6 +250,19 @@ static void set_bank_SIC(int n)
}
}
/* MEGA_4096 */
static void set_bank_MEGA_4096(void)
{
if (active_cart->state == 0xff) {
MEMORY_Cart809fDisable();
MEMORY_CartA0bfDisable();
}
else {
MEMORY_Cart809fEnable();
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0x8000, 0xbfff, active_cart->image + active_cart->state * 0x4000);
}
}
/* Called on a read or write operation to page $D5. Switches banks or
enables/disables the cartridge pointed to by *active_cart. */
static void SwitchBank(int old_state)
@@ -315,17 +286,20 @@ static void SwitchBank(int old_state)
case CARTRIDGE_SDX_64:
case CARTRIDGE_WILL_32:
case CARTRIDGE_ATRAX_SDX_64:
set_bank_A0BF(8);
set_bank_A0BF(8, 7);
break;
case CARTRIDGE_DB_32:
case CARTRIDGE_XEGS_32:
case CARTRIDGE_SWXEGS_32:
set_bank_809F(0x6000, old_state);
break;
case CARTRIDGE_XEGS_64:
case CARTRIDGE_XEGS_07_64:
case CARTRIDGE_SWXEGS_64:
set_bank_809F(0xe000, old_state);
break;
case CARTRIDGE_XEGS_8F_64:
set_bank_XEGS_8F_64();
break;
case CARTRIDGE_XEGS_128:
case CARTRIDGE_SWXEGS_128:
set_bank_809F(0x1e000, old_state);
@@ -344,12 +318,12 @@ static void SwitchBank(int old_state)
break;
case CARTRIDGE_ATRAX_128:
case CARTRIDGE_ATMAX_1024:
set_bank_A0BF(128);
set_bank_A0BF(0x80, 0x7f);
break;
case CARTRIDGE_ATMAX_128:
case CARTRIDGE_TURBOSOFT_64:
case CARTRIDGE_TURBOSOFT_128:
set_bank_A0BF(16);
set_bank_A0BF(0x10, 0x0f);
break;
case CARTRIDGE_MEGA_16:
case CARTRIDGE_MEGA_32:
@@ -358,6 +332,8 @@ static void SwitchBank(int old_state)
case CARTRIDGE_MEGA_256:
case CARTRIDGE_MEGA_512:
case CARTRIDGE_MEGA_1024:
case CARTRIDGE_MEGA_2048:
case CARTRIDGE_MEGAMAX_2048:
set_bank_80BF();
break;
case CARTRIDGE_PHOENIX_8:
@@ -381,7 +357,8 @@ static void SwitchBank(int old_state)
MEMORY_CartA0bfDisable();
break;
case CARTRIDGE_ULTRACART_32:
set_bank_A0BF(4);
case CARTRIDGE_BLIZZARD_32:
set_bank_A0BF(4, 3);
break;
case CARTRIDGE_SIC_128:
set_bank_SIC(0x07);
@@ -392,6 +369,18 @@ static void SwitchBank(int old_state)
case CARTRIDGE_SIC_512:
set_bank_SIC(0x1f);
break;
case CARTRIDGE_MEGA_4096:
set_bank_MEGA_4096();
break;
case CARTRIDGE_THECART_128M:
set_bank_A0BF(0x4000, 0x3fff);
break;
case CARTRIDGE_THECART_32M:
set_bank_A0BF(0x4000, 0x0fff);
break;
case CARTRIDGE_THECART_64M:
set_bank_A0BF(0x4000, 0x1fff);
break;
}
#if DEBUG
if (old_state != active_cart->state)
@@ -519,6 +508,10 @@ static void MapActiveCart(void)
case CARTRIDGE_TURBOSOFT_64:
case CARTRIDGE_TURBOSOFT_128:
case CARTRIDGE_ULTRACART_32:
case CARTRIDGE_BLIZZARD_32:
case CARTRIDGE_THECART_128M:
case CARTRIDGE_THECART_32M:
case CARTRIDGE_THECART_64M:
MEMORY_Cart809fDisable();
break;
case CARTRIDGE_DB_32:
@@ -529,8 +522,9 @@ static void MapActiveCart(void)
MEMORY_CopyROM(0xa000, 0xbfff, active_cart->image + 0x6000);
}
break;
case CARTRIDGE_XEGS_64:
case CARTRIDGE_XEGS_07_64:
case CARTRIDGE_SWXEGS_64:
case CARTRIDGE_XEGS_8F_64:
if (!(active_cart->state & 0x80)) {
MEMORY_CartA0bfEnable();
MEMORY_CopyROM(0xa000, 0xbfff, active_cart->image + 0xe000);
@@ -634,9 +628,12 @@ static void MapActiveCart(void)
case CARTRIDGE_MEGA_256:
case CARTRIDGE_MEGA_512:
case CARTRIDGE_MEGA_1024:
case CARTRIDGE_MEGA_2048:
case CARTRIDGE_MEGA_4096:
case CARTRIDGE_SIC_128:
case CARTRIDGE_SIC_256:
case CARTRIDGE_SIC_512:
case CARTRIDGE_MEGAMAX_2048:
break;
default:
MEMORY_Cart809fDisable();
@@ -847,6 +844,7 @@ static int access_D5(CARTRIDGE_image_t *cart, UWORD addr, int *state)
new_state = addr & 0x17;
break;
case CARTRIDGE_ATMAX_1024:
case CARTRIDGE_MEGAMAX_2048:
new_state = addr;
break;
case CARTRIDGE_OSS_8:
@@ -866,6 +864,10 @@ static int access_D5(CARTRIDGE_image_t *cart, UWORD addr, int *state)
case CARTRIDGE_ULTRACART_32:
new_state = (old_state + 1) % 5;
break;
case CARTRIDGE_BLIZZARD_32:
if (old_state < 4)
new_state = old_state + 1;
break;
default:
/* Other cartridge types don't support enabling/disabling/banking through page D5. */
return FALSE;
@@ -878,7 +880,7 @@ static int access_D5(CARTRIDGE_image_t *cart, UWORD addr, int *state)
static UBYTE GetByte(CARTRIDGE_image_t *cart, UWORD addr, int no_side_effects)
{
int old_state = cart->state;
int new_state;
int new_state = old_state;
#if DEBUG
if (cart->type > CARTRIDGE_NONE)
@@ -905,10 +907,23 @@ static UBYTE GetByte(CARTRIDGE_image_t *cart, UWORD addr, int no_side_effects)
case CARTRIDGE_SIC_512:
case CARTRIDGE_SIC_256:
case CARTRIDGE_SIC_128:
case CARTRIDGE_MEGA_4096:
/* Only react to access to $D50x/$D51x. */
if ((addr & 0xe0) == 0x00)
return cart->state;
break;
case CARTRIDGE_THECART_128M:
case CARTRIDGE_THECART_32M:
case CARTRIDGE_THECART_64M:
switch (addr) {
case 0xd5a0:
return cart->state & 0x00ff;
case 0xd5a1:
return (cart->state & 0x3f00) >> 8;
case 0xd5a2:
return (~cart->state & 0x4000) >> 14;
}
break;
}
return 0xff;
}
@@ -917,7 +932,7 @@ static UBYTE GetByte(CARTRIDGE_image_t *cart, UWORD addr, int no_side_effects)
static void PutByte(CARTRIDGE_image_t *cart, UWORD addr, UBYTE byte)
{
int old_state = cart->state;
int new_state;
int new_state = old_state;
#if DEBUG
if (cart->type > CARTRIDGE_NONE)
@@ -928,10 +943,11 @@ static void PutByte(CARTRIDGE_image_t *cart, UWORD addr, UBYTE byte)
case CARTRIDGE_XEGS_32:
new_state = byte & 0x03;
break;
case CARTRIDGE_XEGS_64:
case CARTRIDGE_XEGS_07_64:
new_state = byte & 0x07;
break;
case CARTRIDGE_XEGS_128:
case CARTRIDGE_XEGS_8F_64:
new_state = byte & 0x0f;
break;
case CARTRIDGE_XEGS_256:
@@ -970,6 +986,7 @@ static void PutByte(CARTRIDGE_image_t *cart, UWORD addr, UBYTE byte)
case CARTRIDGE_SWXEGS_512:
new_state = byte & 0xbf;
break;
case CARTRIDGE_MEGA_2048:
case CARTRIDGE_SWXEGS_1024:
new_state = byte;
break;
@@ -980,10 +997,26 @@ static void PutByte(CARTRIDGE_image_t *cart, UWORD addr, UBYTE byte)
case CARTRIDGE_SIC_512:
case CARTRIDGE_SIC_256:
case CARTRIDGE_SIC_128:
case CARTRIDGE_MEGA_4096:
/* Only react to access to $D50x/$D51x. */
if ((addr & 0xe0) == 0x00)
new_state = byte;
break;
case CARTRIDGE_THECART_128M:
case CARTRIDGE_THECART_32M:
case CARTRIDGE_THECART_64M:
switch (addr) {
case 0xd5a0:
new_state = (old_state & 0x3f00) | byte;
break;
case 0xd5a1:
new_state = (old_state & 0x00ff) | ((byte & 0x3f) << 8);
break;
case 0xd5a2:
new_state = (old_state & 0x3fff) | ((~byte & 0x01) << 14);
break;
}
break;
default:
/* Check types switchable by access to page D5. */
if (!access_D5(cart, addr, &new_state))
@@ -1167,6 +1200,9 @@ static void ResetCartState(CARTRIDGE_image_t *cart)
enabled and the current bank is 0. */
cart->state = 0x10000;
break;
case CARTRIDGE_MEGA_4096:
cart->state = 254;
break;
default:
cart->state = 0;
}
+141 -65
View File
@@ -4,73 +4,149 @@
#include "config.h"
#include "atari.h"
enum { CARTRIDGE_UNKNOWN = -1,
CARTRIDGE_NONE = 0,
CARTRIDGE_STD_8 = 1,
CARTRIDGE_STD_16 = 2,
CARTRIDGE_OSS_034M_16 = 3,
CARTRIDGE_5200_32 = 4,
CARTRIDGE_DB_32 = 5,
CARTRIDGE_5200_EE_16 = 6,
CARTRIDGE_5200_40 = 7,
CARTRIDGE_WILL_64 = 8,
CARTRIDGE_EXP_64 = 9,
CARTRIDGE_DIAMOND_64 = 10,
CARTRIDGE_SDX_64 = 11,
CARTRIDGE_XEGS_32 = 12,
CARTRIDGE_XEGS_64 = 13,
CARTRIDGE_XEGS_128 = 14,
CARTRIDGE_OSS_M091_16 = 15,
CARTRIDGE_5200_NS_16 = 16,
CARTRIDGE_ATRAX_128 = 17,
CARTRIDGE_BBSB_40 = 18,
CARTRIDGE_5200_8 = 19,
CARTRIDGE_5200_4 = 20,
CARTRIDGE_RIGHT_8 = 21,
CARTRIDGE_WILL_32 = 22,
CARTRIDGE_XEGS_256 = 23,
CARTRIDGE_XEGS_512 = 24,
CARTRIDGE_XEGS_1024 = 25,
CARTRIDGE_MEGA_16 = 26,
CARTRIDGE_MEGA_32 = 27,
CARTRIDGE_MEGA_64 = 28,
CARTRIDGE_MEGA_128 = 29,
CARTRIDGE_MEGA_256 = 30,
CARTRIDGE_MEGA_512 = 31,
CARTRIDGE_MEGA_1024 = 32,
CARTRIDGE_SWXEGS_32 = 33,
CARTRIDGE_SWXEGS_64 = 34,
CARTRIDGE_SWXEGS_128 = 35,
CARTRIDGE_SWXEGS_256 = 36,
CARTRIDGE_SWXEGS_512 = 37,
CARTRIDGE_SWXEGS_1024 = 38,
CARTRIDGE_PHOENIX_8 = 39,
CARTRIDGE_BLIZZARD_16 = 40,
CARTRIDGE_ATMAX_128 = 41,
CARTRIDGE_ATMAX_1024 = 42,
CARTRIDGE_SDX_128 = 43,
CARTRIDGE_OSS_8 = 44,
CARTRIDGE_OSS_043M_16 = 45,
CARTRIDGE_BLIZZARD_4 = 46,
CARTRIDGE_AST_32 = 47,
CARTRIDGE_ATRAX_SDX_64 = 48,
CARTRIDGE_ATRAX_SDX_128 = 49,
CARTRIDGE_TURBOSOFT_64 = 50,
CARTRIDGE_TURBOSOFT_128 = 51,
CARTRIDGE_ULTRACART_32 = 52,
CARTRIDGE_LOW_BANK_8 = 53,
CARTRIDGE_SIC_128 = 54,
CARTRIDGE_SIC_256 = 55,
CARTRIDGE_SIC_512 = 56,
CARTRIDGE_STD_2 = 57,
CARTRIDGE_STD_4 = 58,
CARTRIDGE_RIGHT_4 = 59,
CARTRIDGE_LAST_SUPPORTED = 59
enum {
CARTRIDGE_UNKNOWN = -1,
CARTRIDGE_NONE = 0,
CARTRIDGE_STD_8 = 1,
CARTRIDGE_STD_16 = 2,
CARTRIDGE_OSS_034M_16 = 3,
CARTRIDGE_5200_32 = 4,
CARTRIDGE_DB_32 = 5,
CARTRIDGE_5200_EE_16 = 6,
CARTRIDGE_5200_40 = 7,
CARTRIDGE_WILL_64 = 8,
CARTRIDGE_EXP_64 = 9,
CARTRIDGE_DIAMOND_64 = 10,
CARTRIDGE_SDX_64 = 11,
CARTRIDGE_XEGS_32 = 12,
CARTRIDGE_XEGS_07_64 = 13,
CARTRIDGE_XEGS_128 = 14,
CARTRIDGE_OSS_M091_16 = 15,
CARTRIDGE_5200_NS_16 = 16,
CARTRIDGE_ATRAX_128 = 17,
CARTRIDGE_BBSB_40 = 18,
CARTRIDGE_5200_8 = 19,
CARTRIDGE_5200_4 = 20,
CARTRIDGE_RIGHT_8 = 21,
CARTRIDGE_WILL_32 = 22,
CARTRIDGE_XEGS_256 = 23,
CARTRIDGE_XEGS_512 = 24,
CARTRIDGE_XEGS_1024 = 25,
CARTRIDGE_MEGA_16 = 26,
CARTRIDGE_MEGA_32 = 27,
CARTRIDGE_MEGA_64 = 28,
CARTRIDGE_MEGA_128 = 29,
CARTRIDGE_MEGA_256 = 30,
CARTRIDGE_MEGA_512 = 31,
CARTRIDGE_MEGA_1024 = 32,
CARTRIDGE_SWXEGS_32 = 33,
CARTRIDGE_SWXEGS_64 = 34,
CARTRIDGE_SWXEGS_128 = 35,
CARTRIDGE_SWXEGS_256 = 36,
CARTRIDGE_SWXEGS_512 = 37,
CARTRIDGE_SWXEGS_1024 = 38,
CARTRIDGE_PHOENIX_8 = 39,
CARTRIDGE_BLIZZARD_16 = 40,
CARTRIDGE_ATMAX_128 = 41,
CARTRIDGE_ATMAX_1024 = 42,
CARTRIDGE_SDX_128 = 43,
CARTRIDGE_OSS_8 = 44,
CARTRIDGE_OSS_043M_16 = 45,
CARTRIDGE_BLIZZARD_4 = 46,
CARTRIDGE_AST_32 = 47,
CARTRIDGE_ATRAX_SDX_64 = 48,
CARTRIDGE_ATRAX_SDX_128 = 49,
CARTRIDGE_TURBOSOFT_64 = 50,
CARTRIDGE_TURBOSOFT_128 = 51,
CARTRIDGE_ULTRACART_32 = 52,
CARTRIDGE_LOW_BANK_8 = 53,
CARTRIDGE_SIC_128 = 54,
CARTRIDGE_SIC_256 = 55,
CARTRIDGE_SIC_512 = 56,
CARTRIDGE_STD_2 = 57,
CARTRIDGE_STD_4 = 58,
CARTRIDGE_RIGHT_4 = 59,
CARTRIDGE_BLIZZARD_32 = 60,
CARTRIDGE_MEGAMAX_2048 = 61,
CARTRIDGE_THECART_128M = 62,
CARTRIDGE_MEGA_4096 = 63,
CARTRIDGE_MEGA_2048 = 64,
CARTRIDGE_THECART_32M = 65,
CARTRIDGE_THECART_64M = 66,
CARTRIDGE_XEGS_8F_64 = 67,
CARTRIDGE_LAST_SUPPORTED = 67
};
#define CARTRIDGE_MAX_SIZE (1024 * 1024)
extern int CARTRIDGE_kb[CARTRIDGE_LAST_SUPPORTED + 1];
extern char *CARTRIDGE_TextDesc[CARTRIDGE_LAST_SUPPORTED + 1];
#define CARTRIDGE_MAX_SIZE (128 * 1024 * 1024)
extern int const CARTRIDGE_kb[CARTRIDGE_LAST_SUPPORTED + 1];
#define CARTRIDGE_STD_8_DESC "Standard 8 KB cartridge"
#define CARTRIDGE_STD_16_DESC "Standard 16 KB cartridge"
#define CARTRIDGE_OSS_034M_16_DESC "OSS two chip 16 KB cartridge (034M)"
#define CARTRIDGE_5200_32_DESC "Standard 32 KB 5200 cartridge"
#define CARTRIDGE_DB_32_DESC "DB 32 KB cartridge"
#define CARTRIDGE_5200_EE_16_DESC "Two chip 16 KB 5200 cartridge"
#define CARTRIDGE_5200_40_DESC "Bounty Bob 40 KB 5200 cartridge"
#define CARTRIDGE_WILL_64_DESC "64 KB Williams cartridge"
#define CARTRIDGE_EXP_64_DESC "Express 64 KB cartridge"
#define CARTRIDGE_DIAMOND_64_DESC "Diamond 64 KB cartridge"
#define CARTRIDGE_SDX_64_DESC "SpartaDOS X 64 KB cartridge"
#define CARTRIDGE_XEGS_32_DESC "XEGS 32 KB cartridge"
#define CARTRIDGE_XEGS_07_64_DESC "XEGS 64 KB cartridge (banks 0-7)"
#define CARTRIDGE_XEGS_128_DESC "XEGS 128 KB cartridge"
#define CARTRIDGE_OSS_M091_16_DESC "OSS one chip 16 KB cartridge"
#define CARTRIDGE_5200_NS_16_DESC "One chip 16 KB 5200 cartridge"
#define CARTRIDGE_ATRAX_128_DESC "Atrax 128 KB cartridge"
#define CARTRIDGE_BBSB_40_DESC "Bounty Bob 40 KB cartridge"
#define CARTRIDGE_5200_8_DESC "Standard 8 KB 5200 cartridge"
#define CARTRIDGE_5200_4_DESC "Standard 4 KB 5200 cartridge"
#define CARTRIDGE_RIGHT_8_DESC "Right slot 8 KB cartridge"
#define CARTRIDGE_WILL_32_DESC "32 KB Williams cartridge"
#define CARTRIDGE_XEGS_256_DESC "XEGS 256 KB cartridge"
#define CARTRIDGE_XEGS_512_DESC "XEGS 512 KB cartridge"
#define CARTRIDGE_XEGS_1024_DESC "XEGS 1 MB cartridge"
#define CARTRIDGE_MEGA_16_DESC "MegaCart 16 KB cartridge"
#define CARTRIDGE_MEGA_32_DESC "MegaCart 32 KB cartridge"
#define CARTRIDGE_MEGA_64_DESC "MegaCart 64 KB cartridge"
#define CARTRIDGE_MEGA_128_DESC "MegaCart 128 KB cartridge"
#define CARTRIDGE_MEGA_256_DESC "MegaCart 256 KB cartridge"
#define CARTRIDGE_MEGA_512_DESC "MegaCart 512 KB cartridge"
#define CARTRIDGE_MEGA_1024_DESC "MegaCart 1 MB cartridge"
#define CARTRIDGE_SWXEGS_32_DESC "Switchable XEGS 32 KB cartridge"
#define CARTRIDGE_SWXEGS_64_DESC "Switchable XEGS 64 KB cartridge"
#define CARTRIDGE_SWXEGS_128_DESC "Switchable XEGS 128 KB cartridge"
#define CARTRIDGE_SWXEGS_256_DESC "Switchable XEGS 256 KB cartridge"
#define CARTRIDGE_SWXEGS_512_DESC "Switchable XEGS 512 KB cartridge"
#define CARTRIDGE_SWXEGS_1024_DESC "Switchable XEGS 1 MB cartridge"
#define CARTRIDGE_PHOENIX_8_DESC "Phoenix 8 KB cartridge"
#define CARTRIDGE_BLIZZARD_16_DESC "Blizzard 16 KB cartridge"
#define CARTRIDGE_ATMAX_128_DESC "Atarimax 128 KB Flash cartridge"
#define CARTRIDGE_ATMAX_1024_DESC "Atarimax 1 MB Flash cartridge"
#define CARTRIDGE_SDX_128_DESC "SpartaDOS X 128 KB cartridge"
#define CARTRIDGE_OSS_8_DESC "OSS 8 KB cartridge"
#define CARTRIDGE_OSS_043M_16_DESC "OSS two chip 16 KB cartridge (043M)"
#define CARTRIDGE_BLIZZARD_4_DESC "Blizzard 4 KB cartridge"
#define CARTRIDGE_AST_32_DESC "AST 32 KB cartridge"
#define CARTRIDGE_ATRAX_SDX_64_DESC "Atrax SDX 64 KB cartridge"
#define CARTRIDGE_ATRAX_SDX_128_DESC "Atrax SDX 128 KB cartridge"
#define CARTRIDGE_TURBOSOFT_64_DESC "Turbosoft 64 KB cartridge"
#define CARTRIDGE_TURBOSOFT_128_DESC "Turbosoft 128 KB cartridge"
#define CARTRIDGE_ULTRACART_32_DESC "Ultracart 32 KB cartridge"
#define CARTRIDGE_LOW_BANK_8_DESC "Low bank 8 KB cartridge"
#define CARTRIDGE_SIC_128_DESC "SIC! 128 KB cartridge"
#define CARTRIDGE_SIC_256_DESC "SIC! 256 KB cartridge"
#define CARTRIDGE_SIC_512_DESC "SIC! 512 KB cartridge"
#define CARTRIDGE_STD_2_DESC "Standard 2 KB cartridge"
#define CARTRIDGE_STD_4_DESC "Standard 4 KB cartridge"
#define CARTRIDGE_RIGHT_4_DESC "Right slot 4 KB cartridge"
#define CARTRIDGE_BLIZZARD_32_DESC "Blizzard 32 KB cartridge"
#define CARTRIDGE_MEGAMAX_2048_DESC "MegaMax 2 MB cartridge"
#define CARTRIDGE_THECART_128M_DESC "The!Cart 128 MB cartridge"
#define CARTRIDGE_MEGA_4096_DESC "Flash MegaCart 4 MB cartridge"
#define CARTRIDGE_MEGA_2048_DESC "MegaCart 2 MB cartridge"
#define CARTRIDGE_THECART_32M_DESC "The!Cart 32 MB cartridge"
#define CARTRIDGE_THECART_64M_DESC "The!Cart 64 MB cartridge"
#define CARTRIDGE_XEGS_8F_64_DESC "XEGS 64 KB cartridge (banks 8-15)"
/* Indicates whether the emulator should automatically reboot (coldstart)
after inserting/removing a cartridge. (Doesn't affect the piggyback
+19 -6
View File
@@ -2,7 +2,7 @@
* cfg.c - Emulator Configuration
*
* Copyright (c) 1995-1998 David Firth
* Copyright (c) 1998-2010 Atari800 development team (see DOC/CREDITS)
* Copyright (c) 1998-2014 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
@@ -22,6 +22,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "artifact.h"
#include "atari.h"
#include <stdlib.h>
#include "cartridge.h"
@@ -54,6 +55,9 @@
#if SUPPORTS_CHANGE_VIDEOMODE
#include "videomode.h"
#endif
#ifdef SOUND
#include "sound.h"
#endif
int CFG_save_on_exit = FALSE;
@@ -188,15 +192,16 @@ int CFG_LoadConfig(const char *alternate_config_filename)
else if (strcmp(string, "ENABLE_NEW_POKEY") == 0) {
#ifdef SOUND
#ifndef SYNCHRONIZED_SOUND
POKEYSND_enable_new_pokey = Util_sscanbool(ptr);
#endif /* SYNCHRONIZED_SOUND */
#endif /* SOUND */
}
else if (strcmp(string, "STEREO_POKEY") == 0) {
#ifdef STEREO_SOUND
POKEYSND_stereo_enabled = Util_sscanbool(ptr);
#endif
#ifdef SOUND_THIN_API
Sound_desired.channels = POKEYSND_stereo_enabled ? 2 : 1;
#endif /* SOUND_THIN_API */
#endif /* STEREO_SOUND */
}
else if (strcmp(string, "SPEAKER_SOUND") == 0) {
#ifdef CONSOLE_SOUND
@@ -293,6 +298,8 @@ int CFG_LoadConfig(const char *alternate_config_filename)
#if !defined(BASIC) && !defined(CURSES_BASIC)
else if (Colours_ReadConfig(string, ptr)) {
}
else if (ARTIFACT_ReadConfig(string, ptr)) {
}
else if (Screen_ReadConfig(string, ptr)) {
}
#endif
@@ -304,6 +311,10 @@ int CFG_LoadConfig(const char *alternate_config_filename)
else if (VIDEOMODE_ReadConfig(string, ptr)) {
}
#endif
#if defined(SOUND) && defined(SOUND_THIN_API)
else if (Sound_ReadConfig(string, ptr)) {
}
#endif /* defined(SOUND) && defined(SOUND_THIN_API) */
else {
#ifdef SUPPORTS_PLATFORM_CONFIGURE
if (!PLATFORM_Configure(string, ptr)) {
@@ -396,9 +407,7 @@ int CFG_WriteConfig(void)
#endif
#ifdef SOUND
#ifndef SYNCHRONIZED_SOUND
fprintf(fp, "ENABLE_NEW_POKEY=%d\n", POKEYSND_enable_new_pokey);
#endif /* SYNCHRONIZED_SOUND */
#ifdef STEREO_SOUND
fprintf(fp, "STEREO_POKEY=%d\n", POKEYSND_stereo_enabled);
#endif
@@ -429,6 +438,7 @@ int CFG_WriteConfig(void)
#endif
#if !defined(BASIC) && !defined(CURSES_BASIC)
Colours_WriteConfig(fp);
ARTIFACT_WriteConfig(fp);
Screen_WriteConfig(fp);
#endif
#ifdef NTSC_FILTER
@@ -437,6 +447,9 @@ int CFG_WriteConfig(void)
#if SUPPORTS_CHANGE_VIDEOMODE
VIDEOMODE_WriteConfig(fp);
#endif
#if defined(SOUND) && defined(SOUND_THIN_API)
Sound_WriteConfig(fp);
#endif /* defined(SOUND) && defined(SOUND_THIN_API) */
#ifdef SUPPORTS_PLATFORM_CONFIGSAVE
PLATFORM_ConfigSave(fp);
#endif
+32
View File
@@ -76,6 +76,38 @@ void Colours_SetRGB(int i, int r, int g, int b, int *colortable_ptr)
colortable_ptr[i] = (r << 16) + (g << 8) + b;
}
/* 3x3 matrix for conversion from RGB to YUV colourspace. */
static double const RGB2YUV_matrix[3][3] = {
{ 0.299, 0.587, 0.114 },
{ -0.14713, -0.28886, 0.436 },
{ 0.615, -0.51499, -0.10001 }
};
/* 3x3 matrix for conversion from YUV to RGB colourspace. */
static double const YUV2RGB_matrix[3][3] = {
{ 1.0, 0.0, 1.13983 },
{ 1.0, -0.39465, -0.58060 },
{ 1.0, 2.03211, 0.0 }
};
/* Multiply 3x3 matrix MATRIX by vector IN[1..3] and return result in OUT[1..3]. */
static void MultiplyMatrix(double in1, double in2, double in3, double *out1, double *out2, double *out3, double const matrix[3][3])
{
*out1 = matrix[0][0] * in1 + matrix[0][1] * in2 + matrix[0][2] * in3;
*out2 = matrix[1][0] * in1 + matrix[1][1] * in2 + matrix[1][2] * in3;
*out3 = matrix[2][0] * in1 + matrix[2][1] * in2 + matrix[2][2] * in3;
}
void Colours_RGB2YUV(double r, double g, double b, double *y, double *u, double *v)
{
MultiplyMatrix(r, g, b, y, u, v, RGB2YUV_matrix);
}
void Colours_YUV2RGB(double y, double u, double v, double *r, double *g, double *b)
{
MultiplyMatrix(y, u, v, r, g, b, YUV2RGB_matrix);
}
static void UpdateModeDependentPointers(int tv_mode)
{
/* Set pointers to the current setup and external palette. */
+7
View File
@@ -89,4 +89,11 @@ int Colours_Initialise(int *argc, char *argv[]);
void Colours_SetPreset(Colours_preset_t preset);
Colours_preset_t Colours_GetPreset(void);
/* Convert given R, G and B values to corresponding Y, U, V values (all in the
0.0 - 1.0 range). */
void Colours_RGB2YUV(double r, double g, double b, double *y, double *u, double *v);
/* Convert given Y, U and V values to corresponding R, G, B values (all in the
0.0 - 1.0 range). */
void Colours_YUV2RGB(double y, double u, double v, double *r, double *g, double *b);
#endif /* COLOURS_H_ */
+269 -80
View File
@@ -1,7 +1,7 @@
/*
* colours_pal.c - Atari PAL colour palette generation and adjustment
*
* Copyright (C) 2009-2010 Atari800 development team (see DOC/CREDITS)
* Copyright (C) 2009-2014 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
@@ -46,11 +46,11 @@ static struct {
COLOURS_EXTERNAL_t COLOURS_PAL_external = { "", FALSE, FALSE };
/* Applies the colours setup to the external palette. Writes output to
COLOURTABLE. */
static void AdjustExternal(int colourtable[256])
/* Fills YUV_TABLE from external palette. External palette is not adjusted if
COLOURS_PAL_external.adjust is false. */
static void GetYUVFromExternal(double yuv_table[256*5])
{
const double gamma = 1 - COLOURS_PAL_setup.gamma / 2.0;
double const gamma = 1 - COLOURS_PAL_setup.gamma / 2.0;
unsigned char *ext_ptr = COLOURS_PAL_external.palette;
int n;
@@ -63,99 +63,258 @@ static void AdjustExternal(int colourtable[256])
double r = (double)*ext_ptr++ / 255.0;
double g = (double)*ext_ptr++ / 255.0;
double b = (double)*ext_ptr++ / 255.0;
double y = 0.299 * r + 0.587 * g + 0.114 * b;
double u = -0.14713 * r - 0.28886 * g + 0.436 * b;
double v = 0.615 * r - 0.51499 * g - 0.10001 * b;
double tmp_u = u;
double y, u, v, tmp_u;
Colours_RGB2YUV(r, g, b, &y, &u, &v);
tmp_u = u;
u = tmp_u * c - v * s;
v = tmp_u * s + v * c;
y = pow(y, gamma);
y *= COLOURS_PAL_setup.contrast * 0.5 + 1;
y += COLOURS_PAL_setup.brightness * 0.5;
if (y > 1.0)
y = 1.0;
else if (y < 0.0)
y = 0.0;
u *= COLOURS_PAL_setup.saturation + 1.0;
v *= COLOURS_PAL_setup.saturation + 1.0;
/* Optionally adjust external palette. */
if (COLOURS_PAL_external.adjust) {
y = pow(y, gamma);
y *= COLOURS_PAL_setup.contrast * 0.5 + 1;
y += COLOURS_PAL_setup.brightness * 0.5;
if (y > 1.0)
y = 1.0;
else if (y < 0.0)
y = 0.0;
u *= COLOURS_PAL_setup.saturation + 1.0;
v *= COLOURS_PAL_setup.saturation + 1.0;
}
r = y + 1.13983 * v;
g = y - 0.39465 * u - 0.58060 * v;
b = y + 2.03211 * u;
Colours_SetRGB(n, (int) (r * 255), (int) (g * 255), (int) (b * 255), colourtable);
*yuv_table++ = y;
/* Cannot retrieve different U/V values for even and odd lines from an
external palette - instead write each value twice. */
*yuv_table++ = u;
*yuv_table++ = u;
*yuv_table++ = v;
*yuv_table++ = v;
}
}
/* Generates a PAL palette, based on colour setup. Result is written into
COLOURTABLE.
PAL GTIA produces slightly different hues on odd and even lines;
they are later averaged in the TV (a feature of PAL system). The generated
palette reproduces the real machine somewhat - each hue is an average of
an "odd" hue and an "even" hue. */
static void GeneratePalette(int colourtable[256])
/* Below are conclusions from analysis of oscillograms of PAL GTIA output.
The oscillograms are available at:
http://www.atari.org.pl/forum/viewtopic.php?pid=164037#p164037
Like the NTSC GTIA, the PAL GTIA produces color signal by delaying
(phase-shifting) a base chrominance subcarrier by a specified time -
different for each displayed hue. The subcarrier's frequency is
4433618.75 Hz (4.43 MHz in short). The subcarrier is provided at the chip's
PAL pin; output signal is produced at the COL pin.
As in NTSC, the delay introduced by the PAL GTIA can be adjusted to a
certain extent by changing voltage applied at the DEL pin.
This is where the similarities between the PAL GTIA and its NTSC
counterpart end.
In NTSC, each screen line contains, in its back porch, a burst of about 10
cycles of color subcarrier (known as the coloburst). The colorburst is used
by the TV as a reference for decoding colors in each line. Signal with
phase shift equal to the colorburst's (ie. equal to the subcarrier's) is
decoded as 180 deg angle in the YUV colorspace (-U). Delaying the signal is
interpreted as rotating the angle clockwise in YUV.
In PAL, there's also colorburst, but it is not equal to the color
subcarrier. In even lines it lags the subcarrier by 45 deg, and in odd
lines it leads it subcarrier by 45 deg. The resulting 90 deg difference is
used by the TV to distinguish even and odd lines. The original subcarrier
is recreated by the receiver by summing colorbursts from two consecutive
lines (and adjusting its amplitude, since sum of two sine waves shifted by
90 deg has higher amplitude than the original waves).
Then, as in NTSC, signals equal in phase to the (recreated) subcarrier are
decoded as 180 deg angle in YUV. But other signals are decoded differently
in even and in odd lines. In even lines (or "NTSC lines"), delaying the
signal is interpreted as rotating the angle clockwise in YUV, just like in
NTSC. But in odd lines (or "PAL lines"), delaying the signal is akin to
rotating the angle counter-clockwise. So, to achieve the same color in even
and odd lines, the transmitter must send signal delayed wrt. the subcarrier
in even lines but "rushed" (anti-delayed?) in odd lines.
PAL GTIA can only delay input signal; it can't "rush" it, it would involve
creating output before input has arrived. So the requirements of the PAL
system are achieved in the chip by delaying the signal differently in even
and odd lines.
Measurements indicate that the PAL GTIA delays the input subcarrier by
95.2ns; then it might delay it by further 100.7ns if needed; and finally
can delay it further by X, 2*X, 3*X, ..., 7*X, where X is a delay adjusted
by voltage at the DEL pin. The general formula is:
DELAY(hue) = 95.2ns + ADD(hue)*100.7ns + MULT(hue)*X
where
ADD(hue) depends on a given hue and can be 0 or 1,
MULT(hue) depends on a given hue and can be 0, 1, 2, ..., 7,
X depends on voltage at the DEL pin.
So, the chip can shift the input signal by 8*2=16 different delays.
Mapping of ADD and MULT values to specific hues is random - it is
implemented in the source code as the del_coeffs structure.
The relation between DEL pin voltage and the resulting delay is not linear
- it was measured to be:
17.37ns at 5V,
10.60ns at 7V,
7.44ns at 9V.
The PAL GTIA apparently contains a series of 7 delay elements similarly to
the NTSC version (which contains 15 of them), and an additional 100.7ns
delay element. (When looking at the oscillograms, for each hue that passes
through this 100.7ns delay, the resulting waveform is different than for
hues that don't involve the delay - it looks like it was inverted
vertically. This gives a hint about how the delay is implemented
internally.)
The end result is, PAL GTIA actually produces more than 256 colors. It
produces different hues in odd and even lines, but it is not normally
visible since PAL TVs average hues on each two consecutive lines - but
it can be made visible with specially-crafted screens. Currently this
feature of the chip is not implemented - only 256 colors are produced,
each one being an average of "even" and "odd" hues.
In PAL GTIA, just as in NTSC, the colorburst signals have the same phase as
Hue 1. But by changing voltage at the DEL pin, we also change the relative
phase shift of the colorburst between even and odd lines - it is not always
90 degrees. It has the following consequences - all of them observed on a
real machine, and all currently emulated:
1. Changing phase shift between odd and even colorbursts also changes
amplitude of the resulting subcarrier, which is recreated by summing the
two colorbursts. Since amplitude of the color subcarrier is used as a
reference for decoding color saturation, changing voltage at DEL not only
changes hues of displayed colors; it also changes their saturation.
2. With appropriately chosen DEL voltage, phase shift between even and odd
colorbursts can reach 180 deg. At this point the PAL TV can no longer
distinguish even and odd lines, and stops interpreting color signal,
displaying screen as black-and-white with visible chroma dots.
3. Changing DEL voltage further causes phase shift between even and odd
colorbursts to to be larger than 180 deg, at which point the TV starts
interpreting color signal "backwards", as if the color subcarrier suddenly
shifted by 180 deg.
*/
/* Generates PAL palette into YUV_TABLE. */
static void GetYUVFromGenerated(double yuv_table[256*5])
{
struct del_coeff {
int add;
int mult;
};
/* Delay coefficients for each hue. */
static struct {
struct del_coeff even[15];
struct del_coeff odd[15];
} const del_coeffs = {
{ { 1, 5 }, /* Hue $1 in even lines */
{ 1, 6 }, /* Hue $2 in even lines */
{ 1, 7 },
{ 0, 0 },
{ 0, 1 },
{ 0, 2 },
{ 0, 4 },
{ 0, 5 },
{ 0, 6 },
{ 0, 7 },
{ 1, 1 },
{ 1, 2 },
{ 1, 3 },
{ 1, 4 },
{ 1, 5 } /* Hue $F in even lines */
},
{ { 1, 1 }, /* Hue $1 in odd lines */
{ 1, 0 }, /* Hue $2 in odd lines */
{ 0, 7 },
{ 0, 6 },
{ 0, 5 },
{ 0, 4 },
{ 0, 2 },
{ 0, 1 },
{ 0, 0 },
{ 1, 7 },
{ 1, 5 },
{ 1, 4 },
{ 1, 3 },
{ 1, 2 },
{ 1, 1 } /* Hue $F in odd lines */
}
};
int cr, lm;
double scaled_black_level = (double)COLOURS_PAL_setup.black_level / 255.0f;
double scaled_white_level = (double)COLOURS_PAL_setup.white_level / 255.0f;
const double gamma = 1 - COLOURS_PAL_setup.gamma / 2.0;
double const start_angle = COLOURS_PAL_setup.hue * M_PI;
double color_diff = COLOURS_PAL_setup.color_delay * M_PI / 180.0;
double const scaled_black_level = (double)COLOURS_PAL_setup.black_level / 255.0f;
double const scaled_white_level = (double)COLOURS_PAL_setup.white_level / 255.0f;
double const gamma = 1 - COLOURS_PAL_setup.gamma / 2.0;
/* NTSC luma multipliers from CGIA.PDF */
double luma_mult[16] = {
static double const luma_mult[16] = {
0.6941, 0.7091, 0.7241, 0.7401,
0.7560, 0.7741, 0.7931, 0.8121,
0.8260, 0.8470, 0.8700, 0.8930,
0.9160, 0.9420, 0.9690, 1.0000};
/* When phase shift between even and odd colorbursts is close to 180 deg, the
TV stops interpreting color signal. This value determines how close to 180
deg that phase shift must be. It is specific to a TV set. */
static double const color_disable_threshold = 0.05;
/* Base delay - 1/4.43MHz * base_del = ca. 95.2ns */
static double const base_del = 0.421894970414201;
/* Additional delay - 1/4.43MHz * add_del = ca. 100.7ns */
static double const add_del = 0.446563064859117;
/* Delay introduced by the DEL pin voltage. */
double const del_adj = COLOURS_PAL_setup.color_delay / 360.0;
/* Phase delays of colorbursts in even and odd lines. They are equal to
Hue 1. */
double const even_burst_del = base_del + add_del * del_coeffs.even[0].add + del_adj * del_coeffs.even[0].mult;
double const odd_burst_del = base_del + add_del * del_coeffs.odd[0].add + del_adj * del_coeffs.odd[0].mult;
/* Reciprocal of the recreated subcarrier's amplitude. */
double saturation_mult;
/* Phase delay of the recreated amplitude. */
double subcarrier_del = (even_burst_del + odd_burst_del + COLOURS_PAL_setup.hue) / 2.0;
/* Phase difference between colorbursts in even and odd lines. */
double burst_diff = even_burst_del - odd_burst_del;
burst_diff -= floor(burst_diff); /* Normalize to 0..1. */
if (burst_diff > 0.5 - color_disable_threshold && burst_diff < 0.5 + color_disable_threshold)
/* Shift between colorbursts close to 180 deg. Don't produce color. */
saturation_mult = 0.0;
else {
/* Subcarrier is a sum of two waves with equal frequency and amplitude,
but phase-shifted by 2pi*burst_diff. The formula is derived from
http://2000clicks.com/mathhelp/GeometryTrigEquivPhaseShift.aspx */
double subcarrier_amplitude = sqrt(2.0 * cos(burst_diff*2.0*M_PI) + 2.0);
/* Normalise saturation_mult by multiplying by sqrt(2), so that it
equals 1.0 when odd & even colorbursts are shifted by 90 deg (ie.
burst_diff == 0.25). */
saturation_mult = sqrt(2.0) / subcarrier_amplitude;
}
for (cr = 0; cr < 16; cr ++) {
double u = 0.0;
double v = 0.0;
double even_u = 0.0;
double odd_u = 0.0;
double even_v = 0.0;
double odd_v = 0.0;
if (cr) {
struct pal_phase {
double mult;
double shift;
};
static struct pal_phase const phases[14] = {
{ 1.5, M_PI },
{ 2.5, M_PI },
{ 3.5, M_PI },
{ -1.5, 0.0 },
{ -0.5, 0.0 },
{ 0.0, 0.0 },
{ 1.5, 0.0 },
{ 2.5, 0.0 },
{ 3.5, 0.0 },
{ 4.0, 0.0 },
{ -2.5, M_PI },
{ -1.5, M_PI },
{ -0.5, M_PI },
{ 0.5, M_PI }
};
struct pal_phase const *odd_phase = &phases[(cr - 1) % 14];
struct pal_phase const *even_phase = &phases[(25 -(cr - 1)) % 14];
double odd_angle = start_angle + odd_phase->shift - color_diff * (odd_phase->mult);
double even_angle = start_angle + even_phase->shift + color_diff * (even_phase->mult - 0.5);
double odd_u = cos(odd_angle);
double odd_v = sin(odd_angle);
double even_u = cos(even_angle);
double even_v = sin(even_angle);
double saturation = (COLOURS_PAL_setup.saturation + 1) * 0.175;
u = (even_u + odd_u) * 0.5 * saturation;
v = (even_v + odd_v) * 0.5 * saturation;
struct del_coeff const *even_delay = &(del_coeffs.even[cr - 1]);
struct del_coeff const *odd_delay = &(del_coeffs.odd[cr - 1]);
double even_del = base_del + add_del * even_delay->add + del_adj * even_delay->mult;
double odd_del = base_del + add_del * odd_delay->add + del_adj * odd_delay->mult;
double even_angle = (0.5 - (even_del - subcarrier_del)) * 2.0 * M_PI;
double odd_angle = (0.5 + (odd_del - subcarrier_del)) * 2.0 * M_PI;
double saturation = (COLOURS_PAL_setup.saturation + 1) * 0.175 * saturation_mult;
even_u = cos(even_angle) * saturation;
even_v = sin(even_angle) * saturation;
odd_u = cos(odd_angle) * saturation;
odd_v = sin(odd_angle) * saturation;
}
for (lm = 0; lm < 16; lm ++) {
/* calculate yuv for color entry */
double y = (luma_mult[lm] - luma_mult[0]) / (luma_mult[15] - luma_mult[0]);
double r, g, b;
y = pow(y, gamma);
y *= COLOURS_PAL_setup.contrast * 0.5 + 1;
y += COLOURS_PAL_setup.brightness * 0.5;
/* Scale the Y signal's range from 0..1 to
* scaled_black_level..scaled_white_level */
scaled_black_level..scaled_white_level */
y = y * (scaled_white_level - scaled_black_level) + scaled_black_level;
/*
if (y < scaled_black_level)
@@ -163,20 +322,50 @@ static void GeneratePalette(int colourtable[256])
else if (y > scaled_white_level)
y = scaled_white_level;
*/
r = y + 1.13983 * v;
g = y - 0.39465 * u - 0.58060 * v;
b = y + 2.03211 * u;
Colours_SetRGB(cr * 16 + lm, (int) (r * 255), (int) (g * 255), (int) (b * 255), colourtable);
*yuv_table++ = y;
*yuv_table++ = even_u;
*yuv_table++ = odd_u;
*yuv_table++ = even_v;
*yuv_table++ = odd_v;
}
}
}
void COLOURS_PAL_GetYUV(double yuv_table[256*5])
{
if (COLOURS_PAL_external.loaded)
GetYUVFromExternal(yuv_table);
else
GetYUVFromGenerated(yuv_table);
}
/* Averages YUV values from YUV_TABLE and converts them to RGB values. Stores
them in COLOURTABLE. */
static void YUV2RGB(int colourtable[256], double const yuv_table[256*5])
{
double const *yuv_ptr = yuv_table;
int n;
for (n = 0; n < 256; ++n) {
double y = *yuv_ptr++;
double even_u = *yuv_ptr++;
double odd_u = *yuv_ptr++;
double even_v = *yuv_ptr++;
double odd_v = *yuv_ptr++;
double r, g, b;
/* The different colors in odd and even lines are not
emulated - instead the palette contains averaged values. */
double u = (even_u + odd_u) / 2.0;
double v = (even_v + odd_v) / 2.0;
Colours_YUV2RGB(y, u, v, &r, &g, &b);
Colours_SetRGB(n, (int) (r * 255), (int) (g * 255), (int) (b * 255), colourtable);
}
}
void COLOURS_PAL_Update(int colourtable[256])
{
if (COLOURS_PAL_external.loaded)
AdjustExternal(colourtable);
else
GeneratePalette(colourtable);
double yuv_table[256*5];
COLOURS_PAL_GetYUV(yuv_table);
YUV2RGB(colourtable, yuv_table);
}
void COLOURS_PAL_RestoreDefaults(void)
+4
View File
@@ -27,4 +27,8 @@ int COLOURS_PAL_Initialise(int *argc, char *argv[]);
/* Function for getting the PAL-specific color preset. */
Colours_preset_t COLOURS_PAL_GetPreset(void);
/* Writes the PAL palette (generated or external) as {Y, even U, odd U,
even V, odd V} quintuples in YUV_TABLE. */
void COLOURS_PAL_GetYUV(double yuv_table[256*5]);
#endif /* COLOURS_PAL_H_ */
+55 -42
View File
@@ -5,14 +5,13 @@
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* The Austin Franklin 80 column card. */
/* #undef AF80 */
//#define AF80 1
/* Target: Android */
/* #undef ANDROID */
//#define DREAMCAST
/* Target: standard I/O. */
//#define BASIC 1
/* #undef BASIC */
/* Define to use buffered debug output. */
/* #undef BUFFERED_LOG */
@@ -24,7 +23,7 @@
/* #undef CLOSEDIR_VOID */
/* Define to allow console sound (keyboard clicks). */
/* #undef CONSOLE_SOUND */
#define CONSOLE_SOUND 1
/* Define to activate crash menu after CIM instruction. */
/* #undef CRASH_MENU */
@@ -51,7 +50,7 @@
/* #undef DOS_DRIVES */
/* Define to enable event recording. */
/* #undef EVENT_RECORDING */
#define EVENT_RECORDING 1
/* Target: Atari Falcon system. */
/* #undef FALCON */
@@ -59,6 +58,9 @@
/* Define to use m68k assembler CPU core for Falcon target. */
/* #undef FALCON_CPUASM */
/* Use SDL for graphics and input. */
//#define GUI_SDL 1
/* Define to 1 if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H 1
@@ -75,7 +77,7 @@
/* #undef HAVE_DIRECT_H */
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
*/
*/
#define HAVE_DIRENT_H 1
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
@@ -172,10 +174,7 @@
#define HAVE_OPENDIR 1
/* Support for OpenGL graphics acceleration. */
/* #undef HAVE_OPENGL */
/* Define to 1 if you have the <readline/readline.h> header file. */
#define HAVE_READLINE_READLINE_H 1
#define HAVE_OPENGL 1
/* Define to 1 if you have the `rename' function. */
#define HAVE_RENAME 1
@@ -205,7 +204,7 @@
#define HAVE_STAT 1
/* Define to 1 if `stat' has the bug that it succeeds when given the
zero-length file name argument. */
zero-length file name argument. */
/* #undef HAVE_STAT_EMPTY_STRING_BUG */
/* Define to 1 if you have the <stdint.h> header file. */
@@ -248,14 +247,14 @@
#define HAVE_SYSTEM 1
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
*/
*/
/* #undef HAVE_SYS_DIR_H */
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#define HAVE_SYS_IOCTL_H 1
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
*/
*/
/* #undef HAVE_SYS_NDIR_H */
/* Define to 1 if you have the <sys/select.h> header file. */
@@ -325,16 +324,13 @@
#define IDE 1
/* Define to allow sound interpolation. */
/* #undef INTERPOLATE_SOUND */
/* Target: Java NestedVM. */
/* #undef JAVANVM */
#define INTERPOLATE_SOUND 1
/* Define to use LINUX joystick. */
/* #undef LINUX_JOYSTICK */
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
slash. */
slash. */
/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */
/* Define if mkdir takes only one argument. */
@@ -365,13 +361,13 @@
/* #undef MOTIF */
/* Define to allow color changes inside a scanline. */
/* #undef NEW_CYCLE_EXACT */
#define NEW_CYCLE_EXACT 1
/* Define to use nonlinear POKEY mixing. */
/* #undef NONLINEAR_MIXING */
#define NONLINEAR_MIXING 1
/* Use NTSC video filter. */
/* #undef NTSC_FILTER */
//#define NTSC_FILTER 1
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "pstehlik@sophics.cz"
@@ -380,7 +376,7 @@
#define PACKAGE_NAME "Atari800"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "Atari800 2.2.1"
#define PACKAGE_STRING "Atari800 3.1.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "atari800"
@@ -389,11 +385,14 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "2.2.1"
#define PACKAGE_VERSION "3.1.0"
/* Define to use page-based attribute array. */
/* #undef PAGED_ATTRIB */
/* Use accurate PAL color blending. */
//#define PAL_BLENDING 1
/* Define to emulate the Black Box. */
#define PBI_BB 1
@@ -401,10 +400,13 @@
#define PBI_MIO 1
/* A prototype 80 column card for the 1090 expansion box. */
/* #undef PBI_PROTO80 */
//#define PBI_PROTO80 1
/* Define to emulate the 1400XL/1450XLD. */
/* #undef PBI_XLD */
//#define PBI_XLD 1
/* Platform-specific mapping of RGB palette to display surface. */
#define PLATFORM_MAP_PALETTE 1
/* Target: Sony PlayStation 2. */
/* #undef PS2 */
@@ -412,6 +414,9 @@
/* Define as the return type of signal handlers (`int' or `void'). */
#define RETSIGTYPE void
/* Target: Raspberry Pi. */
/* #undef RPI */
/* Define to use R: device. */
/* #undef R_IO_DEVICE */
@@ -422,7 +427,7 @@
/* #undef R_SERIAL */
/* Target: SDL library. */
/* #undef SDL */
//#define SDL 1
/* Define to the type of arg 1 for `select'. */
#define SELECT_TYPE_ARG1 int
@@ -440,41 +445,46 @@
/* #undef SHM */
/* Define to activate sound support. */
/* #undef SOUND */
#define SIGNED_SAMPLES 1
#define POKEYSND_SIGNED_SAMPLES 1
#define SOUND 1
/* Platform updates sound buffer by callback function. */
#define SOUND_CALLBACK 1
/* Use new sound API. */
#define SOUND_THIN_API 1
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to allow stereo sound. */
/* #undef STEREO_SOUND */
#define STEREO_SOUND 1
/* Can change video modes on the fly. */
/* #undef SUPPORTS_CHANGE_VIDEOMODE */
//#define SUPPORTS_CHANGE_VIDEOMODE 1
/* Save additional config file options. */
/* #undef SUPPORTS_PLATFORM_CONFIGSAVE */
//#define SUPPORTS_PLATFORM_CONFIGSAVE 1
/* Additional config file options. */
/* #undef SUPPORTS_PLATFORM_CONFIGURE */
//#define SUPPORTS_PLATFORM_CONFIGURE 1
/* Update the Palette if it changed. */
/* #undef SUPPORTS_PLATFORM_PALETTEUPDATE */
//#define SUPPORTS_PLATFORM_PALETTEUPDATE 1
/* Platform-specific sleep function. */
/* #undef SUPPORTS_PLATFORM_SLEEP */
/* Platform-specific time function. */
//#define SUPPORTS_PLATFORM_TIME 1
/* Can display the screen rotated sideways. */
/* #undef SUPPORTS_ROTATE_VIDEOMODE */
#define SUPPORTS_ROTATE_VIDEOMODE 1
/* Reinitialise the sound system. */
/* #undef SUPPORTS_SOUND_REINIT */
/* Define to use synchronized sound. */
/* #undef SYNCHRONIZED_SOUND */
#define SYNCHRONIZED_SOUND 1
/* Alternate system-wide config file for non-Unix OS. */
/* #undef SYSTEM_WIDE_CFG_FILE */
@@ -494,17 +504,20 @@
/* Target: Ncurses library. */
/* #undef USE_NCURSES */
/* Define to enable on-screen keyboard. */
/* #undef USE_UI_BASIC_ONSCREEN_KEYBOARD */
/* Define to use very slow computer support (faster -refresh). */
/* #undef VERY_SLOW */
/* Define to emulate the Alien Group Voice Box. */
/* #undef VOICEBOX */
//#define VOICEBOX 1
/* Define to allow volume only sound. */
/* #undef VOL_ONLY_SOUND */
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
@@ -522,7 +535,7 @@
/* #undef X11 */
/* Emulate the XEP80. */
/* #undef XEP80_EMULATION */
//#define XEP80_EMULATION 1
/* Target: X11 with XView. */
/* #undef XVIEW */
@@ -540,14 +553,14 @@
/* #undef const */
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
/* #undef inline */
#define inline __inline__
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
/* Define to empty if the keyword `volatile' does not work. Warning: valid
code using `volatile' can become incorrect without. Disable with care. */
code using `volatile' can become incorrect without. Disable with care. */
/* #undef volatile */
+27 -22
View File
@@ -26,7 +26,9 @@
#include <string.h>
#include "antic.h"
#include "binload.h"
#include "cassette.h"
#include "cpu.h"
#include "gtia.h"
#ifndef BASIC
#include "input.h"
@@ -79,8 +81,8 @@ UBYTE GTIA_GRACTL;
/* Internal GTIA state ----------------------------------------------------- */
int GTIA_speaker;
int GTIA_consol_index = 0;
UBYTE GTIA_consol_table[3];
int GTIA_consol_override = 0;
static UBYTE consol;
UBYTE consol_mask;
UBYTE GTIA_TRIG[4];
UBYTE GTIA_TRIG_latch[4];
@@ -415,14 +417,11 @@ void GTIA_NewPmScanline(void)
void GTIA_Frame(void)
{
#ifdef BASIC
int consol = 0xf;
consol = 0xf;
#else
int consol = INPUT_key_consol | 0x08;
consol = INPUT_key_consol | 0x08;
#endif
GTIA_consol_table[0] = consol;
GTIA_consol_table[1] = GTIA_consol_table[2] &= consol;
if (GTIA_GRACTL & 4) {
GTIA_TRIG_latch[0] &= GTIA_TRIG[0];
GTIA_TRIG_latch[1] &= GTIA_TRIG[1];
@@ -519,13 +518,27 @@ UBYTE GTIA_GetByte(UWORD addr, int no_side_effects)
return (Atari800_tv_mode == Atari800_TV_PAL) ? 0x01 : 0x0f;
case GTIA_OFFSET_CONSOL:
{
UBYTE byte = GTIA_consol_table[GTIA_consol_index] & consol_mask;
if (!no_side_effects && GTIA_consol_index > 0) {
GTIA_consol_index--;
if (GTIA_consol_index == 0 && CASSETTE_hold_start) {
/* press Space after Start to start cassette boot */
CASSETTE_press_space = 1;
CASSETTE_hold_start = CASSETTE_hold_start_on_reboot;
UBYTE byte = consol & consol_mask;
if (!no_side_effects && GTIA_consol_override > 0) {
/* Check if we're called from outside OS. This avoids sending
console keystrokes to diagnostic cartridges. */
if (CPU_regPC < 0xc000)
/* Not from OS. Disable console override. */
GTIA_consol_override = 0;
else {
--GTIA_consol_override;
if (Atari800_builtin_basic && Atari800_disable_basic && !BINLOAD_loading_basic)
/* Only for XL/XE - hold Option during reboot. */
byte &= ~INPUT_CONSOL_OPTION;
if (CASSETTE_hold_start && Atari800_machine_type != Atari800_MACHINE_5200) {
/* Only for the computers - hold Start during reboot. */
byte &= ~INPUT_CONSOL_START;
if (GTIA_consol_override == 0) {
/* press Space after Start to start cassette boot. */
CASSETTE_press_space = 1;
CASSETTE_hold_start = CASSETTE_hold_start_on_reboot;
}
}
}
}
return byte;
@@ -1119,14 +1132,6 @@ void GTIA_PutByte(UWORD addr, UBYTE byte)
UPDATE_PM_CYCLE_EXACT
break;
case GTIA_OFFSET_PRIOR:
#ifdef NEW_CYCLE_EXACT
#ifndef NO_GTIA11_DELAY
/* update prior change ring buffer */
ANTIC_prior_curpos = (ANTIC_prior_curpos + 1) % ANTIC_PRIOR_BUF_SIZE;
ANTIC_prior_pos_buf[ANTIC_prior_curpos] = ANTIC_XPOS * 2 - 37 + 2;
ANTIC_prior_val_buf[ANTIC_prior_curpos] = byte;
#endif
#endif
ANTIC_SetPrior(byte);
GTIA_PRIOR = byte;
if (byte & 0x40)
+1 -2
View File
@@ -121,8 +121,7 @@ extern UBYTE GTIA_collisions_mask_player_player;
extern UBYTE GTIA_TRIG[4];
extern UBYTE GTIA_TRIG_latch[4];
extern int GTIA_consol_index;
extern UBYTE GTIA_consol_table[3];
extern int GTIA_consol_override;
extern int GTIA_speaker;
int GTIA_Initialise(int *argc, char *argv[]);
+4 -4
View File
@@ -11,10 +11,10 @@
#ifndef WORDS_BIGENDIAN
#ifdef WORDS_UNALIGNED_OK
#define MEMORY_dGetWord(x) UNALIGNED_GET_WORD(&MEMORY_mem[x], memory_read_word_stat)
#define MEMORY_dPutWord(x, y) UNALIGNED_PUT_WORD(&MEMORY_mem[x], (y), memory_write_word_stat)
#define MEMORY_dGetWordAligned(x) UNALIGNED_GET_WORD(&MEMORY_mem[x], memory_read_aligned_word_stat)
#define MEMORY_dPutWordAligned(x, y) UNALIGNED_PUT_WORD(&MEMORY_mem[x], (y), memory_write_aligned_word_stat)
#define MEMORY_dGetWord(x) UNALIGNED_GET_WORD(MEMORY_mem+(x), memory_read_word_stat)
#define MEMORY_dPutWord(x, y) UNALIGNED_PUT_WORD(MEMORY_mem+(x), (y), memory_write_word_stat)
#define MEMORY_dGetWordAligned(x) UNALIGNED_GET_WORD(MEMORY_mem+(x), memory_read_aligned_word_stat)
#define MEMORY_dPutWordAligned(x, y) UNALIGNED_PUT_WORD(MEMORY_mem+(x), (y), memory_write_aligned_word_stat)
#else /* WORDS_UNALIGNED_OK */
#define MEMORY_dGetWord(x) (MEMORY_mem[x] + (MEMORY_mem[(x) + 1] << 8))
#define MEMORY_dPutWord(x, y) (MEMORY_mem[x] = (UBYTE) (y), MEMORY_mem[(x) + 1] = (UBYTE) ((y) >> 8))
+115 -84
View File
@@ -95,24 +95,25 @@ typedef struct {
UWORD addr;
} symtable_rec;
/* Symbol names taken from atari.equ - part of disassembler by Erich Bacher
and from antic.h, gtia.h, pia.h and pokey.h.
/* Symbol names taken from:
- XL OS sources, Atari Home Computer System - Operating System Manual - XL Addendum
- BASIC sources, The Atari BASIC Source Book
Symbols must be sorted by address. If the address has different names
when reading/writing to it, put the read name first. */
static const symtable_rec symtable_builtin[] = {
{"NGFLAG", 0x0001}, {"CASINI", 0x0002}, {"CASINI+1",0x0003}, {"RAMLO", 0x0004},
{"RAMLO+1", 0x0005}, {"TRAMSZ", 0x0006}, {"CMCMD", 0x0007}, {"WARMST", 0x0008},
{"BOOT", 0x0009}, {"DOSVEC", 0x000a}, {"DOSVEC+1",0x000b}, {"DOSINI", 0x000c},
{"DOSINI+1",0x000d}, {"APPMHI", 0x000e}, {"APPMHI+1",0x000f}, {"POKMSK", 0x0010},
{"BRKKEY", 0x0011}, {"RTCLOK", 0x0012}, {"RTCLOK+1",0x0013}, {"RTCLOK+2",0x0014},
{"BUFADR", 0x0015}, {"BUFADR+1",0x0016}, {"ICCOMT", 0x0017}, {"DSKFMS", 0x0018},
{"DSKFMS+1",0x0019}, {"DSKUTL", 0x001a}, {"DSKUTL+1",0x001b}, {"ABUFPT", 0x001c},
{"ABUFPT+1",0x001d}, {"ABUFPT+2",0x001e}, {"ABUFPT+3",0x001f},
{"LNFLG", 0x0000}, {"NGFLAG", 0x0001}, {"CASINI", 0x0002}, {"CASINI+1",0x0003},
{"RAMLO", 0x0004}, {"RAMLO+1", 0x0005}, {"TRAMSZ", 0x0006}, {"CMCMD", 0x0007},
{"WARMST", 0x0008}, {"BOOT?", 0x0009}, {"DOSVEC", 0x000a}, {"DOSVEC+1",0x000b},
{"DOSINI", 0x000c}, {"DOSINI+1",0x000d}, {"APPMHI", 0x000e}, {"APPMHI+1",0x000f},
{"POKMSK", 0x0010}, {"BRKKEY", 0x0011}, {"RTCLOK", 0x0012}, {"RTCLOK+1",0x0013},
{"RTCLOK+2",0x0014}, {"BUFADR", 0x0015}, {"BUFADR+1",0x0016}, {"ICCOMT", 0x0017},
{"DSKFMS", 0x0018}, {"DSKFMS+1",0x0019}, {"DSKUTL", 0x001a}, {"DSKUTL+1",0x001b},
{"ABUFPT", 0x001c}, {"ABUFPT+1",0x001d}, {"ABUFPT+2",0x001e}, {"ABUFPT+3",0x001f},
{"ICHIDZ", 0x0020}, {"ICDNOZ", 0x0021}, {"ICCOMZ", 0x0022}, {"ICSTAZ", 0x0023},
{"ICBALZ", 0x0024}, {"ICBAHZ", 0x0025}, {"ICPTLZ", 0x0026}, {"ICPTHZ", 0x0027},
{"ICBLLZ", 0x0028}, {"ICBLHZ", 0x0029}, {"ICAX1Z", 0x002a}, {"ICAX2Z", 0x002b},
{"ICAX3Z", 0x002c}, {"ICAX4Z", 0x002d}, {"ICAX5Z", 0x002e}, {"ICAX6Z", 0x002f},
{"ICSPRZ", 0x002c}, {"ICSPRZ+1",0x002d}, {"ICIDNO", 0x002e}, {"CIOCHR", 0x002f},
{"STATUS", 0x0030}, {"CHKSUM", 0x0031}, {"BUFRLO", 0x0032}, {"BUFRHI", 0x0033},
{"BFENLO", 0x0034}, {"BFENHI", 0x0035}, {"LTEMP", 0x0036}, {"LTEMP+1", 0x0037},
{"BUFRFL", 0x0038}, {"RECVDN", 0x0039}, {"XMTDON", 0x003a}, {"CHKSNT", 0x003b},
@@ -121,38 +122,50 @@ static const symtable_rec symtable_builtin[] = {
{"FMSZPG+1",0x0044}, {"FMSZPG+2",0x0045}, {"FMSZPG+3",0x0046}, {"FMSZPG+4",0x0047},
{"FMSZPG+5",0x0048}, {"FMSZPG+6",0x0049}, {"ZCHAIN", 0x004a}, {"ZCHAIN+1",0x004b},
{"DSTAT", 0x004c}, {"ATRACT", 0x004d}, {"DRKMSK", 0x004e}, {"COLRSH", 0x004f},
{"TEMP", 0x0050}, {"HOLD1", 0x0051}, {"LMARGN", 0x0052}, {"RMARGN", 0x0053},
{"TMPCHR", 0x0050}, {"HOLD1", 0x0051}, {"LMARGN", 0x0052}, {"RMARGN", 0x0053},
{"ROWCRS", 0x0054}, {"COLCRS", 0x0055}, {"COLCRS+1",0x0056}, {"DINDEX", 0x0057},
{"SAVMSC", 0x0058}, {"SAVMSC+1",0x0059}, {"OLDROW", 0x005a}, {"OLDCOL", 0x005b},
{"OLDCOL+1",0x005c}, {"OLDCHR", 0x005d}, {"OLDADR", 0x005e}, {"OLDADR+1",0x005f},
{"FKDEF", 0x0060}, {"FKDEF+1", 0x0061}, {"PALNTS", 0x0062}, {"LOGCOL", 0x0063},
{"ADRESS", 0x0064}, {"ADRESS+1",0x0065}, {"MLTTMP", 0x0066}, {"MLTTMP+1",0x0067},
{"ADRESS", 0x0064}, {"ADRESS+1",0x0065}, {"TOADR", 0x0066}, {"TOADR+1", 0x0067},
{"SAVADR", 0x0068}, {"SAVADR+1",0x0069}, {"RAMTOP", 0x006a}, {"BUFCNT", 0x006b},
{"BUFSTR", 0x006c}, {"BUFSTR+1",0x006d}, {"BITMSK", 0x006e}, {"SHFAMT", 0x006f},
{"ROWAC", 0x0070}, {"ROWAC+1", 0x0071}, {"COLAC", 0x0072}, {"COLAC+1", 0x0073},
{"ENDPT", 0x0074}, {"ENDPT+1", 0x0075}, {"DELTAR", 0x0076}, {"DELTAC", 0x0077},
{"DELTAC+1",0x0078}, {"KEYDEF", 0x0079}, {"KEYDEF+1",0x007a}, {"SWPFLG", 0x007b},
{"HOLDCH", 0x007c}, {"INSDAT", 0x007d}, {"COUNTR", 0x007e}, {"COUNTR+1",0x007f},
{"LOMEM", 0x0080}, {"LOMEM+1", 0x0081}, {"VNTP", 0x0082}, {"VNTP+1", 0x0083},
{"VNTD", 0x0084}, {"VNTD+1", 0x0085}, {"VVTP", 0x0086}, {"VVTP+1", 0x0087},
{"STMTAB", 0x0088}, {"STMTAB+1",0x0089}, {"STMCUR", 0x008a}, {"STMCUR+1",0x008b},
{"STARP", 0x008c}, {"STARP+1", 0x008d}, {"RUNSTK", 0x008e}, {"RUNSTK+1",0x008f},
{"TOPSTK", 0x0090}, {"TOPSTK+1",0x0091}, {"MEOLFLG", 0x0092}, {"POKADR", 0x0095},
{"POKADR+1",0x0096}, {"DATAD", 0x00b6}, {"DATALN", 0x00b7}, {"DATALN+1",0x00b8},
{"STOPLN", 0x00ba}, {"STOPLN+1",0x00bb}, {"SAVCUR", 0x00be}, {"IOCMD", 0x00c0},
{"IODVC", 0x00c1}, {"PROMPT", 0x00c2}, {"ERRSAVE", 0x00c3}, {"COLOR", 0x00c8},
{"PTABW", 0x00c9}, {"LOADFLG", 0x00ca}, {"FR0", 0x00d4}, {"FR0+1", 0x00d5},
{"FR0+2", 0x00d6}, {"FR0+3", 0x00d7}, {"FR0+4", 0x00d8}, {"FR0+5", 0x00d9},
{"FRE", 0x00da}, {"FRE+1", 0x00db}, {"FRE+2", 0x00dc}, {"FRE+3", 0x00dd},
{"FRE+4", 0x00de}, {"FRE+5", 0x00df}, {"FR1", 0x00e0}, {"FR1+1", 0x00e1},
{"FR1+2", 0x00e2}, {"FR1+3", 0x00e3}, {"FR1+4", 0x00e4}, {"FR1+5", 0x00e5},
{"FR2", 0x00e6}, {"FR2+1", 0x00e7}, {"FR2+2", 0x00e8}, {"FR2+3", 0x00e9},
{"FR2+4", 0x00ea}, {"FR2+5", 0x00eb}, {"FRX", 0x00ec}, {"EEXP", 0x00ed},
{"NSIGN", 0x00ee}, {"ESIGN", 0x00ef}, {"FCHRFLG", 0x00f0}, {"DIGRT", 0x00f1},
{"CIX", 0x00f2}, {"INBUFF", 0x00f3}, {"INBUFF+1",0x00f4}, {"ZTEMP1", 0x00f5},
{"ZTEMP1+1",0x00f6}, {"ZTEMP4", 0x00f7}, {"ZTEMP4+1",0x00f8}, {"ZTEMP3", 0x00f9},
{"ZTEMP3+1",0x00fa}, {"RADFLG", 0x00fb}, {"FLPTR", 0x00fc}, {"FLPTR+1", 0x00fd},
{"FPTR2", 0x00fe}, {"FPTR2+1", 0x00ff},
{"MEMTOP", 0x0090}, {"MEMTOP+1",0x0091}, {"MEOLFLG", 0x0092},
{"COX", 0x0094}, {"POKADR", 0x0095}, {"POKADR+1",0x0096}, {"SVESA", 0x0097},
{"SVESA+1", 0x0098}, {"MVFA", 0x0099}, {"MVFA+1", 0x009a}, {"MVTA", 0x009b},
{"MVTA+1", 0x009c}, {"CPC", 0x009d}, {"CPC+1", 0x009e}, {"LLNGTH", 0x009f},
{"TSLNUM", 0x00a0}, {"TSLNUM+1",0x00a1}, {"MVLNG", 0x00a2}, {"MVLNG+1", 0x00a3},
{"ECSIZE", 0x00a4}, {"ECSIZE+1",0x00a5}, {"DIRFLG", 0x00a6}, {"STMLBD", 0x00a7},
{"STINDEX", 0x00a8}, {"OPSTKX", 0x00a9}, {"ARSTKX", 0x00aa}, {"EXSVOP", 0x00ab},
{"EXSVPR", 0x00ac}, {"LELNUM", 0x00ad}, {"LELNUM+1",0x00ae}, {"STENUM", 0x00af},
{"COMCNT", 0x00b0}, {"ADFLAG", 0x00b1}, {"SVDISP", 0x00b2}, {"ONLOOP", 0x00b3},
{"ENTDTD", 0x00b4}, {"LISTDTD", 0x00b5}, {"DATAD", 0x00b6}, {"DATALN", 0x00b7},
{"DATALN+1",0x00b8}, {"ERRNUM", 0x00b9}, {"STOPLN", 0x00ba}, {"STOPLN+1",0x00bb},
{"TRAPLN", 0x00bc}, {"TRAPLN+1",0x00bd}, {"SAVCUR", 0x00be}, {"SAVCUR+1",0x00bf},
{"IOCMD", 0x00c0}, {"IODVC", 0x00c1}, {"PROMPT", 0x00c2}, {"ERRSAV", 0x00c3},
{"TEMPA", 0x00c4}, {"TEMPA+1", 0x00c5}, {"ZTEMP2", 0x00c6}, {"ZTEMP2+1",0x00c7},
{"COLOR", 0x00c8}, {"PTABW", 0x00c9}, {"LOADFLG", 0x00ca},
{"VTYPE", 0x00d2}, {"VNUM", 0x00d3},
{"FR0", 0x00d4}, {"FR0+1", 0x00d5}, {"FR0+2", 0x00d6}, {"FR0+3", 0x00d7},
{"FR0+4", 0x00d8}, {"FR0+5", 0x00d9}, {"FRE", 0x00da}, {"FRE+1", 0x00db},
{"FRE+2", 0x00dc}, {"FRE+3", 0x00dd}, {"FRE+4", 0x00de}, {"FRE+5", 0x00df},
{"FR1", 0x00e0}, {"FR1+1", 0x00e1}, {"FR1+2", 0x00e2}, {"FR1+3", 0x00e3},
{"FR1+4", 0x00e4}, {"FR1+5", 0x00e5}, {"FR2", 0x00e6}, {"FR2+1", 0x00e7},
{"FR2+2", 0x00e8}, {"FR2+3", 0x00e9}, {"FR2+4", 0x00ea}, {"FR2+5", 0x00eb},
{"FRX", 0x00ec}, {"EEXP", 0x00ed}, {"NSIGN", 0x00ee}, {"ESIGN", 0x00ef},
{"FCHRFLG", 0x00f0}, {"DIGRT", 0x00f1}, {"CIX", 0x00f2}, {"INBUFF", 0x00f3},
{"INBUFF+1",0x00f4}, {"ZTEMP1", 0x00f5}, {"ZTEMP1+1",0x00f6}, {"ZTEMP4", 0x00f7},
{"ZTEMP4+1",0x00f8}, {"ZTEMP3", 0x00f9}, {"ZTEMP3+1",0x00fa}, {"RADFLG", 0x00fb},
{"FLPTR", 0x00fc}, {"FLPTR+1", 0x00fd}, {"FPTR2", 0x00fe}, {"FPTR2+1", 0x00ff},
{"VDSLST", 0x0200}, {"VDSLST+1",0x0201}, {"VPRCED", 0x0202}, {"VPRCED+1",0x0203},
{"VINTER", 0x0204}, {"VINTER+1",0x0205}, {"VBREAK", 0x0206}, {"VBREAK+1",0x0207},
@@ -166,60 +179,60 @@ static const symtable_rec symtable_builtin[] = {
{"VVBLKD", 0x0224}, {"VVBLKD+1",0x0225}, {"CDTMA1", 0x0226}, {"CDTMA1+1",0x0227},
{"CDTMA2", 0x0228}, {"CDTMA2+1",0x0229}, {"CDTMF3", 0x022a}, {"SRTIMR", 0x022b},
{"CDTMF4", 0x022c}, {"INTEMP", 0x022d}, {"CDTMF5", 0x022e}, {"SDMCTL", 0x022f},
{"SDLSTL", 0x0230}, {"SDLSTH", 0x0231}, {"SSKCTL", 0x0232}, {"SPARE", 0x0233},
{"SDLSTL", 0x0230}, {"SDLSTH", 0x0231}, {"SSKCTL", 0x0232}, {"LCOUNT", 0x0233},
{"LPENH", 0x0234}, {"LPENV", 0x0235}, {"BRKKY", 0x0236}, {"BRKKY+1", 0x0237},
{"VPIRQ", 0x0238}, {"VPIRQ+1", 0x0239}, {"CDEVIC", 0x023a}, {"CCOMND", 0x023b},
{"CAUX1", 0x023c}, {"CAUX2", 0x023d}, {"TMPSIO", 0x023e}, {"ERRFLG", 0x023f},
{"CAUX1", 0x023c}, {"CAUX2", 0x023d}, {"TEMP", 0x023e}, {"ERRFLG", 0x023f},
{"DFLAGS", 0x0240}, {"DBSECT", 0x0241}, {"BOOTAD", 0x0242}, {"BOOTAD+1",0x0243},
{"COLDST", 0x0244}, {"RECLEN", 0x0245}, {"DSKTIM", 0x0246}, {"PDVMSK", 0x0247},
{"SHPDVS", 0x0248}, {"PDMSK", 0x0249}, {"RELADR", 0x024a}, {"RELADR+1",0x024b},
{"PPTMPA", 0x024c}, {"PPTMPX", 0x024d}, {"CHSALT", 0x026b}, {"VSFLAG", 0x026c},
{"KEYDIS", 0x026d}, {"FINE", 0x026e}, {"GPRIOR", 0x026f}, {"PADDL0", 0x0270},
{"PADDL1", 0x0271}, {"PADDL2", 0x0272}, {"PADDL3", 0x0273}, {"PADDL4", 0x0274},
{"PADDL5", 0x0275}, {"PADDL6", 0x0276}, {"PADDL7", 0x0277}, {"STICK0", 0x0278},
{"STICK1", 0x0279}, {"STICK2", 0x027a}, {"STICK3", 0x027b}, {"PTRIG0", 0x027c},
{"PTRIG1", 0x027d}, {"PTRIG2", 0x027e}, {"PTRIG3", 0x027f}, {"PTRIG4", 0x0280},
{"PTRIG5", 0x0281}, {"PTRIG6", 0x0282}, {"PTRIG7", 0x0283}, {"STRIG0", 0x0284},
{"STRIG1", 0x0285}, {"STRIG2", 0x0286}, {"STRIG3", 0x0287}, {"HIBYTE", 0x0288},
{"WMODE", 0x0289}, {"BLIM", 0x028a}, {"IMASK", 0x028b}, {"JVECK", 0x028c},
{"NEWADR", 0x028e}, {"TXTROW", 0x0290}, {"TXTCOL", 0x0291}, {"TXTCOL+1",0x0292},
{"TINDEX", 0x0293}, {"TXTMSC", 0x0294}, {"TXTMSC+1",0x0295}, {"TXTOLD", 0x0296},
{"TXTOLD+1",0x0297}, {"TXTOLD+2",0x0298}, {"TXTOLD+3",0x0299}, {"TXTOLD+4",0x029a},
{"TXTOLD+5",0x029b}, {"CRETRY", 0x029c}, {"HOLD3", 0x029d}, {"SUBTMP", 0x029e},
{"HOLD2", 0x029f}, {"DMASK", 0x02a0}, {"TMPLBT", 0x02a1}, {"ESCFLG", 0x02a2},
{"TABMAP", 0x02a3}, {"TABMAP+1",0x02a4}, {"TABMAP+2",0x02a5}, {"TABMAP+3",0x02a6},
{"TABMAP+4",0x02a7}, {"TABMAP+5",0x02a8}, {"TABMAP+6",0x02a9}, {"TABMAP+7",0x02aa},
{"TABMAP+8",0x02ab}, {"TABMAP+9",0x02ac}, {"TABMAP+A",0x02ad}, {"TABMAP+B",0x02ae},
{"TABMAP+C",0x02af}, {"TABMAP+D",0x02b0}, {"TABMAP+E",0x02b1}, {"LOGMAP", 0x02b2},
{"LOGMAP+1",0x02b3}, {"LOGMAP+2",0x02b4}, {"LOGMAP+3",0x02b5}, {"INVFLG", 0x02b6},
{"FILFLG", 0x02b7}, {"TMPROW", 0x02b8}, {"TMPCOL", 0x02b9}, {"TMPCOL+1",0x02ba},
{"SCRFLG", 0x02bb}, {"HOLD4", 0x02bc}, {"DRETRY", 0x02bd}, {"SHFLOC", 0x02be},
{"BOTSCR", 0x02bf}, {"PCOLR0", 0x02c0}, {"PCOLR1", 0x02c1}, {"PCOLR2", 0x02c2},
{"PCOLR3", 0x02c3}, {"COLOR0", 0x02c4}, {"COLOR1", 0x02c5}, {"COLOR2", 0x02c6},
{"COLOR3", 0x02c7}, {"COLOR4", 0x02c8}, {"RUNADR", 0x02c9}, {"RUNADR+1",0x02ca},
{"HIUSED", 0x02cb}, {"HIUSED+1",0x02cc}, {"ZHIUSE", 0x02cd}, {"ZHIUSE+1",0x02ce},
{"GBYTEA", 0x02cf}, {"GBYTEA+1",0x02d0}, {"LOADAD", 0x02d1}, {"LOADAD+1",0x02d2},
{"ZLOADA", 0x02d3}, {"ZLOADA+1",0x02d4}, {"DSCTLN", 0x02d5}, {"DSCTLN+1",0x02d6},
{"ACMISR", 0x02d7}, {"ACMISR+1",0x02d8}, {"KRPDER", 0x02d9}, {"KEYREP", 0x02da},
{"NOCLIK", 0x02db}, {"HELPFG", 0x02dc}, {"DMASAV", 0x02dd}, {"PBPNT", 0x02de},
{"PBUFSZ", 0x02df}, {"RUNAD", 0x02e0}, {"RUNAD+1", 0x02e1}, {"INITAD", 0x02e2},
{"INITAD+1",0x02e3}, {"RAMSIZ", 0x02e4}, {"MEMTOP", 0x02e5}, {"MEMTOP+1",0x02e6},
{"MEMLO", 0x02e7}, {"MEMLO+1", 0x02e8}, {"HNDLOD", 0x02e9}, {"DVSTAT", 0x02ea},
{"DVSTAT+1",0x02eb}, {"DVSTAT+2",0x02ec}, {"DVSTAT+3",0x02ed}, {"CBAUDL", 0x02ee},
{"CBAUDH", 0x02ef}, {"CRSINH", 0x02f0}, {"KEYDEL", 0x02f1}, {"CH1", 0x02f2},
{"CHACT", 0x02f3}, {"CHBAS", 0x02f4}, {"NEWROW", 0x02f5}, {"NEWCOL", 0x02f6},
{"NEWCOL+1",0x02f7}, {"ROWINC", 0x02f8}, {"COLINC", 0x02f9}, {"CHAR", 0x02fa},
{"ATACHR", 0x02fb}, {"CH", 0x02fc}, {"FILDAT", 0x02fd}, {"DSPFLG", 0x02fe},
{"SSFLAG", 0x02ff},
{"SHPDVS", 0x0248}, {"PDIMSK", 0x0249}, {"RELADR", 0x024a}, {"RELADR+1",0x024b},
{"PPTMPA", 0x024c}, {"PPTMPX", 0x024d}, {"CHSALT", 0x026b},
{"VSFLAG", 0x026c}, {"KEYDIS", 0x026d}, {"FINE", 0x026e}, {"GPRIOR", 0x026f},
{"PADDL0", 0x0270}, {"PADDL1", 0x0271}, {"PADDL2", 0x0272}, {"PADDL3", 0x0273},
{"PADDL4", 0x0274}, {"PADDL5", 0x0275}, {"PADDL6", 0x0276}, {"PADDL7", 0x0277},
{"STICK0", 0x0278}, {"STICK1", 0x0279}, {"STICK2", 0x027a}, {"STICK3", 0x027b},
{"PTRIG0", 0x027c}, {"PTRIG1", 0x027d}, {"PTRIG2", 0x027e}, {"PTRIG3", 0x027f},
{"PTRIG4", 0x0280}, {"PTRIG5", 0x0281}, {"PTRIG6", 0x0282}, {"PTRIG7", 0x0283},
{"STRIG0", 0x0284}, {"STRIG1", 0x0285}, {"STRIG2", 0x0286}, {"STRIG3", 0x0287},
{"HIBYTE", 0x0288}, {"WMODE", 0x0289}, {"BLIM", 0x028a}, {"IMASK", 0x028b},
{"JVECK", 0x028c}, {"JVECK+1", 0x028d}, {"NEWADR", 0x028e}, {"NEWADR+1",0x028f},
{"TXTROW", 0x0290}, {"TXTCOL", 0x0291}, {"TXTCOL+1",0x0292}, {"TINDEX", 0x0293},
{"TXTMSC", 0x0294}, {"TXTMSC+1",0x0295}, {"TXTOLD", 0x0296}, {"TXTOLD+1",0x0297},
{"TXTOLD+2",0x0298}, {"TXTOLD+3",0x0299}, {"TXTOLD+4",0x029a}, {"TXTOLD+5",0x029b},
{"CRETRY", 0x029c}, {"HOLD3", 0x029d}, {"SUBTMP", 0x029e}, {"HOLD2", 0x029f},
{"DMASK", 0x02a0}, {"TMPLBT", 0x02a1}, {"ESCFLG", 0x02a2}, {"TABMAP", 0x02a3},
{"TABMAP+1",0x02a4}, {"TABMAP+2",0x02a5}, {"TABMAP+3",0x02a6}, {"TABMAP+4",0x02a7},
{"TABMAP+5",0x02a8}, {"TABMAP+6",0x02a9}, {"TABMAP+7",0x02aa}, {"TABMAP+8",0x02ab},
{"TABMAP+9",0x02ac}, {"TABMAP+A",0x02ad}, {"TABMAP+B",0x02ae}, {"TABMAP+C",0x02af},
{"TABMAP+D",0x02b0}, {"TABMAP+E",0x02b1}, {"LOGMAP", 0x02b2}, {"LOGMAP+1",0x02b3},
{"LOGMAP+2",0x02b4}, {"LOGMAP+3",0x02b5}, {"INVFLG", 0x02b6}, {"FILFLG", 0x02b7},
{"TMPROW", 0x02b8}, {"TMPCOL", 0x02b9}, {"TMPCOL+1",0x02ba}, {"SCRFLG", 0x02bb},
{"HOLD4", 0x02bc}, {"DRETRY", 0x02bd}, {"SHFLOK", 0x02be}, {"BOTSCR", 0x02bf},
{"PCOLR0", 0x02c0}, {"PCOLR1", 0x02c1}, {"PCOLR2", 0x02c2}, {"PCOLR3", 0x02c3},
{"COLOR0", 0x02c4}, {"COLOR1", 0x02c5}, {"COLOR2", 0x02c6}, {"COLOR3", 0x02c7},
{"COLOR4", 0x02c8}, {"RUNADR", 0x02c9}, {"RUNADR+1",0x02ca}, {"HIUSED", 0x02cb},
{"HIUSED+1",0x02cc}, {"ZHIUSE", 0x02cd}, {"ZHIUSE+1",0x02ce}, {"GBYTEA", 0x02cf},
{"GBYTEA+1",0x02d0}, {"LOADAD", 0x02d1}, {"LOADAD+1",0x02d2}, {"ZLOADA", 0x02d3},
{"ZLOADA+1",0x02d4}, {"DSCTLN", 0x02d5}, {"DSCTLN+1",0x02d6}, {"ACMISR", 0x02d7},
{"ACMISR+1",0x02d8}, {"KRPDEL", 0x02d9}, {"KEYREP", 0x02da}, {"NOCLIK", 0x02db},
{"HELPFG", 0x02dc}, {"DMASAV", 0x02dd}, {"PBPNT", 0x02de}, {"PBUFSZ", 0x02df},
{"RUNAD", 0x02e0}, {"RUNAD+1", 0x02e1}, {"INITAD", 0x02e2}, {"INITAD+1",0x02e3},
{"RAMSIZ", 0x02e4}, {"MEMTOP", 0x02e5}, {"MEMTOP+1",0x02e6}, {"MEMLO", 0x02e7},
{"MEMLO+1", 0x02e8}, {"HNDLOD", 0x02e9}, {"DVSTAT", 0x02ea}, {"DVSTAT+1",0x02eb},
{"DVSTAT+2",0x02ec}, {"DVSTAT+3",0x02ed}, {"CBAUDL", 0x02ee}, {"CBAUDH", 0x02ef},
{"CRSINH", 0x02f0}, {"KEYDEL", 0x02f1}, {"CH1", 0x02f2}, {"CHACT", 0x02f3},
{"CHBAS", 0x02f4}, {"NEWROW", 0x02f5}, {"NEWCOL", 0x02f6}, {"NEWCOL+1",0x02f7},
{"ROWINC", 0x02f8}, {"COLINC", 0x02f9}, {"CHAR", 0x02fa}, {"ATACHR", 0x02fb},
{"CH", 0x02fc}, {"FILDAT", 0x02fd}, {"DSPFLG", 0x02fe}, {"SSFLAG", 0x02ff},
{"DDEVIC", 0x0300}, {"DUNIT", 0x0301}, {"DCOMND", 0x0302}, {"DSTATS", 0x0303},
{"DBUFLO", 0x0304}, {"DBUFHI", 0x0305}, {"DTIMLO", 0x0306}, {"DUNUSE", 0x0307},
{"DBYTLO", 0x0308}, {"DBYTHI", 0x0309}, {"DAUX1", 0x030a}, {"DAUX2", 0x030b},
{"TIMER1", 0x030c}, {"TIMER1+1",0x030d}, {"ADDCOR", 0x030e}, {"CASFLG", 0x030f},
{"TIMER2", 0x0310}, {"TIMER2+1",0x0311}, {"TEMP1", 0x0312}, {"TEMP1+1", 0x0313},
{"TEMP2", 0x0314}, {"TEMP3", 0x0315}, {"SAVIO", 0x0316}, {"TIMFLG", 0x0317},
{"TIMER2", 0x0310}, {"TIMER2+1",0x0311}, {"TEMP1", 0x0312}, {"TEMP2", 0x0313},
{"PTIMOT", 0x0314}, {"TEMP3", 0x0315}, {"SAVIO", 0x0316}, {"TIMFLG", 0x0317},
{"STACKP", 0x0318}, {"TSTAT", 0x0319}, {"HATABS", 0x031a}, /* HATABS 1-34 */
{"PUTBT1", 0x033d}, {"PUTBT2", 0x033e}, {"PUTBT3", 0x033f},
{"PUPBT1", 0x033d}, {"PUPBT2", 0x033e}, {"PUPBT3", 0x033f},
{"B0-ICHID",0x0340}, {"B0-ICDNO",0x0341}, {"B0-ICCOM",0x0342}, {"B0-ICSTA",0x0343},
{"B0-ICBAL",0x0344}, {"B0-ICBAH",0x0345}, {"B0-ICPTL",0x0346}, {"B0-ICPTH",0x0347},
{"B0-ICBLL",0x0348}, {"B0-ICBLH",0x0349}, {"B0-ICAX1",0x034a}, {"B0-ICAX2",0x034b},
@@ -258,6 +271,12 @@ static const symtable_rec symtable_builtin[] = {
{"BASICF", 0x03f8}, {"MINTLK", 0x03f9}, {"GINTLK", 0x03fa}, {"CHLINK", 0x03fb},
{"CHLINK+1",0x03fc}, {"CASBUF", 0x03fd},
{"R-CARTCS",0x9ffa}, {"R-CARTCS+1",0x9ffb},
{"R-CART", 0x9ffc}, {"R-CARTFG", 0x9ffd}, {"R-CARTAD",0x9ffe}, {"R-CARTAD+1",0x9fff},
{"CARTCS", 0xbffa}, {"CARTCS+1",0xbffb},
{"CART", 0xbffc}, {"CARTFG", 0xbffd}, {"CARTAD", 0xbffe}, {"CARTAD+1",0xbfff},
{"M0PF", 0xd000}, {"HPOSP0",0xd000}, {"M1PF", 0xd001}, {"HPOSP1",0xd001},
{"M2PF", 0xd002}, {"HPOSP2",0xd002}, {"M3PF", 0xd003}, {"HPOSP3",0xd003},
{"P0PF", 0xd004}, {"HPOSM0",0xd004}, {"P1PF", 0xd005}, {"HPOSM1",0xd005},
@@ -273,12 +292,14 @@ static const symtable_rec symtable_builtin[] = {
{"COLPF2",0xd018}, {"COLPF3",0xd019}, {"COLBK", 0xd01a}, {"PRIOR", 0xd01b},
{"VDELAY",0xd01c}, {"GRACTL",0xd01d}, {"HITCLR",0xd01e}, {"CONSOL",0xd01f},
{"PBI", 0xd100}, /* PBI 1-254 */ {"PDVI", 0xd1ff}, {"PDVS", 0xd1ff},
{"POT0", 0xd200}, {"AUDF1", 0xd200}, {"POT1", 0xd201}, {"AUDC1", 0xd201},
{"POT2", 0xd202}, {"AUDF2", 0xd202}, {"POT3", 0xd203}, {"AUDC2", 0xd203},
{"POT4", 0xd204}, {"AUDF3", 0xd204}, {"POT5", 0xd205}, {"AUDC3", 0xd205},
{"POT6", 0xd206}, {"AUDF4", 0xd206}, {"POT7", 0xd207}, {"AUDC4", 0xd207},
{"ALLPOT",0xd208}, {"AUDCTL",0xd208}, {"KBCODE",0xd209}, {"STIMER",0xd209},
{"RANDOM",0xd20a}, {"SKREST",0xd20a}, {"POTGO", 0xd20b},
{"RANDOM",0xd20a}, {"SKRES", 0xd20a}, {"POTGO", 0xd20b},
{"SERIN", 0xd20d}, {"SEROUT",0xd20d}, {"IRQST", 0xd20e}, {"IRQEN", 0xd20e},
{"SKSTAT",0xd20f}, {"SKCTL", 0xd20f},
@@ -289,19 +310,29 @@ static const symtable_rec symtable_builtin[] = {
{"WSYNC", 0xd40a}, {"VCOUNT",0xd40b}, {"PENH", 0xd40c}, {"PENV", 0xd40d},
{"NMIEN", 0xd40e}, {"NMIST", 0xd40f}, {"NMIRES",0xd40f},
{"AFP", 0xd800}, {"FASC", 0xd8e6}, {"IFP", 0xd9aa}, {"FPI", 0xd9d2},
{"ZPRO", 0xda44}, {"ZF1", 0xda46}, {"FSUB", 0xda60}, {"FADD", 0xda66},
{"PBIRAM",0xd600}, /* PMIRAM 1-255 */
{"AFP", 0xd800},
{"PDID1", 0xd803}, {"PDIOV", 0xd805}, {"PDIOV+1",0xd806},{"PDIRQV", 0xd808},
{"PDIRQV+1",0xd809}, {"PDID2", 0xd80b}, {"PDVV", 0xd80d},
{"FASC", 0xd8e6}, {"IFP", 0xd9aa}, {"FPI", 0xd9d2},
{"ZFR0", 0xda44}, {"ZF1", 0xda46}, {"FSUB", 0xda60}, {"FADD", 0xda66},
{"FMUL", 0xdadb}, {"FDIV", 0xdb28}, {"PLYEVL",0xdd40}, {"FLD0R", 0xdd89},
{"FLD0R", 0xdd8d}, {"FLD1R", 0xdd98}, {"FLD1P", 0xdd9c}, {"FST0R", 0xdda7},
{"FLD0P", 0xdd8d}, {"FLD1R", 0xdd98}, {"FLD1P", 0xdd9c}, {"FST0R", 0xdda7},
{"FST0P", 0xddab}, {"FMOVE", 0xddb6}, {"EXP", 0xddc0}, {"EXP10", 0xddcc},
{"LOG", 0xdecd}, {"LOG10", 0xded1},
{"DSKINV",0xe453}, {"CIOV", 0xe456}, {"SIOV", 0xe459}, {"SETVBV",0xe45c},
{"SYSVBV",0xe45f}, {"XITVBV",0xe462}, {"SIOINV",0xe465}, {"SENDEV",0xe468},
{"INTINV",0xe46b}, {"CIOINV",0xe46e}, {"SELFSV",0xe471}, {"WARMSV",0xe474},
{"COLDSV",0xe477}, {"RBLOKV",0xe47a}, {"CSOPIV",0xe47d}, {"PUPDIV",0xe480},
{"SELFTSV",0xe483},{"PENTV", 0xe486}, {"PHUNLV",0xe489}, {"PHINIV",0xe48c},
{"GPDVV", 0xe48f},
{"EDITRV",0xe400}, {"SCRENV",0xe410}, {"KEYBDV",0xe420}, {"PRINTV",0xe430},
{"CASETV",0xe440},
{"DINITV",0xe450}, {"DSKINV",0xe453}, {"CIOV", 0xe456}, {"SIOV", 0xe459},
{"SETVBV",0xe45c}, {"SYSVBV",0xe45f}, {"XITVBV",0xe462}, {"SIOINV",0xe465},
{"SENDEV",0xe468}, {"INTINV",0xe46b}, {"CIOINV",0xe46e}, {"BLKBDV",0xe471},
{"WARMSV",0xe474}, {"COLDSV",0xe477}, {"RBLOKV",0xe47a}, {"CSOPIV",0xe47d},
{"PUPDIV",0xe480}, {"SLFTSV",0xe483}, {"PHENTV",0xe486}, {"PHUNLV",0xe489},
{"PHINIV",0xe48c}, {"GPDVV", 0xe48f},
{NULL, 0x0000}
};
@@ -347,7 +378,7 @@ static const symtable_rec symtable_builtin_5200[] = {
{"POT4", 0xe804}, {"AUDF3", 0xe804}, {"POT5", 0xe805}, {"AUDC3", 0xe805},
{"POT6", 0xe806}, {"AUDF4", 0xe806}, {"POT7", 0xe807}, {"AUDC4", 0xe807},
{"ALLPOT",0xe808}, {"AUDCTL",0xe808}, {"KBCODE",0xe809}, {"STIMER",0xe809},
{"RANDOM",0xe80a}, {"SKREST",0xe80a}, {"POTGO", 0xe80b},
{"RANDOM",0xe80a}, {"SKRES", 0xe80a}, {"POTGO", 0xe80b},
{"SERIN", 0xe80d}, {"SEROUT",0xe80d}, {"IRQST", 0xe80e}, {"IRQEN", 0xe80e},
{"SKSTAT",0xe80f}, {"SKCTL", 0xe80f},
+81 -136
View File
@@ -2,7 +2,7 @@
* mzpokeysnd.c - POKEY sound chip emulation, v1.6
*
* Copyright (C) 2002 Michael Borisov
* Copyright (C) 2002-2005 Atari800 development team (see DOC/CREDITS)
* Copyright (C) 2002-2014 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
@@ -36,13 +36,6 @@
#include "remez.h"
#include "antic.h"
#include "gtia.h"
#include "util.h"
#ifdef SYNCHRONIZED_SOUND
#if defined(PBI_XLD) || defined (VOICEBOX)
#include "votraxsnd.h"
#endif
#include "sndsave.h"
#endif
#define CONSOLE_VOL 8
#ifdef NONLINEAR_MIXING
@@ -79,7 +72,6 @@ static const double pokeymix[61+CONSOLE_VOL] = { /* Nonlinear POKEY mixing array
static int num_cur_pokeys = 0;
/* Filter */
static int sample_rate; /* Hz */
static int pokey_frq; /* Hz - for easier resampling */
static int filter_size;
static double filter_data[SND_FILTER_SIZE];
@@ -100,7 +92,6 @@ static const int filter_size_8_8 = 1214;
#endif
/* Flags and quality */
static int snd_flags = 0;
static int snd_quality = 0;
/* Poly tables */
@@ -122,6 +113,11 @@ typedef double qev_t;
typedef unsigned char qev_t;
#endif
#ifdef SYNCHRONIZED_SOUND
static double ticks_per_sample;
static double samp_pos;
#endif /* SYNCHRONIZED_SOUND */
/* State variables for single Pokey Chip */
typedef struct stPokeyState
{
@@ -284,19 +280,6 @@ static void event2_pure(PokeyState* ps, int p5v, int p4v, int p917v);
static int readout3_normal(PokeyState* ps);
static void event3_pure(PokeyState* ps, int p5v, int p4v, int p917v);
#ifdef SYNCHRONIZED_SOUND
static int ticks_per_frame;
static int tick_pos;
static double samp_pos;
static int start_sample;
static double ticks_per_sample;
UBYTE *MZPOKEYSND_process_buffer = NULL;
static void render_to_tick(int last_tick);
#endif
static void ResetPokeyState(PokeyState* ps)
{
/* Poly positions */
@@ -1159,10 +1142,10 @@ static void advance_ticks(PokeyState* ps, int ticks)
static double generate_sample(PokeyState* ps)
{
/*unsigned long ta = (subticks+pokey_frq)/sample_rate;
subticks = (subticks+pokey_frq)%sample_rate;*/
/*unsigned long ta = (subticks+pokey_frq)/POKEYSND_playback_freq;
subticks = (subticks+pokey_frq)%POKEYSND_playback_freq;*/
advance_ticks(ps, pokey_frq/sample_rate);
advance_ticks(ps, pokey_frq/POKEYSND_playback_freq);
return read_resam_all(ps);
}
@@ -1298,7 +1281,19 @@ static void Update_vol_only_sound_mz( void );
/* */
/*****************************************************************************/
void init_mzpokeysnd_sync(void);
#ifdef SYNCHRONIZED_SOUND
static void generate_sync(unsigned int num_ticks);
static void init_syncsound(void)
{
double samples_per_frame = (double)POKEYSND_playback_freq/(Atari800_tv_mode == Atari800_TV_PAL ? Atari800_FPS_PAL : Atari800_FPS_NTSC);
unsigned int ticks_per_frame = Atari800_tv_mode*114;
ticks_per_sample = (double)ticks_per_frame / samples_per_frame;
samp_pos = 0.0;
POKEYSND_GenerateSync = generate_sync;
}
#endif /* SYNCHRONIZED_SOUND */
int MZPOKEYSND_Init(ULONG freq17, int playback_freq, UBYTE num_pokeys,
int flags, int quality
#ifdef __PLUS
@@ -1308,16 +1303,14 @@ int MZPOKEYSND_Init(ULONG freq17, int playback_freq, UBYTE num_pokeys,
{
double cutoff;
sample_rate = playback_freq;
snd_flags = flags;
snd_quality = quality;
POKEYSND_Update = Update_pokey_sound_mz;
POKEYSND_Update_ptr = Update_pokey_sound_mz;
#ifdef SERIO_SOUND
POKEYSND_UpdateSerio = Update_serio_sound_mz;
#endif
#ifdef CONSOLE_SOUND
POKEYSND_UpdateConsol = Update_consol_sound_mz;
POKEYSND_UpdateConsol_ptr = Update_consol_sound_mz;
#endif
#ifdef VOL_ONLY_SOUND
POKEYSND_UpdateVolOnly = Update_vol_only_sound_mz;
@@ -1404,9 +1397,9 @@ int MZPOKEYSND_Init(ULONG freq17, int playback_freq, UBYTE num_pokeys,
break;
#endif
default:
pokey_frq = (int)(((double)pokey_frq_ideal/sample_rate) + 0.5)
* sample_rate;
filter_size = remez_filter_table((double)sample_rate/pokey_frq,
pokey_frq = (int)(((double)pokey_frq_ideal/POKEYSND_playback_freq) + 0.5)
* POKEYSND_playback_freq;
filter_size = remez_filter_table((double)POKEYSND_playback_freq/pokey_frq,
&cutoff, quality);
audible_frq = (int ) (cutoff * pokey_frq);
}
@@ -1426,7 +1419,7 @@ int MZPOKEYSND_Init(ULONG freq17, int playback_freq, UBYTE num_pokeys,
num_cur_pokeys = num_pokeys;
#ifdef SYNCHRONIZED_SOUND
init_mzpokeysnd_sync();
init_syncsound();
#endif
return 0; /* OK */
}
@@ -1976,23 +1969,6 @@ static void Update_c3stop(PokeyState* ps)
}
#endif /*NONLINEAR_MIXING*/
#ifdef SYNCHRONIZED_SOUND
static void Update_synchronized_sound(void)
{
int last_tick = ANTIC_ypos*114+ANTIC_XPOS+1;
int i;
if (last_tick > ticks_per_frame) last_tick = ticks_per_frame; /* XXX it could go past the frame, fix this */
render_to_tick(last_tick); /* only advances to last sample tick */
if (last_tick - tick_pos > 0) {
for (i = 0; i < (int)num_cur_pokeys; i++)
{
/* remaining ticks */
advance_ticks(pokey_states + i, last_tick - tick_pos);
}
tick_pos = last_tick;
}
}
#endif
/*****************************************************************************/
/* Function: Update_pokey_sound_mz() */
/* */
@@ -2009,9 +1985,6 @@ static void Update_pokey_sound_mz(UWORD addr, UBYTE val, UBYTE chip, UBYTE gain)
{
PokeyState* ps = pokey_states+chip;
#ifdef SYNCHRONIZED_SOUND
Update_synchronized_sound();
#endif
switch(addr & 0x0f)
{
case POKEY_OFFSET_AUDF1:
@@ -2433,78 +2406,55 @@ static void mzpokeysnd_process_16(void* sndbuffer, int sndn)
}
#ifdef SYNCHRONIZED_SOUND
void init_mzpokeysnd_sync(void)
static void generate_sync(unsigned int num_ticks)
{
int bytes_per_frame;
double samples_per_frame;
samples_per_frame = (double)sample_rate/((Atari800_tv_mode == Atari800_TV_PAL) ? Atari800_FPS_PAL : Atari800_FPS_NTSC);
ticks_per_frame = Atari800_tv_mode*114;
ticks_per_sample = (double)ticks_per_frame / samples_per_frame;
tick_pos = 0;
bytes_per_frame = (int)ceil(num_cur_pokeys*samples_per_frame*((snd_flags & POKEYSND_BIT16) ? 2:1));
free(MZPOKEYSND_process_buffer);
MZPOKEYSND_process_buffer = (UBYTE *)Util_malloc(bytes_per_frame);
memset(MZPOKEYSND_process_buffer, 0, bytes_per_frame);
tick_pos = 0;
samp_pos = 0.0;
start_sample = 0;
}
double new_samp_pos;
unsigned int ticks;
UBYTE *buffer = POKEYSND_process_buffer + POKEYSND_process_buffer_fill;
UBYTE *buffer_end = POKEYSND_process_buffer + POKEYSND_process_buffer_length;
unsigned int i;
/* render sound into the buffer up to the specified tick position */
static void render_to_tick(int last_tick)
{
int i;
UBYTE *buffer = (UBYTE *)MZPOKEYSND_process_buffer + start_sample*((snd_flags & POKEYSND_BIT16) ? 2 : 1);
for (;;) {
double int_part;
new_samp_pos = samp_pos + ticks_per_sample;
new_samp_pos = modf(new_samp_pos, &int_part);
ticks = (unsigned int)int_part;
if (ticks > num_ticks) {
samp_pos -= num_ticks;
break;
}
if (buffer >= buffer_end)
break;
/* the new sample position is a floating point number that can be
* between two ticks */
double new_samp_pos;
int new_tick_pos;
samp_pos = new_samp_pos;
num_ticks -= ticks;
if (num_cur_pokeys<1)
return ; /* module was not initialized */
for (i = 0; i < num_cur_pokeys; ++i) {
/* advance pokey to the new position and produce a sample */
advance_ticks(pokey_states + i, ticks);
if (POKEYSND_snd_flags & POKEYSND_BIT16) {
*((SWORD *)buffer) = (SWORD)floor(
(interp_read_resam_all(pokey_states + i, samp_pos) - MAX_SAMPLE / 2.0)
* (65535.0 / MAX_SAMPLE / 4 * M_PI * 0.95)
+ 0.5 + 0.5 * rand() / RAND_MAX - 0.25
);
buffer += 2;
}
else
*buffer++ = (UBYTE)floor(
(interp_read_resam_all(pokey_states + i, samp_pos) - MAX_SAMPLE / 2.0)
* (255.0 / MAX_SAMPLE / 4 * M_PI * 0.95)
+ 128 + 0.5 + 0.5 * rand() / RAND_MAX - 0.25
);
}
}
do {
/* advance to the next sample position */
new_samp_pos = samp_pos + ticks_per_sample;
/* the next tick position is the integer part */
new_tick_pos = floor(new_samp_pos);
/* leave the loop if we went past the desired position */
if (new_tick_pos > last_tick) {
break;
}
for (i = 0; i<num_cur_pokeys; i++)
{
/* advance pokey to the new position and produce a sample */
advance_ticks(pokey_states + i, new_tick_pos - tick_pos);
if (snd_flags & POKEYSND_BIT16) ((SWORD *)buffer)[i] = (SWORD)floor((interp_read_resam_all(pokey_states + i, new_samp_pos - new_tick_pos) - MAX_SAMPLE / 2.0)
* (65535.0 / MAX_SAMPLE / 4 * M_PI * 0.95) + 0.5 + 0.5 * rand() / RAND_MAX - 0.25);
else buffer[i] = (UBYTE)floor((interp_read_resam_all(pokey_states + i, new_samp_pos - new_tick_pos) - MAX_SAMPLE / 2.0)
* (255.0 / MAX_SAMPLE / 4 * M_PI * 0.95) + 128 + 0.5 + 0.5 * rand() / RAND_MAX - 0.25);
}
buffer += num_cur_pokeys*((snd_flags & POKEYSND_BIT16) ? 2 : 1 );
samp_pos = new_samp_pos;
tick_pos = new_tick_pos;
} while (1);
/* adjust the starting sample position in the buffer for next time */
start_sample = (buffer - (UBYTE *)MZPOKEYSND_process_buffer)/((snd_flags & POKEYSND_BIT16) ? 2 : 1);
}
int MZPOKEYSND_UpdateProcessBuffer(void)
{
int result;
render_to_tick(ticks_per_frame);
samp_pos = samp_pos - (double)ticks_per_frame;
tick_pos = tick_pos - ticks_per_frame;
result = start_sample;
start_sample = 0;
#if defined(PBI_XLD) || defined (VOICEBOX)
VOTRAXSND_Process(MZPOKEYSND_process_buffer,result);
#endif
#if !defined(__PLUS) && !defined(ASAP)
SndSave_WriteToSoundFile((const unsigned char *)MZPOKEYSND_process_buffer, result);
#endif
return result;
POKEYSND_process_buffer_fill = buffer - POKEYSND_process_buffer;
if (num_ticks > 0) {
/* remaining ticks */
for (i = 0; i < num_cur_pokeys; ++i)
advance_ticks(pokey_states + i, num_ticks);
}
}
#endif /* SYNCHRONIZED_SOUND */
@@ -2549,18 +2499,14 @@ static void Update_serio_sound_mz( int out, UBYTE data )
static void Update_consol_sound_mz( int set )
{
#ifdef SYNCHRONIZED_SOUND
if (!POKEYSND_console_sound_enabled) return;
if (set) { /* The set variable is 0 only in VOL_ONLY_SOUND routines */
Update_synchronized_sound();
pokey_states[0].speaker = GTIA_speaker*CONSOLE_VOL;
pokey_states[0].forcero = 1; /* first chip */
}
#else /* SYNCHRONIZED_SOUND */
#ifdef VOL_ONLY_SOUND
static int prev_atari_speaker=0;
static unsigned int prev_cpu_clock=0;
int d;
if (!POKEYSND_console_sound_enabled) return;
if (set) { /* The set variable is 0 only in VOL_ONLY_SOUND routines */
pokey_states[0].speaker = GTIA_speaker*CONSOLE_VOL;
pokey_states[0].forcero = 1; /* first chip */
}
#elif defined(VOL_ONLY_SOUND)
static int prev_atari_speaker=0;
static unsigned int prev_cpu_clock=0;
int d;
if( !set && POKEYSND_samp_consol_val==0 ) return;
POKEYSND_sampbuf_lastval-=POKEYSND_samp_consol_val;
@@ -2593,8 +2539,7 @@ static void Update_consol_sound_mz( int set )
if( POKEYSND_sampbuf_rptr>=POKEYSND_SAMPBUF_MAX )
POKEYSND_sampbuf_rptr=0;
}
#endif /* VOL_ONLY_SOUND */
#endif /* SYNCHRONIZED_SOUND */
#endif /* !SYNCHRONIZED_SOUND && VOL_ONLY_SOUND */
}
#endif
-6
View File
@@ -1,8 +1,6 @@
#ifndef MZPOKEYSND_H_
#define MZPOKEYSND_H_
#include "config.h"
#include "pokeysnd.h"
#include "atari.h"
int MZPOKEYSND_Init(ULONG freq17,
@@ -15,8 +13,4 @@ int MZPOKEYSND_Init(ULONG freq17,
#endif
);
#ifdef SYNCHRONIZED_SOUND
#endif /* SYNCHRONIZED_SOUND */
int MZPOKEYSND_UpdateProcessBuffer(void);
extern UBYTE *MZPOKEYSND_process_buffer;
#endif /* MZPOKEYSND_H_ */
+87 -6
View File
@@ -3,9 +3,13 @@
#include "config.h"
#include <stdio.h>
#include "atari.h"
#if SUPPORTS_CHANGE_VIDEOMODE
#include "videomode.h"
#endif
#if defined(SOUND) && defined(SOUND_THIN_API)
#include "sound.h"
#endif /* defined(SOUND) && defined(SOUND_THIN_API) */
/* This include file defines prototypes for platform-specific functions. */
@@ -45,6 +49,11 @@ void PLATFORM_PaletteUpdate(void);
void PLATFORM_Sleep(double s);
#endif
#ifdef SUPPORTS_PLATFORM_TIME
/* This function is for those ports that need their own version of sleep */
double PLATFORM_Time(void);
#endif
#ifdef USE_CURSES
void curses_clear_screen(void);
@@ -66,12 +75,6 @@ int PLATFORM_GetRawKey(void);
int PLATFORM_GetKeyName(void);
#endif
#ifdef SYNCHRONIZED_SOUND
/* This function returns a number which is used to adjust the speed
* of execution to synchronize with the sound output */
double PLATFORM_AdjustSpeed(void);
#endif /* SYNCHRONIZED SOUND */
#if SUPPORTS_CHANGE_VIDEOMODE
/* Returns whether the platform-specific code support the given display mode, MODE,
with/without stretching and with/without rotation. */
@@ -91,4 +94,82 @@ int PLATFORM_WindowMaximised(void);
#endif /* SUPPORTS_CHANGE_VIDEOMODE */
#ifdef PLATFORM_MAP_PALETTE
typedef struct PLATFORM_pixel_format_t {
int bpp; /* Current bits per pixel */
ULONG rmask;
ULONG gmask;
ULONG bmask;
} PLATFORM_pixel_format_t;
/* Returns parameters of the current display pixel format. Used when computing
lookup tables used for blitting the Atari screen to display surface. */
void PLATFORM_GetPixelFormat(PLATFORM_pixel_format_t *format);/* Can be 8, 16, 32 */
/* Convert a table of RGB values, PALETTE, of size SIZE, to a display's native
format and store it in the lookup table DEST. */
void PLATFORM_MapRGB(void *dest, int const *palette, int size);
#endif /* PLATFORM_MAP_PALETTE */
#if defined(SOUND) && defined(SOUND_THIN_API)
/* PLATFORM_SoundSetup opens the hardware sound output with parameters
set beforehand in Sound_out. The implementation If the code decides so,
the actual setup with which audio output is opened may differ from the
provided ones. In such case Sound_out will be modified accordingly.
The function returns TRUE if it successfully opened the sound output - in such
case the caller should set Sound_enabled to TRUE. Sound output is initially
paused - caller should call PLATFORM_SoundContinue to start sound output.
When opening failed, the function returns FALSE - in this case the caller
should set Sound_enabled to FALSE and not attempt to generate any sound.
Calling PLATFORM_SoundSetup again with Sound_out unmodified since the
previous call to the function, is guaranteed to not change them further -
after all, they had been determined to be OK (or modified to be OK) at the
previous call.
PLATFORM_SoundSetup may be called multiple times without calling
PLATFORM_SoundExit inbetween. */
int PLATFORM_SoundSetup(Sound_setup_t *setup);
/* PLATFORM_SoundExit is the reverse of PLATFORM_SoundSetup. It closes the
sound output completely.
The function will be called only if the last call to PLATFORM_SoundSetup
returned TRUE (ie. iff Sound_enabled == TRUE). */
void PLATFORM_SoundExit(void);
/* PLATFORM_SoundPause pauses the sound output.
The function will be called only if the last call to PLATFORM_SoundSetup
returned TRUE (ie. iff Sound_enabled == TRUE) and only when sound is
unpaused (ie. after PLATFORM_SoundContinue). */
void PLATFORM_SoundPause(void);
/* PLATFORM_SoundContinue unpauses the sound output.
The function will be called only if the last call to PLATFORM_SoundSetup
returned TRUE (ie. iff Sound_enabled == TRUE) and only when sound is paused
(ie. straight after PLATFORM_SoundSetup or after PLATFORM_SoundPause). */
void PLATFORM_SoundContinue(void);
#ifdef SOUND_CALLBACK
/* Data from sound buffer is sent to output device by calling Sound_Callback
in a separate thread. These two functions must be used in the main thread to
synchronise access to variables accessed by Sound_Callback. */
void PLATFORM_SoundLock(void);
void PLATFORM_SoundUnlock(void);
#else /* !SOUND_CALLBACK */
/* Return number of bytes that can be written to the output device without
blocking. If it is equal or larger than
Sound_out.frag_frames*channels*sample_size, it probably means that sound
underflow has occurred. */
unsigned int PLATFORM_SoundAvailable(void);
/* Write contents of *BUFFER to audio output device. SIZE is the size of BUFFER.
SIZE must not be greater than
Sound_out.frag_frames*Sound_out.channels*Sound_out.sample_size. */
void PLATFORM_SoundWrite(UBYTE const *buffer, unsigned int size);
/* Dummy functions, not needed with no SOUND_CALLBACK. */
#define PLATFORM_SoundLock() {}
#define PLATFORM_SoundUnlock() {}
#endif /* !SOUND_CALLBACK */
#endif /* defined(SOUND) && defined(SOUND_THIN_API) */
#endif /* PLATFORM_H_ */
+165 -13
View File
@@ -2,7 +2,7 @@
* pokeysnd.c - POKEY sound chip emulation, v2.4
*
* Copyright (C) 1996-1998 Ron Fries
* Copyright (C) 1998-2008 Atari800 development team (see DOC/CREDITS)
* Copyright (C) 1998-2014 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
@@ -23,6 +23,8 @@
*/
#include "config.h"
#include <stdlib.h>
#include <math.h>
#ifdef ASAP /* external project, see http://asap.sf.net */
#include "asap_internal.h"
@@ -41,6 +43,7 @@
#endif
#include "antic.h"
#include "gtia.h"
#include "util.h"
#ifdef WORDS_UNALIGNED_OK
# define READ_U32(x) (*(ULONG *) (x))
@@ -173,7 +176,7 @@ void (*POKEYSND_Process_ptr)(void *sndbuffer, int sndn) = null_pokey_process;
static void Update_pokey_sound_rf(UWORD, UBYTE, UBYTE, UBYTE);
static void null_pokey_sound(UWORD addr, UBYTE val, UBYTE chip, UBYTE gain) {}
void (*POKEYSND_Update) (UWORD addr, UBYTE val, UBYTE chip, UBYTE gain)
void (*POKEYSND_Update_ptr) (UWORD addr, UBYTE val, UBYTE chip, UBYTE gain)
= null_pokey_sound;
#ifdef SERIO_SOUND
@@ -186,7 +189,7 @@ int POKEYSND_serio_sound_enabled = 1;
#ifdef CONSOLE_SOUND
static void Update_consol_sound_rf(int set);
static void null_consol_sound(int set) {}
void (*POKEYSND_UpdateConsol)(int set) = null_consol_sound;
void (*POKEYSND_UpdateConsol_ptr)(int set) = null_consol_sound;
int POKEYSND_console_sound_enabled = 1;
#endif
@@ -196,6 +199,22 @@ static void null_vol_only_sound(void) {}
void (*POKEYSND_UpdateVolOnly)(void) = null_vol_only_sound;
#endif
#ifdef SYNCHRONIZED_SOUND
UBYTE *POKEYSND_process_buffer = NULL;
unsigned int POKEYSND_process_buffer_length;
unsigned int POKEYSND_process_buffer_fill;
static unsigned int prev_update_tick;
static void Generate_sync_rf(unsigned int num_ticks);
static void null_generate_sync(unsigned int num_ticks) {}
void (*POKEYSND_GenerateSync)(unsigned int num_ticks) = null_generate_sync;
static double ticks_per_sample;
static double samp_pos;
static int speaker;
static int const CONSOLE_VOL = 32;
#endif /* SYNCHRONIZED_SOUND */
/*****************************************************************************/
/* In my routines, I treat the sample output as another divide by N counter */
/* For better accuracy, the Samp_n_cnt has a fixed binary decimal point */
@@ -242,9 +261,30 @@ void (*POKEYSND_UpdateVolOnly)(void) = null_vol_only_sound;
static int pokeysnd_init_rf(ULONG freq17, int playback_freq,
UBYTE num_pokeys, int flags);
#ifdef VOL_ONLY_SOUND
/* Initialise variables related to volume-only sound. */
static void init_vol_only(void)
{
POKEYSND_sampbuf_rptr = POKEYSND_sampbuf_ptr;
POKEYSND_sampbuf_last = ANTIC_CPU_CLOCK;
POKEYSND_sampbuf_lastval = 0;
POKEYSND_samp_consol_val = 0;
#ifdef STEREO_SOUND
sampbuf_rptr2 = sampbuf_ptr2;
sampbuf_last2 = ANTIC_CPU_CLOCK;
sampbuf_lastval2 = 0;
#endif /* STEREO_SOUND */
}
#endif /* VOL_ONLY_SOUND */
int POKEYSND_DoInit(void)
{
SndSave_CloseSoundFile();
#ifdef VOL_ONLY_SOUND
init_vol_only();
#endif /* VOL_ONLY_SOUND */
if (POKEYSND_enable_new_pokey)
return MZPOKEYSND_Init(snd_freq17, POKEYSND_playback_freq,
POKEYSND_num_pokeys, POKEYSND_snd_flags, mz_quality
@@ -271,6 +311,22 @@ int POKEYSND_Init(ULONG freq17, int playback_freq, UBYTE num_pokeys,
#ifdef __PLUS
mz_clear_regs = clear_regs;
#endif
#ifdef SYNCHRONIZED_SOUND
{
/* A single call to Atari800_Frame may emulate a bit more CPU ticks than the exact number of
ticks per frame (Atari800_tv_mode*114). So we add a few ticks to buffer size just to be safe. */
unsigned int const surplus_ticks = 10;
double samples_per_frame = (double)POKEYSND_playback_freq/(Atari800_tv_mode == Atari800_TV_PAL ? Atari800_FPS_PAL : Atari800_FPS_NTSC);
unsigned int ticks_per_frame = Atari800_tv_mode*114;
unsigned int max_ticks_per_frame = ticks_per_frame + surplus_ticks;
double ticks_per_sample = (double)ticks_per_frame / samples_per_frame;
POKEYSND_process_buffer_length = POKEYSND_num_pokeys * (unsigned int)ceil((double)max_ticks_per_frame / ticks_per_sample) * ((POKEYSND_snd_flags & POKEYSND_BIT16) ? 2:1);
free(POKEYSND_process_buffer);
POKEYSND_process_buffer = (UBYTE *)Util_malloc(POKEYSND_process_buffer_length);
POKEYSND_process_buffer_fill = 0;
prev_update_tick = ANTIC_CPU_CLOCK;
}
#endif /* SYNCHRONIZED_SOUND */
#if defined(PBI_XLD) || defined (VOICEBOX)
VOTRAXSND_Init(playback_freq, num_pokeys, (flags & POKEYSND_BIT16));
@@ -294,17 +350,53 @@ void POKEYSND_Process(void *sndbuffer, int sndn)
#endif
}
#ifdef SYNCHRONIZED_SOUND
static void Update_synchronized_sound(void)
{
POKEYSND_GenerateSync(ANTIC_CPU_CLOCK - prev_update_tick);
prev_update_tick = ANTIC_CPU_CLOCK;
}
int POKEYSND_UpdateProcessBuffer(void)
{
int sndn;
Update_synchronized_sound();
sndn = POKEYSND_process_buffer_fill / ((POKEYSND_snd_flags & POKEYSND_BIT16) ? 2 : 1);
POKEYSND_process_buffer_fill = 0;
#if defined(PBI_XLD) || defined (VOICEBOX)
VOTRAXSND_Process(POKEYSND_process_buffer, sndn);
#endif
#if !defined(__PLUS) && !defined(ASAP)
SndSave_WriteToSoundFile((const unsigned char *)POKEYSND_process_buffer, sndn);
#endif
return sndn;
}
#endif /* SYNCHRONIZED_SOUND */
#ifdef SYNCHRONIZED_SOUND
static void init_syncsound(void)
{
double samples_per_frame = (double)POKEYSND_playback_freq/(Atari800_tv_mode == Atari800_TV_PAL ? Atari800_FPS_PAL : Atari800_FPS_NTSC);
unsigned int ticks_per_frame = Atari800_tv_mode*114;
ticks_per_sample = (double)ticks_per_frame / samples_per_frame;
samp_pos = 0.0;
POKEYSND_GenerateSync = Generate_sync_rf;
speaker = 0;
}
#endif /* SYNCHRONIZED_SOUND */
static int pokeysnd_init_rf(ULONG freq17, int playback_freq,
UBYTE num_pokeys, int flags)
{
UBYTE chan;
POKEYSND_Update = Update_pokey_sound_rf;
POKEYSND_Update_ptr = Update_pokey_sound_rf;
#ifdef SERIO_SOUND
POKEYSND_UpdateSerio = Update_serio_sound_rf;
#endif
#ifdef CONSOLE_SOUND
POKEYSND_UpdateConsol = Update_consol_sound_rf;
POKEYSND_UpdateConsol_ptr = Update_consol_sound_rf;
#endif
#ifdef VOL_ONLY_SOUND
POKEYSND_UpdateVolOnly = Update_vol_only_sound_rf;
@@ -342,6 +434,9 @@ static int pokeysnd_init_rf(ULONG freq17, int playback_freq,
/* set the number of pokey chips currently emulated */
Num_pokeys = num_pokeys;
#ifdef SYNCHRONIZED_SOUND
init_syncsound();
#endif
return 0; /* OK */
}
@@ -365,6 +460,14 @@ static int pokeysnd_init_rf(ULONG freq17, int playback_freq,
/* */
/*****************************************************************************/
void POKEYSND_Update(UWORD addr, UBYTE val, UBYTE chip, UBYTE gain)
{
#ifdef SYNCHRONIZED_SOUND
Update_synchronized_sound();
#endif /* SYNCHRONIZED_SOUND */
POKEYSND_Update_ptr(addr, val, chip, gain);
}
static void Update_pokey_sound_rf(UWORD addr, UBYTE val, UBYTE chip,
UBYTE gain)
{
@@ -721,11 +824,10 @@ static void pokeysnd_process_8(void *sndbuffer, int sndn)
#endif /* STEREO_SOUND */
count--;
} while (count);
/*
#if defined (USE_DOSSOUND)
cur_val += 32 * GTIA_speaker;
#ifdef SYNCHRONIZED_SOUND
cur_val += speaker;
#endif
*/
/* loop until the buffer is filled */
while (n) {
@@ -1163,10 +1265,62 @@ static void pokeysnd_process_16(void *sndbuffer, int sndn)
}
}
#ifdef SYNCHRONIZED_SOUND
static void Generate_sync_rf(unsigned int num_ticks)
{
double new_samp_pos;
unsigned int ticks;
UBYTE *buffer = POKEYSND_process_buffer + POKEYSND_process_buffer_fill;
UBYTE *buffer_end = POKEYSND_process_buffer + POKEYSND_process_buffer_length;
for (;;) {
double int_part;
new_samp_pos = samp_pos + ticks_per_sample;
new_samp_pos = modf(new_samp_pos, &int_part);
ticks = (unsigned int)int_part;
if (ticks > num_ticks) {
samp_pos -= num_ticks;
break;
}
if (buffer >= buffer_end)
break;
samp_pos = new_samp_pos;
num_ticks -= ticks;
if (POKEYSND_snd_flags & POKEYSND_BIT16) {
pokeysnd_process_16(buffer, 1);
buffer += 2 * POKEYSND_num_pokeys;
}
else {
pokeysnd_process_8(buffer, 1);
buffer += POKEYSND_num_pokeys;
}
}
POKEYSND_process_buffer_fill = buffer - POKEYSND_process_buffer;
}
#endif /* SYNCHRONIZED_SOUND */
#ifdef CONSOLE_SOUND
void POKEYSND_UpdateConsol(int set)
{
if (!POKEYSND_console_sound_enabled)
return;
#ifdef SYNCHRONIZED_SOUND
if (set)
Update_synchronized_sound();
#endif /* SYNCHRONIZED_SOUND */
POKEYSND_UpdateConsol_ptr(set);
}
static void Update_consol_sound_rf(int set)
{
#ifdef VOL_ONLY_SOUND
#ifdef SYNCHRONIZED_SOUND
if (set)
speaker = CONSOLE_VOL * GTIA_speaker;
#elif defined(VOL_ONLY_SOUND)
static int prev_atari_speaker = 0;
static unsigned int prev_cpu_clock = 0;
int d;
@@ -1174,8 +1328,6 @@ static void Update_consol_sound_rf(int set)
if (!g_Sound.nDigitized)
return;
#endif
if (!POKEYSND_console_sound_enabled)
return;
if (!set && POKEYSND_samp_consol_val == 0)
return;
@@ -1211,7 +1363,7 @@ static void Update_consol_sound_rf(int set)
if (POKEYSND_sampbuf_rptr >= POKEYSND_SAMPBUF_MAX)
POKEYSND_sampbuf_rptr = 0;
}
#endif /* VOL_ONLY_SOUND */
#endif /* !SYNCHRONIZED_SOUND && VOL_ONLY_SOUND */
}
#endif /* CONSOLE_SOUND */
+12 -2
View File
@@ -92,9 +92,9 @@ extern int POKEYSND_console_sound_enabled;
extern int POKEYSND_bienias_fix;
extern void (*POKEYSND_Process_ptr)(void *sndbuffer, int sndn);
extern void (*POKEYSND_Update)(UWORD addr, UBYTE val, UBYTE /*chip*/, UBYTE gain);
extern void (*POKEYSND_Update_ptr)(UWORD addr, UBYTE val, UBYTE chip, UBYTE gain);
extern void (*POKEYSND_UpdateSerio)(int out, UBYTE data);
extern void (*POKEYSND_UpdateConsol)(int set);
extern void (*POKEYSND_UpdateConsol_ptr)(int set);
extern void (*POKEYSND_UpdateVolOnly)(void);
int POKEYSND_Init(ULONG freq17, int playback_freq, UBYTE num_pokeys,
@@ -103,6 +103,8 @@ int POKEYSND_Init(ULONG freq17, int playback_freq, UBYTE num_pokeys,
, int clear_regs
#endif
);
void POKEYSND_Update(UWORD addr, UBYTE val, UBYTE /*chip*/, UBYTE gain);
void POKEYSND_UpdateConsol(int set);
void POKEYSND_Process(void *sndbuffer, int sndn);
int POKEYSND_DoInit(void);
void POKEYSND_SetMzQuality(int quality);
@@ -123,6 +125,14 @@ extern int POKEYSND_samp_freq;
extern int POKEYSND_samp_consol_val; /* actual value of console sound */
#endif /* VOL_ONLY_SOUND */
#ifdef SYNCHRONIZED_SOUND
extern UBYTE *POKEYSND_process_buffer;
extern unsigned int POKEYSND_process_buffer_length;
extern unsigned int POKEYSND_process_buffer_fill;
extern void (*POKEYSND_GenerateSync)(unsigned int num_ticks);
int POKEYSND_UpdateProcessBuffer(void);
#endif /* SYNCHRONIZED_SOUND */
#ifdef __cplusplus
}
+547
View File
@@ -0,0 +1,547 @@
/*
* sound.c - platform-independent interface for platform-specific sound output.
*
* Copyright (C) 2013 Tomasz Krasuski
* Copyright (C) 2013-2014 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
* Atari800 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Atari800 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 General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with Atari800; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include "sound.h"
#include "atari.h"
#include "log.h"
#include "platform.h"
#include "pokeysnd.h"
#include "util.h"
#define DEBUG 0
int Sound_enabled = 1;
Sound_setup_t Sound_desired = {
44100,
2,
1,
0
};
Sound_setup_t Sound_out;
static int paused = TRUE;
#ifndef SOUND_CALLBACK
static UBYTE *process_buffer = NULL;
static unsigned int process_buffer_size;
#endif /* !SOUND_CALLBACK */
#ifdef SYNCHRONIZED_SOUND
static UBYTE *sync_buffer = NULL;
static unsigned int sync_buffer_size;
/* Two invariants are held:
a) 0 <= sync_read_pos < sync_buffer_size
b) sync_read_pos <= sync_write_pos <= sync_buffer_size + sync_read_pos
sync_write_pos may be >= sync_buffer_size. In such case the actual write
position is sync_write_pos % sync_buffer_size. */
static unsigned int sync_write_pos;
static unsigned int sync_read_pos;
unsigned int Sound_latency = 20;
/* Cumulative audio difference. */
static double avg_fill;
/* Estimated fill of sync_buffer */
static unsigned int sync_est_fill;
/* If sync_est_fill goes outside this bounds, emulation speed is adjusted. */
static unsigned int sync_min_fill;
static unsigned int sync_max_fill;
#ifdef SOUND_CALLBACK
#endif /* SOUND_CALLBACK */
/* Time of last write of sudio to output device (either by Sound_Callback or
WriteOut). */
double last_audio_write_time;
#endif /* SYNCHRONIZED_SOUND */
enum { MAX_SAMPLE_SIZE = 2, /* for 16-bit */
#ifdef STEREO_SOUND
MAX_CHANNELS = 2,
#else /* !STEREO_SOUND */
MAX_CHANNELS = 1,
#endif /* !STEREO_SOUND */
MAX_FRAME_SIZE = MAX_SAMPLE_SIZE * MAX_CHANNELS
};
int Sound_ReadConfig(char *option, char *ptr)
{
if (strcmp(option, "SOUND_ENABLED") == 0)
return (Sound_enabled = Util_sscanbool(ptr)) != -1;
else if (strcmp(option, "SOUND_RATE") == 0)
return (Sound_desired.freq = Util_sscandec(ptr)) != -1;
else if (strcmp(option, "SOUND_BITS") == 0) {
int bits = Util_sscandec(ptr);
if (bits != 8 && bits != 16)
return FALSE;
Sound_desired.sample_size = bits / 8;
}
else if (strcmp(option, "SOUND_FRAG_FRAMES") == 0) {
int val = Util_sscandec(ptr);
if (val == -1)
return FALSE;
Sound_desired.frag_frames = val;
}
#ifdef SYNCHRONIZED_SOUND
else if (strcmp(option, "SOUND_LATENCY") == 0)
return (Sound_latency = Util_sscandec(ptr)) != -1;
#endif /* SYNCHRONIZED_SOUND */
else
return FALSE;
return TRUE;
}
void Sound_WriteConfig(FILE *fp)
{
fprintf(fp, "SOUND_ENABLED=%u\n", Sound_enabled);
fprintf(fp, "SOUND_RATE=%u\n", Sound_desired.freq);
fprintf(fp, "SOUND_BITS=%u\n", Sound_desired.sample_size * 8);
fprintf(fp, "SOUND_FRAG_FRAMES=%u\n", Sound_desired.frag_frames);
#ifdef SYNCHRONIZED_SOUND
fprintf(fp, "SOUND_LATENCY=%u\n", Sound_latency);
#endif /* SYNCHRONIZED_SOUND */
}
int Sound_Initialise(int *argc, char *argv[])
{
int i, j;
int help_only = FALSE;
for (i = j = 1; i < *argc; i++) {
int i_a = (i + 1 < *argc); /* is argument available? */
int a_m = FALSE; /* error, argument missing! */
int a_i = FALSE; /* error, argument invalid! */
if (strcmp(argv[i], "-sound") == 0)
Sound_enabled = 1;
else if (strcmp(argv[i], "-nosound") == 0)
Sound_enabled = 0;
else if (strcmp(argv[i], "-dsprate") == 0) {
if (i_a)
a_i = (Sound_desired.freq = Util_sscandec(argv[++i])) == -1;
else a_m = TRUE;
}
else if (strcmp(argv[i], "-audio16") == 0)
Sound_desired.sample_size = 2;
else if (strcmp(argv[i], "-audio8") == 0)
Sound_desired.sample_size = 1;
else if (strcmp(argv[i], "snd-fragsize") == 0) {
if (i_a) {
int val = Util_sscandec(argv[++i]);
if (val == -1)
a_i = TRUE;
else
Sound_desired.frag_frames = val;
}
else a_m = TRUE;
}
#ifdef SYNCHRONIZED_SOUND
else if (strcmp(argv[i], "-snddelay") == 0)
if (i_a)
Sound_latency = Util_sscandec(argv[++i]);
else a_m = TRUE;
#endif /* SYNCHRONIZED_SOUND */
else {
if (strcmp(argv[i], "-help") == 0) {
help_only = TRUE;
Log_print("\t-sound Enable sound");
Log_print("\t-nosound Disable sound");
Log_print("\t-dsprate <rate> Set sound output frequency in Hz");
Log_print("\t-audio16 Set sound output format to 16-bit");
Log_print("\t-audio8 Set sound output format to 8-bit");
Log_print("\t-snd-fragsize <num> Set size of the hardware sound buffer (fragment size)");
#ifdef SYNCHRONIZED_SOUND
Log_print("\t-snddelay <time> Set sound latency in milliseconds");
#endif /* SYNCHRONIZED_SOUND */
}
argv[j++] = argv[i];
}
if (a_m) {
Log_print("Missing argument for '%s'", argv[i]);
return FALSE;
} else if (a_i) {
Log_print("Invalid argument for '%s'", argv[--i]);
return FALSE;
}
}
*argc = j;
if (help_only)
Sound_enabled = FALSE;
return TRUE;
}
int Sound_Setup(void)
{
/* Sanitize freq. */
if (POKEYSND_enable_new_pokey && Sound_desired.freq < 8192)
/* MZ POKEY seems to segfault or remain silent with rate < 8009 Hz. */
Sound_desired.freq = 8192;
else if (Sound_desired.freq < 1000)
/* Such low value is impractical. */
Sound_desired.freq = 1000;
else if (Sound_desired.freq > 65535)
/* POKEY emulation doesn't support rate > 65535 Hz. */
Sound_desired.freq = 65535;
/* 0 indicates setting frag_size automatically. */
if (Sound_desired.frag_frames != 0) {
/* Make sure frag_frames is a power of 2. */
unsigned int pow_val = 1;
unsigned int val = Sound_desired.frag_frames;
while (val >>= 1)
pow_val <<= 1;
if (pow_val < Sound_desired.frag_frames)
pow_val <<= 1;
Sound_desired.frag_frames = pow_val;
if (Sound_desired.frag_frames < 16)
/* Lower values are simply not practical. */
Sound_desired.frag_frames = 16;
}
Sound_out = Sound_desired;
if (!(Sound_enabled = PLATFORM_SoundSetup(&Sound_out)))
return FALSE;
/* Now setup contains actual audio output settings. */
if ((POKEYSND_enable_new_pokey && Sound_out.freq < 8192)
|| Sound_out.freq < 1000 || Sound_out.freq > 65535) {
Log_print("%d frequency not supported", Sound_out.freq);
Sound_Exit();
return FALSE;
}
if (Sound_out.channels > MAX_CHANNELS) {
Log_print("%d channels not supported", Sound_out.channels);
Sound_Exit();
return FALSE;
}
POKEYSND_stereo_enabled = Sound_out.channels == 2;
#ifndef SOUND_CALLBACK
free(process_buffer);
process_buffer_size = Sound_out.frag_frames * Sound_out.channels * Sound_out.sample_size;
process_buffer = Util_malloc(process_buffer_size);
#endif /* !SOUND_CALLBACK */
POKEYSND_Init(POKEYSND_FREQ_17_EXACT, Sound_out.freq, Sound_out.channels, Sound_out.sample_size == 2 ? POKEYSND_BIT16 : 0);
#ifdef SYNCHRONIZED_SOUND
Sound_SetLatency(Sound_latency);
#endif /* SYNCHRONIZED_SOUND */
Sound_desired.freq = Sound_out.freq;
Sound_desired.sample_size = Sound_out.sample_size;
Sound_desired.channels = Sound_out.channels;
/* Don't copy Sound_out.frag_frames to Sound_desired.frag_frames.
Reason: some backends (e.g. SDL on PulseAudio) always
decrease the desired frag_size when opening audio. If the
obtained value was copied, repeated calls to Sound_Setup
would quickly decrease frag_size to 0. */
paused = TRUE;
return TRUE;
}
void Sound_Exit(void)
{
if (Sound_enabled) {
PLATFORM_SoundExit();
Sound_enabled = FALSE;
#ifndef SOUND_CALLBACK
free(process_buffer);
process_buffer = NULL;
#endif /* !SOUND_CALLBACK */
#ifdef SYNCHRONIZED_SOUND
free(sync_buffer);
sync_buffer = NULL;
#endif /* SYNCHRONIZED_SOUND */
}
}
void Sound_Pause(void)
{
if (Sound_enabled && !paused) {
/* stop audio output */
PLATFORM_SoundPause();
paused = TRUE;
}
}
void Sound_Continue(void)
{
if (Sound_enabled && paused) {
/* start audio output */
#ifdef SYNCHRONIZED_SOUND
/* sync_write_pos = sync_read_pos + sync_min_fill;
avg_fill = sync_min_fill;*/
last_audio_write_time = Util_time();
#endif /* SYNCHRONIZED_SOUND */
PLATFORM_SoundContinue();
paused = FALSE;
}
}
/* Fills buffer BUFFER with SIZE bytes of audio samples. */
static void FillBuffer(UBYTE *buffer, unsigned int size)
{
#ifdef SYNCHRONIZED_SOUND
unsigned int new_read_pos;
static UBYTE last_frame[MAX_FRAME_SIZE];
unsigned int bytes_per_frame = Sound_out.channels * Sound_out.sample_size;
unsigned int to_write = sync_write_pos - sync_read_pos;
if (to_write > 0) {
if (to_write > size)
to_write = size;
new_read_pos = sync_read_pos + to_write;
if (new_read_pos <= sync_buffer_size)
/* no wrap */
memcpy(buffer, sync_buffer + sync_read_pos, to_write);
else {
/* wraps */
unsigned int first_part_size = sync_buffer_size - sync_read_pos;
memcpy(buffer, sync_buffer + sync_read_pos, first_part_size);
memcpy(buffer + first_part_size, sync_buffer, to_write - first_part_size);
}
sync_read_pos = new_read_pos;
if (sync_read_pos > sync_buffer_size) {
sync_read_pos -= sync_buffer_size;
sync_write_pos -= sync_buffer_size;
}
/* Save the last frame as we may need it to fill underflow. */
memcpy(last_frame, buffer + to_write - bytes_per_frame, bytes_per_frame);
}
/* Just repeat the last good frame if underflow. */
if (to_write < size) {
#if DEBUG
Log_print("Sound buffer underflow: fill %d, needed %d",
to_write/Sound_out.channels/Sound_out.sample_size,
size/Sound_out.channels/Sound_out.sample_size);
#endif
do {
memcpy(buffer + to_write, last_frame, bytes_per_frame);
to_write += bytes_per_frame;
} while (to_write < size);
}
#else /* !SYNCHRONIZED_SOUND */
POKEYSND_Process(buffer, size / Sound_out.sample_size);
#endif /* !SYNCHRONIZED_SOUND */
}
#ifdef SOUND_CALLBACK
void Sound_Callback(UBYTE *buffer, unsigned int size)
{
#if DEBUG >= 2
Log_print("Callback: fill %u, needed %u",
(sync_write_pos - sync_read_pos) / Sound_out.channels / Sound_out.sample_size,
size / Sound_out.channels / Sound_out.sample_size);
#endif
FillBuffer(buffer, size);
#ifdef SYNCHRONIZED_SOUND
last_audio_write_time = Util_time();
#endif /* SYNCHRONIZED_SOUND */
}
#else /* !SOUND_CALLBACK */
/* Write audio to output device. */
static void WriteOut(void)
{
unsigned int avail = PLATFORM_SoundAvailable();
if (avail > 0) {
#if DEBUG >= 2
Log_print("WriteOut: fill %u, needed %u",
(sync_write_pos - sync_read_pos) / Sound_out.channels / Sound_out.sample_size,
avail / Sound_out.channels / Sound_out.sample_size);
#endif
/* On some platforms (eg. NestedVM) avail may be larger than process_buffer_size. */
do {
unsigned int len = avail > process_buffer_size ? process_buffer_size : avail;
FillBuffer(process_buffer, len);
PLATFORM_SoundWrite(process_buffer, len);
avail -= len;
} while (avail > 0);
#ifdef SYNCHRONIZED_SOUND
last_audio_write_time = Util_time();
#endif /* SYNCHRONIZED_SOUND */
}
}
#endif /* !SOUND_CALLBACK */
#ifdef SYNCHRONIZED_SOUND
static void UpdateSyncBuffer(void)
{
unsigned int bytes_written;
unsigned int samples_written;
unsigned int fill;
unsigned int new_write_pos;
PLATFORM_SoundLock();
/* Current fill of the audio buffer. */
fill = sync_write_pos - sync_read_pos;
/* Update sync_est_fill. */
{
unsigned int est_gap;
est_gap = (Util_time() - last_audio_write_time)*Sound_out.freq*Sound_out.channels*Sound_out.sample_size;
if (fill < est_gap)
sync_est_fill = 0;
else
sync_est_fill = fill - est_gap;
}
if (Atari800_turbo && sync_est_fill > sync_max_fill) {
PLATFORM_SoundUnlock();
return;
}
/* produce samples from the sound emulation */
samples_written = POKEYSND_UpdateProcessBuffer();
bytes_written = Sound_out.sample_size * samples_written;
/* if there isn't enough room... */
if (bytes_written > sync_buffer_size - fill) {
/* Overflow of sync_buffer. */
#if DEBUG
Log_print("Sound buffer overflow: free %d, needed %d",
(sync_buffer_size - fill)/Sound_out.channels/Sound_out.sample_size,
bytes_written/Sound_out.channels/Sound_out.sample_size);
#endif
/* Wait until hardware buffer can be filled, or wait until callback
makes place in the buffer. */
do {
PLATFORM_SoundUnlock();
/* Sleep for the duration of one full HW buffer. */
Util_sleep((double)Sound_out.frag_frames / Sound_out.freq);
PLATFORM_SoundLock();
#ifndef SOUND_CALLBACK
WriteOut(); /* Write to audio buffer as much as possible. */
#endif /* SOUND_CALLBACK */
fill = sync_write_pos - sync_read_pos;
} while (bytes_written > sync_buffer_size - fill);
}
/* Now bytes_written <= audio_buffer_size + dsp_read_pos - dsp_write_pos) */
#if DEBUG >= 2
Log_print("UpdateSyncBuffer: est_gap: %f, fill %u, write %u",
(Util_time() - last_audio_write_time)*Sound_out.freq,
fill / Sound_out.channels/Sound_out.sample_size,
bytes_written / Sound_out.channels/Sound_out.sample_size);
#endif
/* now we copy the data into the buffer and adjust the positions */
new_write_pos = sync_write_pos + bytes_written;
if (new_write_pos/sync_buffer_size == sync_write_pos/sync_buffer_size)
/* no wrap */
memcpy(sync_buffer + sync_write_pos%sync_buffer_size, POKEYSND_process_buffer, bytes_written);
else {
/* wraps */
int first_part_size = sync_buffer_size - sync_write_pos%sync_buffer_size;
memcpy(sync_buffer + sync_write_pos%sync_buffer_size, POKEYSND_process_buffer, first_part_size);
memcpy(sync_buffer, POKEYSND_process_buffer + first_part_size, bytes_written - first_part_size);
}
sync_write_pos = new_write_pos;
if (sync_write_pos > sync_read_pos + sync_buffer_size)
sync_write_pos -= sync_buffer_size;
PLATFORM_SoundUnlock();
}
#endif /* SYNCHRONIZED_SOUND */
void Sound_Update(void)
{
if (!Sound_enabled || paused)
return;
#ifdef SYNCHRONIZED_SOUND
UpdateSyncBuffer();
#endif /* SYNCHRONIZED_SOUND */
#ifndef SOUND_CALLBACK
WriteOut();
#endif /* !SOUND_CALLBACK */
}
#ifdef SYNCHRONIZED_SOUND
void Sound_SetLatency(unsigned int latency)
{
Sound_latency = latency;
if (Sound_enabled) {
/* how many fragments in the audio buffer */
enum { SYNC_BUFFER_FRAGS = 5 };
unsigned int bytes_per_frame = Sound_out.channels * Sound_out.sample_size;
unsigned int latency_frames = Sound_out.freq*Sound_latency/1000;
PLATFORM_SoundLock();
sync_buffer_size = (latency_frames + SYNC_BUFFER_FRAGS*Sound_out.frag_frames) * bytes_per_frame;
sync_min_fill = latency_frames * bytes_per_frame;
sync_max_fill = sync_min_fill + Sound_out.frag_frames * bytes_per_frame;
avg_fill = sync_min_fill;
sync_read_pos = 0;
sync_write_pos = sync_min_fill;
free(sync_buffer);
sync_buffer = Util_malloc(sync_buffer_size);
memset(sync_buffer, 0, sync_buffer_size);
PLATFORM_SoundUnlock();
}
}
double Sound_AdjustSpeed(void)
{
double delay_mult = 1.0;
static double const alpha = 2.0/(1.0+40.0);
if (Sound_enabled && !paused) {
#if 1
avg_fill = avg_fill + alpha * (sync_est_fill - avg_fill);
if (avg_fill < sync_min_fill)
delay_mult = 0.95;
else if (avg_fill > sync_max_fill)
delay_mult = 1.05;
#endif
#if 0
if (sync_est_fill < sync_min_fill)
delay_mult = 0.95;
else if (sync_est_fill > sync_max_fill)
delay_mult = 1.05;
#endif
#if DEBUG >= 2
Log_print("delay_mult: %f, est_fill: %u, avg_fill: %f, buf_size: %u, min_fill: %u, max_fill: %u",
delay_mult,
sync_est_fill / Sound_out.channels / Sound_out.sample_size,
avg_fill / Sound_out.channels / Sound_out.sample_size,
sync_buffer_size / Sound_out.channels / Sound_out.sample_size,
sync_min_fill / Sound_out.channels / Sound_out.sample_size,
sync_max_fill / Sound_out.channels / Sound_out.sample_size);
#endif
}
return delay_mult;
}
#endif /* SYNCHRONIZED_SOUND */
+81 -1
View File
@@ -1,7 +1,10 @@
#ifndef SOUND_H_
#define SOUND_H_
#include <stdio.h>
#include "config.h"
#include "atari.h"
int Sound_Initialise(int *argc, char *argv[]);
void Sound_Exit(void);
@@ -10,6 +13,83 @@ void Sound_Pause(void);
void Sound_Continue(void);
#ifdef SUPPORTS_SOUND_REINIT
void Sound_Reinit(void);
#endif
#endif /* SUPPORTS_SOUND_REINIT */
#ifdef SOUND_THIN_API
/* Nomenclature used:
Sample - a single portion of one channel of audio signal. Sample size equals
1 byte for 8-bit audio and 2 bytes for 16-bit audio.
Frame - a single portion of samples for all channels of audio signal. Frame
size equals sample size * number of channels.
The word "size", unless additionally specified, means size in bytes.
*/
typedef struct Sound_setup_t {
/* Sound sample rate - number of frames per second: 1000..65535. */
unsigned int freq;
/* Number of bytes per each sample, also determines sample format:
1 = unsigned 8-bit format.
2 = signed 16-bit system-endian format. */
int sample_size;
/* Number of audio channels: 1 = mono, 2 = stereo. */
unsigned int channels;
/* Size of the hardware audio buffer in frames. Should be a power of 2.
To get the buffer's size in bytes, compute
frag_frames*sample_size*channels. */
unsigned int frag_frames;
} Sound_setup_t;
/* Holds parameters of the audio output desired by user. When calling Sound_Setup(),
these parameters are used to open audio output. Audio output may get opened with
different parameters than the desired ones (e.g. hardware might not support
the desired parameters), so after opening, the actual parameters of the opened
output are stored in Sound_out.
Set Sound_desired.frag_frames to 0 if you want the hardware to decide value of this
parameter automatically.
*/
extern Sound_setup_t Sound_desired;
/* Holds parameters of the currently-opened hardware audio output. Don't change
it directly - use Sound_Setup instead. */
extern Sound_setup_t Sound_out;
/* Indicates whether sound output is enabled. Don't change it directly - use
Sound_Setup to enable sound, and Sound_Exit to disable it. */
extern int Sound_enabled;
/* Enables hardware audio output with parameters based on those stored in
Sound_desired. Stores the parameters of the actual opened output in
Sound_out. The actual parameters may differ from the desired ones.
The function can be called multiple times without calling Sound_Exit
inbetween, e.g. to update params of an already-opened audio output.
The function returns TRUE or FALSE to indicate if audio output
has opened successfully, and also sets Sound_enabled to that value. */
int Sound_Setup(void);
#ifdef SOUND_CALLBACK
/* Callback function to be called from platform-specific code. Fills audio
buffer BUFFER with SIZE bytes of audio samples. */
void Sound_Callback(UBYTE *buffer, unsigned int size);
#endif /* SOUND_CALLBACK */
/* Read/write to configuration file. */
int Sound_ReadConfig(char *option, char *ptr);
void Sound_WriteConfig(FILE *fp);
#ifdef SYNCHRONIZED_SOUND
/* Sound latency in ms. Don't change directly - use Sound_SetLatency instead. */
extern unsigned int Sound_latency;
void Sound_SetLatency(unsigned int latency);
/* Returns a factor (1.0 by default) to adjust the speed of the emulation
* so that if the sound buffer is too full or too empty. The emulation
* slows down or speeds up to match the actual speed of sound output. */
double Sound_AdjustSpeed(void);
#endif /* SYNCHRONIZED_SOUND */
#endif /* SOUND_THIN_API */
#endif /* SOUND_H_ */
+135 -196
View File
@@ -2,7 +2,7 @@
* sound_oss.c - Open Sound System driver
*
* Copyright (C) 1995-1998 David Firth
* Copyright (C) 1998-2010 Atari800 development team (see DOC/CREDITS)
* Copyright (C) 1998-2013 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
@@ -22,233 +22,172 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#ifdef SOUND
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
//#include <sys/soundcard.h>
#include <sys/soundcard.h>
/* XXX: #include <machine/soundcard.h> */
#include "atari.h"
#include "log.h"
#include "pokeysnd.h"
#include "platform.h"
#include "sound.h"
#include "util.h"
void ATR800WriteSoundBuffer(void *buffer, unsigned int len);
#define DEBUG 0
//static const char * const dspname = "/dev/dsp";
static int dsprate = 22050;
static const char * const dspname = "/dev/dsp";
static int sound_enabled = TRUE;
//static int dsp_fd;
static int output_channels;
static int pokey_chips;
static int dsp_fd;
int Sound_Initialise(int *argc, char *argv[])
/* When opening an OSS audio device, we don't limit number of sound fragments
that OSS creates. To minimise latency resulting from too many fragments,
we take advantage of the fact that OSS usually starts playback after fully
filling 2 fragments, and ensure that we never have more filled fragments
than MAX_FILLED_FRAGMENTS (which is <> 2 for some additional headroom). */
enum { MAX_FILLED_FRAGMENTS = 4 };
int PLATFORM_SoundSetup(Sound_setup_t *setup)
{
// int i, j;
// int help_only = FALSE;
//
// for (i = j = 1; i < *argc; i++) {
// int i_a = (i + 1 < *argc); /* is argument available? */
// int a_m = FALSE; /* error, argument missing! */
//
// if (strcmp(argv[i], "-sound") == 0)
// sound_enabled = TRUE;
// else if (strcmp(argv[i], "-nosound") == 0)
// sound_enabled = FALSE;
// else if (strcmp(argv[i], "-dsprate") == 0) {
// if (i_a)
// dsprate = Util_sscandec(argv[++i]);
// else a_m = TRUE;
// }
// else {
// if (strcmp(argv[i], "-help") == 0) {
// help_only = TRUE;
// Log_print("\t-sound Enable sound\n"
// "\t-nosound Disable sound\n"
// "\t-dsprate <rate> Set sample rate in Hz"
// );
// }
// argv[j++] = argv[i];
// }
//
// if (a_m) {
// Log_print("Missing argument for '%s'", argv[i]);
// sound_enabled = FALSE;
// return FALSE;
// }
// }
// *argc = j;
//
// if (help_only || !sound_enabled) {
// sound_enabled = FALSE;
// return TRUE;
// }
//
// dsp_fd = open(dspname, O_WRONLY);
// if (dsp_fd == -1) {
// perror(dspname);
// sound_enabled = FALSE;
// return TRUE;
// }
// i = AFMT_U8;
// if (ioctl(dsp_fd, SNDCTL_DSP_SETFMT, &i)) {
// Log_print("%s: cannot set 8-bit unsigned samples", dspname);
// close(dsp_fd);
// sound_enabled = FALSE;
// return TRUE;
// }
int format;
int frag_size;
int setfragment;
/* try to set the OSS device into appropriate number of channels (1 for
* single pokey, 2 for dual Pokey).
* If the sound card does not support the mode we need it should not fail
* but just set the output_channels to value it's able to support.
*/
#ifdef STEREO_SOUND
output_channels = 2;
#else
output_channels = 1;
#endif
// if (ioctl(dsp_fd, SNDCTL_DSP_CHANNELS, &output_channels)) {
// Log_print("%s: SNDCTL_DSP_CHANNELS(%1) failed", dspname, output_channels);
// close(dsp_fd);
// sound_enabled = FALSE;
// return TRUE;
// }
//
// if (ioctl(dsp_fd, SNDCTL_DSP_SPEED, &dsprate)) {
// Log_print("%s: cannot set %d sample rate", dspname, dsprate);
// close(dsp_fd);
// sound_enabled = FALSE;
// return TRUE;
// }
// if (dsprate < 1000 || dsprate > 65535) {
// Log_print("%s: %d sample rate is not supported", dspname, dsprate);
// close(dsp_fd);
// sound_enabled = FALSE;
// return TRUE;
// }
if (Sound_enabled)
close(dsp_fd);
#ifdef STEREO_SOUND
pokey_chips = 2; /* stereo sound generated by two Pokey chips */
#else
pokey_chips = 1;
dsp_fd = open(dspname, O_WRONLY);
if (dsp_fd == -1) {
perror(dspname);
return FALSE;
}
if (setup->frag_frames == 0)
/* Set frag_frames automatically. */
frag_size = setup->freq / 50;
else
frag_size = setup->frag_frames;
frag_size *= setup->channels * setup->sample_size;
/* By setting number of fragments to 0x7fff (ie. don't limit) we ensure
that the obtained fragment size will be as close to the requested value
as possible. */
setfragment = 0x7fff0000;
{
/* Compute the closest power of two. */
int pow_val = 1;
int val = frag_size;
while (val >>= 1) {
pow_val <<= 1;
++setfragment;
}
if (pow_val < frag_size)
/* Ensure fragment size is not smaller than user-provided value. */
++setfragment;
}
if (ioctl(dsp_fd, SNDCTL_DSP_SETFRAGMENT, &setfragment) == -1) {
Log_print("%s: SNDCTL_DSP_SETFRAGMENT(%.8x) failed", dspname, setfragment);
close(dsp_fd);
return FALSE;
}
format = setup->sample_size == 2 ? AFMT_S16_NE : AFMT_U8;
if (ioctl(dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1) {
Log_print("%s: SNDCTL_DSP_SETFMT(%i) failed", dspname, format);
close(dsp_fd);
return FALSE;
}
if (format == AFMT_S16_NE)
setup->sample_size = 2;
else if (format == AFMT_U8)
setup->sample_size = 1;
else {
Log_print("%s: Obtained format %i not supported", dspname, format);
close(dsp_fd);
return FALSE;
}
if (ioctl(dsp_fd, SNDCTL_DSP_CHANNELS, &setup->channels) == -1) {
Log_print("%s: SNDCTL_DSP_CHANNELS(%u) failed", dspname, setup->channels);
close(dsp_fd);
return FALSE;
}
if (ioctl(dsp_fd, SNDCTL_DSP_SPEED, &setup->freq) == -1) {
Log_print("%s: SNDCTL_DSP_SPEED(%u) failed", dspname, setup->freq);
close(dsp_fd);
return FALSE;
}
if (ioctl(dsp_fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) == -1) {
Log_print("%s: SNDCTL_DSP_GETBLKSIZE failed", dspname);
close(dsp_fd);
return FALSE;
}
setup->frag_frames = frag_size / setup->channels / setup->sample_size;
{
audio_buf_info bi;
if (ioctl(dsp_fd, SNDCTL_DSP_GETOSPACE, &bi) == -1) {
Log_print("%s: cannot retrieve ospace", dspname);
return 0;
}
#if DEBUG
Log_print("fragments=%i, fragstotal=%i, fragsize=%i, bytes=%i", bi.fragments, bi.fragstotal, bi.fragsize, bi.bytes);
Log_print("frag_size=%i, buf_Frames=%u", frag_size, setup->frag_frames);
#endif
POKEYSND_Init(POKEYSND_FREQ_17_EXACT, dsprate, pokey_chips, 0);
}
return TRUE;
}
void Sound_Pause(void)
void PLATFORM_SoundExit(void)
{
if (sound_enabled) {
/* flush buffers */
// ioctl(dsp_fd, SNDCTL_DSP_POST, NULL);
}
close(dsp_fd);
}
void Sound_Continue(void)
void PLATFORM_SoundPause(void)
{
/* flush buffers */
ioctl(dsp_fd, SNDCTL_DSP_POST, NULL);
}
void PLATFORM_SoundContinue(void)
{
/* do nothing */
}
void Sound_Exit(void)
unsigned int PLATFORM_SoundAvailable(void)
{
if (sound_enabled) {
// close(dsp_fd);
sound_enabled = FALSE;
}
}
audio_buf_info bi;
int filled_frags;
enum { MAX_FILLED_FRAGMENTS = 4 };
void Sound_Update(void)
{
/* 4096 bytes are enough for stereo 102400Hz
- pokeysnd currently supports only up to 65535Hz */
static unsigned char buffer[4096];
unsigned int len;
if (!sound_enabled || Atari800_turbo)
return;
/* compute number of samples for one Atari frame
(assuming 60Hz for NTSC and 50Hz for PAL) */
len = dsprate / (Atari800_tv_mode == Atari800_TV_NTSC ? 60 : 50) * pokey_chips;
#if 0
/* this code is not needed because buffer[] is big enough */
while (len > sizeof(buffer)) {
POKEYSND_Process(buffer, sizeof(buffer));
write(dsp_fd, buffer, sizeof(buffer));
len -= sizeof(buffer);
if (ioctl(dsp_fd, SNDCTL_DSP_GETOSPACE, &bi) == -1) {
Log_print("%s: cannot retrieve ospace", dspname);
return 0;
}
#if DEBUG
Log_print("fragments=%i, fragstotal=%i, fragsize=%i, bytes=%i", bi.fragments, bi.fragstotal, bi.fragsize, bi.bytes);*/
#endif
POKEYSND_Process(buffer, len);
#if 0
/* For some unknown reason, this is needed
on Piotr's Red Hat 9, VT82C686 AC97 Audio Controller.
Not that the sound is just a bit silent without this,
it is totally broken. */
{
unsigned int i;
for (i = 0; i < len; i++)
buffer[i] <<= 1;
}
#endif
/* the following block of code deals with situation when Pokey output
* does not match OSS output.
* It would better be handled in the Pokey emulation itself
*/
if (output_channels == 2) {
/* OSS device set to two channel mode */
if (pokey_chips == 1) {
/* upmix mono to stereo - for sound in both channels */
int i;
for (i = len-1; i >= 0; i--) {
int pos = i * 2;
buffer[pos] = buffer[pos+1] = buffer[i];
}
}
else if (! POKEYSND_stereo_enabled) {
/* only single Pokey plays - copy left channel to right channel */
int i;
for (i = 0; i < len; i+=2) {
buffer[i+1] = buffer[i];
}
}
}
else {
/* OSS device set to single channel output */
if (pokey_chips == 2) {
/* downmix both channels into single output */
int i;
for (i = 0; i < len/2; i++) {
int pos = i * 2;
buffer[i] = (POKEYSND_stereo_enabled ? buffer[pos]/2 + buffer[pos+1]/2 :
buffer[pos]);
}
}
}
{
// TODO: write to ring buffer
ATR800WriteSoundBuffer(buffer, len);
// int wlen = write(dsp_fd, buffer, len);
// if (wlen < len) {
// /* handle problem */
// }
}
/* Usually OSS playback starts when 2 fragments are fully filled. Take
advantage of it: write audio only if at most MAX_FILLED_FRAGS fragments
are filled, to minimize latency regardless of actual total number of
fragments. */
filled_frags = bi.fragstotal - bi.fragments;
if (filled_frags <= MAX_FILLED_FRAGMENTS)
return bi.fragsize * (MAX_FILLED_FRAGMENTS - filled_frags);
else if (bi.fragstotal <= MAX_FILLED_FRAGMENTS)
return bi.bytes;
else
return 0;
}
#endif /* SOUND */
/*
vim:ts=4:sw=4:
*/
void PLATFORM_SoundWrite(UBYTE const *buffer, unsigned int size)
{
int wsize = write(dsp_fd, buffer, size);
if (wsize < size) {
/* TODO: handle problem */
}
}
+336 -164
View File
@@ -2,7 +2,7 @@
* ui.c - main user interface
*
* Copyright (C) 1995-1998 David Firth
* Copyright (C) 1998-2011 Atari800 development team (see DOC/CREDITS)
* Copyright (C) 1998-2014 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
@@ -31,6 +31,7 @@
#include "afile.h"
#include "antic.h"
#include "artifact.h"
#include "atari.h"
#include "binload.h"
#include "cartridge.h"
@@ -54,6 +55,9 @@
#include "akey.h"
#include "log.h"
#include "memory.h"
#ifdef PAL_BLENDING
#include "pal_blending.h"
#endif /* PAL_BLENDING */
#include "platform.h"
#include "rtime.h"
#include "screen.h"
@@ -150,6 +154,11 @@ extern void do_hz_test(void);
#endif /* HZ_TEST */
#endif /* DREAMCAST */
#ifdef RPI
extern int op_filtering;
extern float op_zoom;
#endif /* RPI */
UI_tDriver *UI_driver = &UI_BASIC_driver;
int UI_is_active = FALSE;
@@ -434,7 +443,7 @@ static void SystemSettings(void)
if (auto_xegame == -1)
menu_array[4].suffix = "ROM missing";
else {
sprintf(default_xegame_label, "%s (auto)", FindMenuItem(basic_menu_array, auto_xegame)->item);
sprintf(default_xegame_label, "%s (auto)", FindMenuItem(xegame_menu_array, auto_xegame)->item);
menu_array[4].suffix = default_xegame_label;
}
}
@@ -966,66 +975,74 @@ static void DiskManagement(void)
int UI_SelectCartType(int k)
{
UI_tMenuItem menu_array[] = {
UI_MENU_ACTION(CARTRIDGE_STD_8, CARTRIDGE_TextDesc[CARTRIDGE_STD_8]),
UI_MENU_ACTION(CARTRIDGE_STD_16, CARTRIDGE_TextDesc[CARTRIDGE_STD_16]),
UI_MENU_ACTION(CARTRIDGE_OSS_034M_16, CARTRIDGE_TextDesc[CARTRIDGE_OSS_034M_16]),
UI_MENU_ACTION(CARTRIDGE_5200_32, CARTRIDGE_TextDesc[CARTRIDGE_5200_32]),
UI_MENU_ACTION(CARTRIDGE_DB_32, CARTRIDGE_TextDesc[CARTRIDGE_DB_32]),
UI_MENU_ACTION(CARTRIDGE_5200_EE_16, CARTRIDGE_TextDesc[CARTRIDGE_5200_EE_16]),
UI_MENU_ACTION(CARTRIDGE_5200_40, CARTRIDGE_TextDesc[CARTRIDGE_5200_40]),
UI_MENU_ACTION(CARTRIDGE_WILL_64, CARTRIDGE_TextDesc[CARTRIDGE_WILL_64]),
UI_MENU_ACTION(CARTRIDGE_EXP_64, CARTRIDGE_TextDesc[CARTRIDGE_EXP_64]),
UI_MENU_ACTION(CARTRIDGE_DIAMOND_64, CARTRIDGE_TextDesc[CARTRIDGE_DIAMOND_64]),
UI_MENU_ACTION(CARTRIDGE_SDX_64, CARTRIDGE_TextDesc[CARTRIDGE_SDX_64]),
UI_MENU_ACTION(CARTRIDGE_XEGS_32, CARTRIDGE_TextDesc[CARTRIDGE_XEGS_32]),
UI_MENU_ACTION(CARTRIDGE_XEGS_64, CARTRIDGE_TextDesc[CARTRIDGE_XEGS_64]),
UI_MENU_ACTION(CARTRIDGE_XEGS_128, CARTRIDGE_TextDesc[CARTRIDGE_XEGS_128]),
UI_MENU_ACTION(CARTRIDGE_OSS_M091_16, CARTRIDGE_TextDesc[CARTRIDGE_OSS_M091_16]),
UI_MENU_ACTION(CARTRIDGE_5200_NS_16, CARTRIDGE_TextDesc[CARTRIDGE_5200_NS_16]),
UI_MENU_ACTION(CARTRIDGE_ATRAX_128, CARTRIDGE_TextDesc[CARTRIDGE_ATRAX_128]),
UI_MENU_ACTION(CARTRIDGE_BBSB_40, CARTRIDGE_TextDesc[CARTRIDGE_BBSB_40]),
UI_MENU_ACTION(CARTRIDGE_5200_8, CARTRIDGE_TextDesc[CARTRIDGE_5200_8]),
UI_MENU_ACTION(CARTRIDGE_5200_4, CARTRIDGE_TextDesc[CARTRIDGE_5200_4]),
UI_MENU_ACTION(CARTRIDGE_RIGHT_8, CARTRIDGE_TextDesc[CARTRIDGE_RIGHT_8]),
UI_MENU_ACTION(CARTRIDGE_WILL_32, CARTRIDGE_TextDesc[CARTRIDGE_WILL_32]),
UI_MENU_ACTION(CARTRIDGE_XEGS_256, CARTRIDGE_TextDesc[CARTRIDGE_XEGS_256]),
UI_MENU_ACTION(CARTRIDGE_XEGS_512, CARTRIDGE_TextDesc[CARTRIDGE_XEGS_512]),
UI_MENU_ACTION(CARTRIDGE_XEGS_1024, CARTRIDGE_TextDesc[CARTRIDGE_XEGS_1024]),
UI_MENU_ACTION(CARTRIDGE_MEGA_16, CARTRIDGE_TextDesc[CARTRIDGE_MEGA_16]),
UI_MENU_ACTION(CARTRIDGE_MEGA_32, CARTRIDGE_TextDesc[CARTRIDGE_MEGA_32]),
UI_MENU_ACTION(CARTRIDGE_MEGA_64, CARTRIDGE_TextDesc[CARTRIDGE_MEGA_64]),
UI_MENU_ACTION(CARTRIDGE_MEGA_128, CARTRIDGE_TextDesc[CARTRIDGE_MEGA_128]),
UI_MENU_ACTION(CARTRIDGE_MEGA_256, CARTRIDGE_TextDesc[CARTRIDGE_MEGA_256]),
UI_MENU_ACTION(CARTRIDGE_MEGA_512, CARTRIDGE_TextDesc[CARTRIDGE_MEGA_512]),
UI_MENU_ACTION(CARTRIDGE_MEGA_1024, CARTRIDGE_TextDesc[CARTRIDGE_MEGA_1024]),
UI_MENU_ACTION(CARTRIDGE_SWXEGS_32, CARTRIDGE_TextDesc[CARTRIDGE_SWXEGS_32]),
UI_MENU_ACTION(CARTRIDGE_SWXEGS_64, CARTRIDGE_TextDesc[CARTRIDGE_SWXEGS_64]),
UI_MENU_ACTION(CARTRIDGE_SWXEGS_128, CARTRIDGE_TextDesc[CARTRIDGE_SWXEGS_128]),
UI_MENU_ACTION(CARTRIDGE_SWXEGS_256, CARTRIDGE_TextDesc[CARTRIDGE_SWXEGS_256]),
UI_MENU_ACTION(CARTRIDGE_SWXEGS_512, CARTRIDGE_TextDesc[CARTRIDGE_SWXEGS_512]),
UI_MENU_ACTION(CARTRIDGE_SWXEGS_1024, CARTRIDGE_TextDesc[CARTRIDGE_SWXEGS_1024]),
UI_MENU_ACTION(CARTRIDGE_PHOENIX_8, CARTRIDGE_TextDesc[CARTRIDGE_PHOENIX_8]),
UI_MENU_ACTION(CARTRIDGE_BLIZZARD_16, CARTRIDGE_TextDesc[CARTRIDGE_BLIZZARD_16]),
UI_MENU_ACTION(CARTRIDGE_ATMAX_128, CARTRIDGE_TextDesc[CARTRIDGE_ATMAX_128]),
UI_MENU_ACTION(CARTRIDGE_ATMAX_1024, CARTRIDGE_TextDesc[CARTRIDGE_ATMAX_1024]),
UI_MENU_ACTION(CARTRIDGE_SDX_128, CARTRIDGE_TextDesc[CARTRIDGE_SDX_128]),
UI_MENU_ACTION(CARTRIDGE_OSS_8, CARTRIDGE_TextDesc[CARTRIDGE_OSS_8]),
UI_MENU_ACTION(CARTRIDGE_OSS_043M_16, CARTRIDGE_TextDesc[CARTRIDGE_OSS_043M_16]),
UI_MENU_ACTION(CARTRIDGE_BLIZZARD_4, CARTRIDGE_TextDesc[CARTRIDGE_BLIZZARD_4]),
UI_MENU_ACTION(CARTRIDGE_AST_32, CARTRIDGE_TextDesc[CARTRIDGE_AST_32]),
UI_MENU_ACTION(CARTRIDGE_ATRAX_SDX_64, CARTRIDGE_TextDesc[CARTRIDGE_ATRAX_SDX_64]),
UI_MENU_ACTION(CARTRIDGE_ATRAX_SDX_128, CARTRIDGE_TextDesc[CARTRIDGE_ATRAX_SDX_128]),
UI_MENU_ACTION(CARTRIDGE_TURBOSOFT_64, CARTRIDGE_TextDesc[CARTRIDGE_TURBOSOFT_64]),
UI_MENU_ACTION(CARTRIDGE_TURBOSOFT_128, CARTRIDGE_TextDesc[CARTRIDGE_TURBOSOFT_128]),
UI_MENU_ACTION(CARTRIDGE_ULTRACART_32, CARTRIDGE_TextDesc[CARTRIDGE_ULTRACART_32]),
UI_MENU_ACTION(CARTRIDGE_LOW_BANK_8, CARTRIDGE_TextDesc[CARTRIDGE_LOW_BANK_8]),
UI_MENU_ACTION(CARTRIDGE_SIC_128, CARTRIDGE_TextDesc[CARTRIDGE_SIC_128]),
UI_MENU_ACTION(CARTRIDGE_SIC_256, CARTRIDGE_TextDesc[CARTRIDGE_SIC_256]),
UI_MENU_ACTION(CARTRIDGE_SIC_512, CARTRIDGE_TextDesc[CARTRIDGE_SIC_512]),
UI_MENU_ACTION(CARTRIDGE_STD_2, CARTRIDGE_TextDesc[CARTRIDGE_STD_2]),
UI_MENU_ACTION(CARTRIDGE_STD_4, CARTRIDGE_TextDesc[CARTRIDGE_STD_4]),
UI_MENU_ACTION(CARTRIDGE_RIGHT_4, CARTRIDGE_TextDesc[CARTRIDGE_RIGHT_4]),
static UI_tMenuItem menu_array[] = {
UI_MENU_ACTION(CARTRIDGE_STD_8, CARTRIDGE_STD_8_DESC),
UI_MENU_ACTION(CARTRIDGE_STD_16, CARTRIDGE_STD_16_DESC),
UI_MENU_ACTION(CARTRIDGE_OSS_034M_16, CARTRIDGE_OSS_034M_16_DESC),
UI_MENU_ACTION(CARTRIDGE_5200_32, CARTRIDGE_5200_32_DESC),
UI_MENU_ACTION(CARTRIDGE_DB_32, CARTRIDGE_DB_32_DESC),
UI_MENU_ACTION(CARTRIDGE_5200_EE_16, CARTRIDGE_5200_EE_16_DESC),
UI_MENU_ACTION(CARTRIDGE_5200_40, CARTRIDGE_5200_40_DESC),
UI_MENU_ACTION(CARTRIDGE_WILL_64, CARTRIDGE_WILL_64_DESC),
UI_MENU_ACTION(CARTRIDGE_EXP_64, CARTRIDGE_EXP_64_DESC),
UI_MENU_ACTION(CARTRIDGE_DIAMOND_64, CARTRIDGE_DIAMOND_64_DESC),
UI_MENU_ACTION(CARTRIDGE_SDX_64, CARTRIDGE_SDX_64_DESC),
UI_MENU_ACTION(CARTRIDGE_XEGS_32, CARTRIDGE_XEGS_32_DESC),
UI_MENU_ACTION(CARTRIDGE_XEGS_07_64, CARTRIDGE_XEGS_07_64_DESC),
UI_MENU_ACTION(CARTRIDGE_XEGS_128, CARTRIDGE_XEGS_128_DESC),
UI_MENU_ACTION(CARTRIDGE_OSS_M091_16, CARTRIDGE_OSS_M091_16_DESC),
UI_MENU_ACTION(CARTRIDGE_5200_NS_16, CARTRIDGE_5200_NS_16_DESC),
UI_MENU_ACTION(CARTRIDGE_ATRAX_128, CARTRIDGE_ATRAX_128_DESC),
UI_MENU_ACTION(CARTRIDGE_BBSB_40, CARTRIDGE_BBSB_40_DESC),
UI_MENU_ACTION(CARTRIDGE_5200_8, CARTRIDGE_5200_8_DESC),
UI_MENU_ACTION(CARTRIDGE_5200_4, CARTRIDGE_5200_4_DESC),
UI_MENU_ACTION(CARTRIDGE_RIGHT_8, CARTRIDGE_RIGHT_8_DESC),
UI_MENU_ACTION(CARTRIDGE_WILL_32, CARTRIDGE_WILL_32_DESC),
UI_MENU_ACTION(CARTRIDGE_XEGS_256, CARTRIDGE_XEGS_256_DESC),
UI_MENU_ACTION(CARTRIDGE_XEGS_512, CARTRIDGE_XEGS_512_DESC),
UI_MENU_ACTION(CARTRIDGE_XEGS_1024, CARTRIDGE_XEGS_1024_DESC),
UI_MENU_ACTION(CARTRIDGE_MEGA_16, CARTRIDGE_MEGA_16_DESC),
UI_MENU_ACTION(CARTRIDGE_MEGA_32, CARTRIDGE_MEGA_32_DESC),
UI_MENU_ACTION(CARTRIDGE_MEGA_64, CARTRIDGE_MEGA_64_DESC),
UI_MENU_ACTION(CARTRIDGE_MEGA_128, CARTRIDGE_MEGA_128_DESC),
UI_MENU_ACTION(CARTRIDGE_MEGA_256, CARTRIDGE_MEGA_256_DESC),
UI_MENU_ACTION(CARTRIDGE_MEGA_512, CARTRIDGE_MEGA_512_DESC),
UI_MENU_ACTION(CARTRIDGE_MEGA_1024, CARTRIDGE_MEGA_1024_DESC),
UI_MENU_ACTION(CARTRIDGE_SWXEGS_32, CARTRIDGE_SWXEGS_32_DESC),
UI_MENU_ACTION(CARTRIDGE_SWXEGS_64, CARTRIDGE_SWXEGS_64_DESC),
UI_MENU_ACTION(CARTRIDGE_SWXEGS_128, CARTRIDGE_SWXEGS_128_DESC),
UI_MENU_ACTION(CARTRIDGE_SWXEGS_256, CARTRIDGE_SWXEGS_256_DESC),
UI_MENU_ACTION(CARTRIDGE_SWXEGS_512, CARTRIDGE_SWXEGS_512_DESC),
UI_MENU_ACTION(CARTRIDGE_SWXEGS_1024, CARTRIDGE_SWXEGS_1024_DESC),
UI_MENU_ACTION(CARTRIDGE_PHOENIX_8, CARTRIDGE_PHOENIX_8_DESC),
UI_MENU_ACTION(CARTRIDGE_BLIZZARD_16, CARTRIDGE_BLIZZARD_16_DESC),
UI_MENU_ACTION(CARTRIDGE_ATMAX_128, CARTRIDGE_ATMAX_128_DESC),
UI_MENU_ACTION(CARTRIDGE_ATMAX_1024, CARTRIDGE_ATMAX_1024_DESC),
UI_MENU_ACTION(CARTRIDGE_SDX_128, CARTRIDGE_SDX_128_DESC),
UI_MENU_ACTION(CARTRIDGE_OSS_8, CARTRIDGE_OSS_8_DESC),
UI_MENU_ACTION(CARTRIDGE_OSS_043M_16, CARTRIDGE_OSS_043M_16_DESC),
UI_MENU_ACTION(CARTRIDGE_BLIZZARD_4, CARTRIDGE_BLIZZARD_4_DESC),
UI_MENU_ACTION(CARTRIDGE_AST_32, CARTRIDGE_AST_32_DESC),
UI_MENU_ACTION(CARTRIDGE_ATRAX_SDX_64, CARTRIDGE_ATRAX_SDX_64_DESC),
UI_MENU_ACTION(CARTRIDGE_ATRAX_SDX_128, CARTRIDGE_ATRAX_SDX_128_DESC),
UI_MENU_ACTION(CARTRIDGE_TURBOSOFT_64, CARTRIDGE_TURBOSOFT_64_DESC),
UI_MENU_ACTION(CARTRIDGE_TURBOSOFT_128, CARTRIDGE_TURBOSOFT_128_DESC),
UI_MENU_ACTION(CARTRIDGE_ULTRACART_32, CARTRIDGE_ULTRACART_32_DESC),
UI_MENU_ACTION(CARTRIDGE_LOW_BANK_8, CARTRIDGE_LOW_BANK_8_DESC),
UI_MENU_ACTION(CARTRIDGE_SIC_128, CARTRIDGE_SIC_128_DESC),
UI_MENU_ACTION(CARTRIDGE_SIC_256, CARTRIDGE_SIC_256_DESC),
UI_MENU_ACTION(CARTRIDGE_SIC_512, CARTRIDGE_SIC_512_DESC),
UI_MENU_ACTION(CARTRIDGE_STD_2, CARTRIDGE_STD_2_DESC),
UI_MENU_ACTION(CARTRIDGE_STD_4, CARTRIDGE_STD_4_DESC),
UI_MENU_ACTION(CARTRIDGE_RIGHT_4, CARTRIDGE_RIGHT_4_DESC),
UI_MENU_ACTION(CARTRIDGE_BLIZZARD_32, CARTRIDGE_BLIZZARD_32_DESC),
UI_MENU_ACTION(CARTRIDGE_MEGAMAX_2048, CARTRIDGE_MEGAMAX_2048_DESC),
UI_MENU_ACTION(CARTRIDGE_THECART_128M, CARTRIDGE_THECART_128M_DESC),
UI_MENU_ACTION(CARTRIDGE_MEGA_4096, CARTRIDGE_MEGA_4096_DESC),
UI_MENU_ACTION(CARTRIDGE_MEGA_2048, CARTRIDGE_MEGA_2048_DESC),
UI_MENU_ACTION(CARTRIDGE_THECART_32M, CARTRIDGE_THECART_32M_DESC),
UI_MENU_ACTION(CARTRIDGE_THECART_64M, CARTRIDGE_THECART_64M_DESC),
UI_MENU_ACTION(CARTRIDGE_XEGS_8F_64, CARTRIDGE_XEGS_8F_64_DESC),
UI_MENU_END
};
@@ -2546,6 +2563,25 @@ static void ColourSliderLabel(char *label, int value, void *user_data)
Colours_Update();
}
#ifdef RPI
static int ZoomSettingToSlider()
{
/* 0.8 <= op_zoom <= 1.3 */
return (int) Util_round((op_zoom - 0.8f) * 50.0 / (1.3f - 0.8f));
}
static double SliderToZoomSetting(int value)
{
/* 0 <= value <= 50 */
return (double) value * (1.3f - 0.8f) / 50.0 + 0.8f;
}
static void ZoomSliderLabel(char *label, int value, void *user_data)
{
double setting = SliderToZoomSetting(value);
sprintf(label, "% .2f", setting);
op_zoom = setting;
}
#endif /* RPI */
#if NTSC_FILTER
/* Submenu with controls for NTSC filter. */
static void NTSCFilterSettings(void)
@@ -2649,13 +2685,19 @@ static void SavePalette(void)
static void DisplaySettings(void)
{
static const UI_tMenuItem artif_quality_menu_array[] = {
UI_MENU_ACTION(0, "off"),
UI_MENU_ACTION(1, "original"),
UI_MENU_ACTION(2, "new"),
static UI_tMenuItem artif_menu_array[] = {
UI_MENU_ACTION(ARTIFACT_NONE, "off"),
UI_MENU_ACTION(ARTIFACT_NTSC_OLD, "old NTSC artifacts"),
UI_MENU_ACTION(ARTIFACT_NTSC_NEW, "new NTSC artifacts"),
#if NTSC_FILTER
UI_MENU_ACTION(3, "NTSC filter"),
UI_MENU_ACTION(ARTIFACT_NTSC_FULL, "full NTSC filter"),
#endif
#ifndef NO_SIMPLE_PAL_BLENDING
UI_MENU_ACTION(ARTIFACT_PAL_SIMPLE, "simple PAL blending"),
#endif
#if PAL_BLENDING
UI_MENU_ACTION(ARTIFACT_PAL_BLEND, "accurate PAL blending"),
#endif /* PAL_BLENDING */
UI_MENU_END
};
static const UI_tMenuItem artif_mode_menu_array[] = {
@@ -2677,11 +2719,18 @@ static void DisplaySettings(void)
#endif
static char refresh_status[16];
#ifdef RPI
static char op_zoom_string[16];
#endif /* RPI */
static UI_tMenuItem menu_array[] = {
#if SUPPORTS_CHANGE_VIDEOMODE
UI_MENU_SUBMENU(24, "Video mode settings"),
#endif /* SUPPORTS_CHANGE_VIDEOMODE */
UI_MENU_SUBMENU_SUFFIX(0, "NTSC artifacting quality:", NULL),
#ifdef RPI
UI_MENU_CHECK(30, "Filtering:"),
{ UI_ITEM_ACTION, 31, NULL, "Zoom: ", op_zoom_string },
#endif /* RPI */
UI_MENU_SUBMENU_SUFFIX(0, "Video artifacts:", NULL),
UI_MENU_SUBMENU_SUFFIX(11, "NTSC artifacting mode:", NULL),
#if SUPPORTS_CHANGE_VIDEOMODE && (defined(XEP80_EMULATION) || defined(PBI_PROTO80) || defined(AF80))
UI_MENU_CHECK(25, "Show output of 80 column device:"),
@@ -2724,16 +2773,14 @@ static void DisplaySettings(void)
#if SUPPORTS_CHANGE_VIDEOMODE
int option = 24;
#else
#elif RPI
int option = 30;
#else /* RPI */
int option = 0;
#endif
#endif /* RPI */
int option2;
int seltype;
/* Current artifacting quality, computed from
PLATFORM_artifacting and ANTIC_artif_new */
int artif_quality;
#if SUPPORTS_PLATFORM_PALETTEUPDATE
Colours_preset_t colours_preset;
int i;
@@ -2741,24 +2788,12 @@ static void DisplaySettings(void)
#endif
for (;;) {
#if NTSC_FILTER
/* Computing current artifacting quality... */
if (VIDEOMODE_ntsc_filter) {
/* NTSC filter is on */
FindMenuItem(menu_array, 0)->suffix = artif_quality_menu_array[3].item;
FindMenuItem(menu_array, 11)->suffix = "N/A";
artif_quality = 3;
} else
#endif /* NTSC_FILTER */
if (ANTIC_artif_mode == 0) { /* artifacting is off */
FindMenuItem(menu_array, 0)->suffix = artif_quality_menu_array[0].item;
FindMenuItem(menu_array, 11)->suffix = "N/A";
artif_quality = 0;
} else { /* ANTIC artifacting is on */
FindMenuItem(menu_array, 0)->suffix = artif_quality_menu_array[1 + ANTIC_artif_new].item;
FindMenuItem(menu_array, 11)->suffix = artif_mode_menu_array[ANTIC_artif_mode - 1].item;
artif_quality = 1 + ANTIC_artif_new;
}
FindMenuItem(menu_array, 0)->suffix = artif_menu_array[ARTIFACT_mode].item;
#if SUPPORTS_PLATFORM_PALETTEUPDATE
colours_preset = Colours_GetPreset();
@@ -2782,6 +2817,10 @@ static void DisplaySettings(void)
SetItemChecked(menu_array, 25, VIDEOMODE_80_column);
#endif
snprintf(refresh_status, sizeof(refresh_status), "1:%-2d", Atari800_refresh_rate);
#ifdef RPI
snprintf(op_zoom_string, sizeof(op_zoom_string), "%.2f", op_zoom);
SetItemChecked(menu_array, 30, op_filtering);
#endif /* RPI */
SetItemChecked(menu_array, 2, Atari800_collisions_in_skipped_frames);
SetItemChecked(menu_array, 3, Screen_show_atari_speed);
SetItemChecked(menu_array, 4, Screen_show_disk_led);
@@ -2803,35 +2842,29 @@ static void DisplaySettings(void)
break;
#endif
case 0:
option2 = UI_driver->fSelect(NULL, UI_SELECT_POPUP, artif_quality, artif_quality_menu_array, NULL);
artif_menu_array[ARTIFACT_NTSC_OLD].flags =
Atari800_tv_mode == Atari800_TV_NTSC ? UI_ITEM_ACTION : UI_ITEM_HIDDEN;
artif_menu_array[ARTIFACT_NTSC_NEW].flags =
Atari800_tv_mode == Atari800_TV_NTSC ? UI_ITEM_ACTION : UI_ITEM_HIDDEN;
#if NTSC_FILTER
artif_menu_array[ARTIFACT_NTSC_FULL].flags =
Atari800_tv_mode == Atari800_TV_NTSC ? UI_ITEM_ACTION : UI_ITEM_HIDDEN;
#endif /* NTSC_FILTER */
#ifndef NO_SIMPLE_PAL_BLENDING
artif_menu_array[ARTIFACT_PAL_SIMPLE].flags =
Atari800_tv_mode == Atari800_TV_PAL ? UI_ITEM_ACTION : UI_ITEM_HIDDEN;
#endif /* NO_SIMPLE_PAL_BLENDING */
#ifdef PAL_BLENDING
artif_menu_array[ARTIFACT_PAL_BLEND].flags =
Atari800_tv_mode == Atari800_TV_PAL ? UI_ITEM_ACTION : UI_ITEM_HIDDEN;
#endif /* PAL_BLENDING */
option2 = UI_driver->fSelect(NULL, UI_SELECT_POPUP, ARTIFACT_mode, artif_menu_array, NULL);
if (option2 >= 0)
{
#if NTSC_FILTER && SUPPORTS_CHANGE_VIDEOMODE
/* If switched between non-filter and NTSC filter,
VIDEOMODE_ntsc_filter must be updated. */
if (option2 >= 3 && artif_quality < 3)
VIDEOMODE_SetNtscFilter(TRUE);
else if (option2 < 3 && artif_quality >= 3)
VIDEOMODE_SetNtscFilter(FALSE);
#endif /* NTSC_FILTER && SUPPORTS_CHANGE_VIDEOMODE */
/* ANTIC artifacting settings cannot be turned on
when artifacting is off or NTSC filter. */
if (option2 == 0 || option2 >= 3) {
ANTIC_artif_new = ANTIC_artif_mode = 0;
} else {
/* Do not reset artifacting mode when switched between original and new. */
if (artif_quality >= 3 || artif_quality == 0)
/* switched from off/ntsc filter to ANTIC artifacting */
ANTIC_artif_mode = 1;
ANTIC_artif_new = option2 - 1;
}
ANTIC_UpdateArtifacting();
}
ARTIFACT_Set(option2);
break;
case 11:
/* The artifacting mode option is only active for ANTIC artifacting. */
if (artif_quality > 0 && artif_quality < 3)
if (ANTIC_artif_mode != 0)
{
option2 = UI_driver->fSelect(NULL, UI_SELECT_POPUP, ANTIC_artif_mode - 1, artif_mode_menu_array, NULL);
if (option2 >= 0) {
@@ -2857,6 +2890,21 @@ static void DisplaySettings(void)
UI_driver->fMessage("No 80 column hardware available now.", 1);
break;
#endif /* SUPPORTS_CHANGE_VIDEOMODE && (defined(XEP80_EMULATION) || defined(PBI_PROTO80) || defined(AF80)) */
#ifdef RPI
case 30:
op_filtering = !op_filtering;
break;
case 31:
{
int value = UI_driver->fSelectSlider("Adjust zoom",
ZoomSettingToSlider(),
50, &ZoomSliderLabel, NULL);
if (value != -1) {
op_zoom = SliderToZoomSetting(value);
}
}
break;
#endif /* RPI */
case 1:
Atari800_refresh_rate = UI_driver->fSelectInt(Atari800_refresh_rate, 1, 99);
break;
@@ -2943,7 +2991,7 @@ static void DisplaySettings(void)
break;
#if NTSC_FILTER
case 19:
if (VIDEOMODE_ntsc_filter) {
if (ARTIFACT_mode == ARTIFACT_NTSC_FULL) {
NTSCFilterSettings();
/* While in NTSC Filter menu, the "Filter preset" option also changes the "standard" colour
controls (saturation etc.) - so we need to call UpdateColourControls to update the menu. */
@@ -2956,7 +3004,7 @@ static void DisplaySettings(void)
case 20:
Colours_RestoreDefaults();
#if NTSC_FILTER
if (VIDEOMODE_ntsc_filter)
if (ARTIFACT_mode == ARTIFACT_NTSC_FULL)
FILTER_NTSC_RestoreDefaults();
#endif
UpdateColourControls(menu_array);
@@ -3621,96 +3669,220 @@ static void ControllerConfiguration(void)
static int SoundSettings(void)
{
#ifdef SOUND_THIN_API
Sound_setup_t setup = Sound_desired;
static char freq_string[9]; /* "nnnnn Hz\0" */
static char frag_frames_string[13]; /* "auto (nnnnn)\0" */
#ifdef SYNCHRONIZED_SOUND
static char latency_string[8]; /* nnnn ms\0" */
#endif /* SYNCHRONIZED_SOUND */
static const unsigned int freq_values[] = {
8192,
11025,
22050,
44100,
48000
};
static const UI_tMenuItem freq_menu_array[] = {
UI_MENU_ACTION(0, "8192 Hz"),
UI_MENU_ACTION(1, "11025 Hz"),
UI_MENU_ACTION(2, "22050 Hz"),
UI_MENU_ACTION(3, "44100 Hz"),
UI_MENU_ACTION(4, "48000 Hz"),
UI_MENU_ACTION(5, "custom"),
UI_MENU_END
};
static const UI_tMenuItem frag_frames_menu_array[] = {
UI_MENU_ACTION(0, "automatic"),
UI_MENU_ACTION(128, "128"),
UI_MENU_ACTION(256, "256"),
UI_MENU_ACTION(512, "512"),
UI_MENU_ACTION(1024, "1024"),
UI_MENU_ACTION(2048, "2048"),
UI_MENU_ACTION(4096, "4096"),
UI_MENU_ACTION(8192, "8192"),
UI_MENU_ACTION(16384, "16384"),
UI_MENU_END
};
#endif /* SOUND_THIN_API */
static UI_tMenuItem menu_array[] = {
/* XXX: don't allow on smartphones? */
#ifndef SYNCHRONIZED_SOUND
UI_MENU_CHECK(0, "High Fidelity POKEY:"),
#ifdef SOUND_THIN_API
UI_MENU_CHECK(0, "Enable sound:"),
UI_MENU_SUBMENU_SUFFIX(1, "Frequency:", freq_string),
UI_MENU_ACTION(2, "Bit depth:"),
UI_MENU_SUBMENU_SUFFIX(3, "Fragment size:", frag_frames_string),
#ifdef SYNCHRONIZED_SOUND
UI_MENU_SUBMENU_SUFFIX(4, "Latency:", latency_string),
#endif /* SYNCHRONIZED_SOUND */
#endif /* SOUND_THIN_API */
#ifdef DREAMCAST
UI_MENU_CHECK(0, "Enable sound:"),
#endif
#ifdef STEREO_SOUND
UI_MENU_CHECK(1, "Dual POKEY (Stereo):"),
UI_MENU_CHECK(5, "Dual POKEY (Stereo):"),
#endif
UI_MENU_CHECK(6, "High Fidelity POKEY:"),
#ifdef CONSOLE_SOUND
UI_MENU_CHECK(2, "Speaker (Key Click):"),
UI_MENU_CHECK(7, "Speaker (Key Click):"),
#endif
#ifdef SERIO_SOUND
UI_MENU_CHECK(3, "Serial IO Sound:"),
#endif
#ifndef SYNCHRONIZED_SOUND
UI_MENU_ACTION(4, "Enable higher frequencies:"),
#endif
#ifdef DREAMCAST
UI_MENU_CHECK(5, "Enable sound:"),
UI_MENU_CHECK(8, "Serial IO Sound:"),
#endif
UI_MENU_ACTION(9, "Enable higher frequencies:"),
UI_MENU_END
};
int option = 0;
for (;;) {
#ifndef SYNCHRONIZED_SOUND
SetItemChecked(menu_array, 0, POKEYSND_enable_new_pokey);
#ifdef SOUND_THIN_API
SetItemChecked(menu_array, 0, Sound_enabled);
snprintf(freq_string, sizeof(freq_string), "%i Hz", setup.freq);
menu_array[2].suffix = setup.sample_size == 2 ? "16 bit" : "8 bit";
if (setup.frag_frames == 0) {
if (Sound_enabled)
snprintf(frag_frames_string, sizeof(frag_frames_string), "auto (%u)", Sound_out.frag_frames);
else
strncpy(frag_frames_string, "auto", sizeof(frag_frames_string));
}
else
snprintf(frag_frames_string, sizeof(frag_frames_string), "%u", setup.frag_frames);
#ifdef SYNCHRONIZED_SOUND
snprintf(latency_string, sizeof(latency_string), "%i ms", Sound_latency);
#endif /* SYNCHRONIZED_SOUND */
#endif /* SOUND_THIN_API */
#ifdef DREAMCAST
SetItemChecked(menu_array, 0, glob_snd_ena);
#endif
#ifdef STEREO_SOUND
SetItemChecked(menu_array, 1, POKEYSND_stereo_enabled);
#endif
#ifdef SOUND_THIN_API
SetItemChecked(menu_array, 5, setup.channels == 2);
#else /* !defined(SOUND_THIN_API) */
SetItemChecked(menu_array, 5, POKEYSND_stereo_enabled);
#endif /* SOUND_THIN_API */
#endif /* STEREO_SOUND */
SetItemChecked(menu_array, 6, POKEYSND_enable_new_pokey);
#ifdef CONSOLE_SOUND
SetItemChecked(menu_array, 2, POKEYSND_console_sound_enabled);
SetItemChecked(menu_array, 7, POKEYSND_console_sound_enabled);
#endif
#ifdef SERIO_SOUND
SetItemChecked(menu_array, 3, POKEYSND_serio_sound_enabled);
#endif
#ifndef SYNCHRONIZED_SOUND
FindMenuItem(menu_array, 4)->suffix = POKEYSND_enable_new_pokey ? "N/A" : POKEYSND_bienias_fix ? "Yes" : "No ";
#endif
#ifdef DREAMCAST
SetItemChecked(menu_array, 5, glob_snd_ena);
SetItemChecked(menu_array, 8, POKEYSND_serio_sound_enabled);
#endif
FindMenuItem(menu_array, 9)->suffix = POKEYSND_enable_new_pokey ? "N/A" : POKEYSND_bienias_fix ? "Yes" : "No ";
#if 0
option = UI_driver->fSelect(NULL, UI_SELECT_POPUP, option, menu_array, NULL);
#else
option = UI_driver->fSelect("Sound Settings", 0, option, menu_array, NULL);
#endif
switch (option) {
#ifndef SYNCHRONIZED_SOUND
#ifdef SOUND_THIN_API
case 0:
if (Sound_enabled)
Sound_Exit();
else {
Sound_desired = setup;
if (!Sound_Setup())
UI_driver->fMessage("Error: can't open sound device", 1);
else
setup = Sound_desired;
}
break;
case 1:
{
int option2;
int current;
for (current = 0; freq_menu_array[current].retval < 5; ++current) {
/* Find the currently-chosen frequency. */
if (freq_values[freq_menu_array[current].retval] == setup.freq)
break;
}
option2 = UI_driver->fSelect(NULL, UI_SELECT_POPUP, current, freq_menu_array, NULL);
if (option2 == 5) {
snprintf(freq_string, sizeof(freq_string), "%u", setup.freq); /* Remove " Hz" suffix */
if (UI_driver->fEditString("Enter sound frequency", freq_string, sizeof(freq_string)-3))
setup.freq = atoi(freq_string);
}
else if (option2 >= 0)
setup.freq = freq_values[option2];
}
break;
case 2:
setup.sample_size = 3 - setup.sample_size; /* Toggle 1<->2 */
break;
case 3:
{
int option2 = UI_driver->fSelect(NULL, UI_SELECT_POPUP, setup.frag_frames, frag_frames_menu_array, NULL);
if (option2 >= 0)
setup.frag_frames = option2;
}
break;
#ifdef SYNCHRONIZED_SOUND
case 4:
snprintf(latency_string, sizeof(latency_string), "%u", Sound_latency); /* Remove " ms" suffix */
if (UI_driver->fEditString("Enter sound latency", latency_string, sizeof(latency_string)-3))
Sound_SetLatency(atoi(latency_string));
break;
#endif /* SYNCHRONIZED_SOUND */
#endif /* SOUND_THIN_API */
#ifdef DREAMCAST
case 0:
glob_snd_ena = !glob_snd_ena;
break;
#endif
#ifdef STEREO_SOUND
case 5:
#ifdef SOUND_THIN_API
setup.channels = 3 - setup.channels; /* Toggle 1<->2 */
#else /* !defined(SOUND_THIN_API) */
POKEYSND_stereo_enabled = !POKEYSND_stereo_enabled;
#ifdef SUPPORTS_SOUND_REINIT
Sound_Reinit();
#endif
#endif /* SOUND_THIN_API */
break;
#endif
case 6:
POKEYSND_enable_new_pokey = !POKEYSND_enable_new_pokey;
POKEYSND_DoInit();
/* According to the PokeySnd doc the POKEY switch can occur on
a cold-restart only */
UI_driver->fMessage("Will reboot to apply the change", 1);
return TRUE; /* reboot required */
#endif
#ifdef STEREO_SOUND
case 1:
POKEYSND_stereo_enabled = !POKEYSND_stereo_enabled;
#ifdef SUPPORTS_SOUND_REINIT
Sound_Reinit();
#endif
break;
#endif
#ifdef CONSOLE_SOUND
case 2:
case 7:
POKEYSND_console_sound_enabled = !POKEYSND_console_sound_enabled;
break;
#endif
#ifdef SERIO_SOUND
case 3:
case 8:
POKEYSND_serio_sound_enabled = !POKEYSND_serio_sound_enabled;
break;
#endif
#ifndef SYNCHRONIZED_SOUND
case 4:
if (! POKEYSND_enable_new_pokey) POKEYSND_bienias_fix = !POKEYSND_bienias_fix;
case 9:
if (!POKEYSND_enable_new_pokey)
POKEYSND_bienias_fix = !POKEYSND_bienias_fix;
break;
#endif
#ifdef DREAMCAST
case 5:
glob_snd_ena = !glob_snd_ena;
break;
#endif
default:
#ifdef SOUND_THIN_API
if (!Sound_enabled)
/* Only store setup from menu in Sound_desired. */
Sound_desired = setup;
else if (setup.freq != Sound_desired.freq ||
setup.sample_size != Sound_desired.sample_size ||
#ifdef STEREO_SOUND
setup.channels != Sound_desired.channels ||
#endif
setup.frag_frames != Sound_desired.frag_frames) {
/* Sound output reinitialisation needed. */
Sound_desired = setup;
if (!Sound_Setup()) {
UI_driver->fMessage("Error: can't open sound device", 1);
/* Don't leave menu on failure. */
break;
}
setup = Sound_desired;
}
#endif /* SOUND_THIN_API */
return FALSE;
}
}
+2 -2
View File
@@ -55,10 +55,10 @@
#include "screen.h" /* Screen_atari */
#include "ui.h"
#include "util.h"
#include "ui_basic.h"
#ifdef DIRECTX
#include "win32\main.h"
#include "ui_basic.h"
#include "win32/main.h"
#endif
static int initialised = FALSE;
+2 -1
View File
@@ -9,7 +9,8 @@ extern UI_tDriver UI_BASIC_driver;
/* for Windows CE and Dreamcast */
#ifdef USE_UI_BASIC_ONSCREEN_KEYBOARD
int UI_BASIC_OnScreenKeyboard(const char *title, int layout);
extern int UI_BASIC_in_kbui;
extern int UI_BASIC_OnScreenKeyboard(const char *title, int layout);
/* layout must be one of MACHINE_* values (see atari.h)
or -1 for base keyboard with no function keys */
#endif
+77 -1
View File
@@ -2,7 +2,7 @@
* util.c - utility functions
*
* Copyright (c) 2005 Piotr Fusik
* Copyright (c) 2005 Atari800 development team (see DOC/CREDITS)
* Copyright (c) 2005-2013 Atari800 development team (see DOC/CREDITS)
*
* This file is part of the Atari800 emulator project which emulates
* the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
@@ -40,8 +40,19 @@
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# elif defined(HAVE_TIME_H)
# include <time.h>
# endif
#endif
#include "atari.h"
#include "platform.h"
#include "util.h"
int Util_chrieq(char c1, char c2)
@@ -438,3 +449,68 @@ int Util_unlink(const char *filename)
return (DeleteFile(filename) != 0) ? 0 : -1;
}
#endif /* defined(HAVE_WINDOWS_H) && defined(UNICODE) */
double Util_time(void)
{
#ifdef SUPPORTS_PLATFORM_TIME
return PLATFORM_Time();
#elif defined(HAVE_WINDOWS_H)
return GetTickCount() * 1e-3;
#elif defined(DJGPP)
/* DJGPP has gettimeofday, but it's not more accurate than uclock */
return uclock() * (1.0 / UCLOCKS_PER_SEC);
#elif defined(HAVE_GETTIMEOFDAY)
struct timeval tp;
gettimeofday(&tp, NULL);
return tp.tv_sec + 1e-6 * tp.tv_usec;
#elif defined(HAVE_UCLOCK)
return uclock() * (1.0 / UCLOCKS_PER_SEC);
#elif defined(HAVE_CLOCK)
return clock() * (1.0 / CLK_TCK);
#else
#error No function found for Util_time()
#endif
}
/* FIXME: Ports should use SUPPORTS_PLATFORM_SLEEP and SUPPORTS_PLATFORM_TIME */
/* and not this mess */
void Util_sleep(double s)
{
#ifdef SUPPORTS_PLATFORM_SLEEP
PLATFORM_Sleep(s);
#else /* !SUPPORTS_PLATFORM_SLEEP */
if (s > 0) {
#ifdef HAVE_WINDOWS_H
Sleep((DWORD) (s * 1e3));
#elif defined(DJGPP)
/* DJGPP has usleep and select, but they don't work that good */
/* XXX: find out why */
double curtime = Util_time();
while ((curtime + s) > Util_time());
#elif defined(HAVE_NANOSLEEP)
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = s * 1e9;
nanosleep(&ts, NULL);
#elif defined(HAVE_USLEEP)
usleep(s * 1e6);
#elif defined(__BEOS__)
/* added by Walter Las for BeOS */
snooze(s * 1e6);
#elif defined(__EMX__)
/* added by Brian Smith for os/2 */
DosSleep(s);
#elif defined(HAVE_SELECT)
/* linux */
struct timeval tp;
tp.tv_sec = 0;
tp.tv_usec = s * 1e6;
select(1, NULL, NULL, NULL, &tp);
#else
double curtime = Util_time();
while ((curtime + s) > Util_time());
#endif
}
#endif /* !SUPPORTS_PLATFORM_SLEEP */
}
+3
View File
@@ -199,4 +199,7 @@ FILE *Util_uniqopen(char *filename, const char *mode);
#define Util_fclose(fp, tmpbuf) fclose(fp)
#endif
void Util_sleep(double s);
double Util_time(void);
#endif /* UTIL_H_ */
+2 -33
View File
@@ -32,6 +32,7 @@
#ifdef AF80
#include "af80.h"
#endif
#include "artifact.h"
#include "atari.h"
#include "cfg.h"
#include "config.h"
@@ -175,9 +176,6 @@ static display_mode_t display_modes[VIDEOMODE_MODE_SIZE] = {
#endif
};
#if NTSC_FILTER
int VIDEOMODE_ntsc_filter = FALSE;
#endif
#if COLUMN_80
int VIDEOMODE_80_column = TRUE;
#endif
@@ -229,7 +227,7 @@ static VIDEOMODE_MODE_t CurrentDisplayMode(void)
}
#endif /* COLUMN_80 */
#if NTSC_FILTER
if (VIDEOMODE_ntsc_filter)
if (ARTIFACT_mode == ARTIFACT_NTSC_FULL)
return VIDEOMODE_MODE_NTSC_FILTER;
#endif
return VIDEOMODE_MODE_NORMAL;
@@ -762,18 +760,6 @@ int VIDEOMODE_ToggleRotate90(void)
}
#endif /* SUPPORTS_ROTATE_VIDEOMODE */
#if NTSC_FILTER
int VIDEOMODE_SetNtscFilter(int value)
{
return SetIntAndUpdateVideo(&VIDEOMODE_ntsc_filter, value);
}
int VIDEOMODE_ToggleNtscFilter(void)
{
return VIDEOMODE_SetNtscFilter(!VIDEOMODE_ntsc_filter);
}
#endif /* NTSC_FILTER */
#if COLUMN_80
int VIDEOMODE_Set80Column(int value)
{
@@ -969,10 +955,6 @@ int VIDEOMODE_ReadConfig(char *option, char *ptr)
else
return ParseAspectRatio(ptr, &VIDEOMODE_host_aspect_ratio_w, &VIDEOMODE_host_aspect_ratio_h);
}
#if NTSC_FILTER
else if (strcmp(option, "VIDEOMODE_NTSC_FILTER") == 0)
return (VIDEOMODE_ntsc_filter = Util_sscanbool(ptr)) != -1;
#endif
#if COLUMN_80
else if (strcmp(option, "VIDEOMODE_80_COLUMN") == 0)
return (VIDEOMODE_80_column = Util_sscanbool(ptr)) != -1;
@@ -1008,9 +990,6 @@ void VIDEOMODE_WriteConfig(FILE *fp) {
fprintf(fp, "VIDEOMODE_ROTATE90=%d\n", VIDEOMODE_rotate90);
#endif
fprintf(fp, "VIDEOMODE_HOST_ASPECT_RATIO=%g:%g\n", VIDEOMODE_host_aspect_ratio_w, VIDEOMODE_host_aspect_ratio_h);
#if NTSC_FILTER
fprintf(fp, "VIDEOMODE_NTSC_FILTER=%d\n", VIDEOMODE_ntsc_filter);
#endif
#if COLUMN_80
fprintf(fp, "VIDEOMODE_80_COLUMN=%d\n", VIDEOMODE_80_column);
#endif
@@ -1125,12 +1104,6 @@ int VIDEOMODE_Initialise(int *argc, char *argv[])
}
else a_m = TRUE;
}
#if NTSC_FILTER
else if (strcmp(argv[i], "-ntscemu") == 0)
VIDEOMODE_ntsc_filter = TRUE;
else if (strcmp(argv[i], "-no-ntscemu") == 0)
VIDEOMODE_ntsc_filter = FALSE;
#endif /* NTSC_FILTER */
#if COLUMN_80
else if (strcmp(argv[i], "-80column") == 0)
VIDEOMODE_80_column = TRUE;
@@ -1163,10 +1136,6 @@ int VIDEOMODE_Initialise(int *argc, char *argv[])
#endif /* SUPPORTS_ROTATE_VIDEOMODE */
Log_print("\t-host-aspect-ratio auto|<w>:<h>");
Log_print("\t Set host display aspect ratio");
#if NTSC_FILTER
Log_print("\t-ntscemu Enable NTSC composite video filter");
Log_print("\t-no-ntscemu Disable NTSC composite video filter");
#endif
#if COLUMN_80
Log_print("\t-80column Show output of an 80 column card, if present");
Log_print("\t-no-80column Show standard screen output");
-7
View File
@@ -210,13 +210,6 @@ typedef enum {
#endif
VIDEOMODE_MODE_SIZE
} VIDEOMODE_MODE_t;
#if NTSC_FILTER
/* Get/set state of NTSC filtering. */
/* Call VIDEOMODE_Update() after changing this variable, or use VIDEOMODE_SetNtscFilter() instead. */
extern int VIDEOMODE_ntsc_filter;
int VIDEOMODE_SetNtscFilter(int value);
int VIDEOMODE_ToggleNtscFilter(void);
#endif /* NTSC_FILTER */
#if defined(XEP80_EMULATION) || defined(PBI_PROTO80) || defined(AF80)
/* Indicates that 80 column display should be active when a 80 column card is available.
Setting to TRUE does not switch to 80 column display when no 80 column card is present. */