Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d2f745873a | |||
| 30217f1573 | |||
| 99b00cb506 | |||
| d5ada05caa | |||
| a44d58c3f2 | |||
| ffa7f54c7b | |||
| 9bfc60ba63 | |||
| e67fec4d66 | |||
| 34d0634d33 | |||
| 0b0cb4efa1 | |||
| b8fded2733 | |||
| 9edbc12ada | |||
| 99aa528027 | |||
| d0ff1ae969 | |||
| 85ff87c8df | |||
| 85a1a68886 | |||
| eb317a7914 | |||
| 3b9eaf63b9 | |||
| 66d5fbcaa0 | |||
| 268551a95e | |||
| f657e9b60e |
@@ -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;
|
||||
|
||||
@@ -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.
@@ -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:
|
||||
|
||||
@@ -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
@@ -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 *) >IA_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);
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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[]);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user