├── .gitignore ├── .gitmodules ├── Info.plist ├── MAME.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── MAMEGameCore.h ├── MAMEGameCore.m ├── MAME_Prefix.pch └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | build 3 | */Build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData/ 16 | .idea/ 17 | *.hmap 18 | 19 | # MAME 20 | *.a 21 | *.o 22 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "deps/mame"] 2 | path = deps/mame 3 | url = https://github.com/stuartcarnie/mame.git 4 | branch = mame0225-headless 5 | -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | OEGameCoreController 25 | OEGameCoreClass 26 | MAMEGameCore 27 | OEGameCoreOptions 28 | 29 | openemu.system.arcade 30 | 31 | OEGameCoreRewindBufferSeconds 32 | 10 33 | OEGameCoreRewindInterval 34 | 0 35 | OEGameCoreSupportsDisplayModeChange 36 | 37 | OEGameCoreSupportsRewinding 38 | 39 | 40 | 41 | OEGameCorePlayerCount 42 | 8 43 | OEProjectURL 44 | http://mamedev.org 45 | OESystemIdentifiers 46 | 47 | openemu.system.arcade 48 | 49 | SUEnableAutomaticChecks 50 | 1 51 | SUFeedURL 52 | https://raw.github.com/OpenEmu/OpenEmu-Update/master/mame_appcast.xml 53 | 54 | 55 | -------------------------------------------------------------------------------- /MAME.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 53; 7 | objects = { 8 | 9 | /* Begin PBXAggregateTarget section */ 10 | D0AADE271763813100759E26 /* Build & Install MAME */ = { 11 | isa = PBXAggregateTarget; 12 | buildConfigurationList = D0AADE281763813100759E26 /* Build configuration list for PBXAggregateTarget "Build & Install MAME" */; 13 | buildPhases = ( 14 | D0AADE2D1763815000759E26 /* ShellScript */, 15 | ); 16 | dependencies = ( 17 | D0AADE2C1763813900759E26 /* PBXTargetDependency */, 18 | ); 19 | name = "Build & Install MAME"; 20 | productName = "Build & Install MAME"; 21 | }; 22 | /* End PBXAggregateTarget section */ 23 | 24 | /* Begin PBXBuildFile section */ 25 | 0510AA1E2300825E002028C1 /* mamearcade_headless.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 0510AA1D2300825D002028C1 /* mamearcade_headless.dylib */; }; 26 | 0510AA1F23008294002028C1 /* mamearcade_headless.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = 0510AA1D2300825D002028C1 /* mamearcade_headless.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 27 | D00A068E1763763000C99008 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D00A068D1763763000C99008 /* Cocoa.framework */; }; 28 | D00A06A617637E9100C99008 /* MAMEGameCore.m in Sources */ = {isa = PBXBuildFile; fileRef = D00A06A517637E9100C99008 /* MAMEGameCore.m */; }; 29 | D0AADE31176382F900759E26 /* OpenEmuBase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0AADE30176382F900759E26 /* OpenEmuBase.framework */; }; 30 | /* End PBXBuildFile section */ 31 | 32 | /* Begin PBXContainerItemProxy section */ 33 | D0AADE2B1763813900759E26 /* PBXContainerItemProxy */ = { 34 | isa = PBXContainerItemProxy; 35 | containerPortal = D00A06821763762F00C99008 /* Project object */; 36 | proxyType = 1; 37 | remoteGlobalIDString = D00A06891763763000C99008; 38 | remoteInfo = MAME; 39 | }; 40 | /* End PBXContainerItemProxy section */ 41 | 42 | /* Begin PBXCopyFilesBuildPhase section */ 43 | 0510AA2023008294002028C1 /* Embed Libraries */ = { 44 | isa = PBXCopyFilesBuildPhase; 45 | buildActionMask = 2147483647; 46 | dstPath = ""; 47 | dstSubfolderSpec = 10; 48 | files = ( 49 | 0510AA1F23008294002028C1 /* mamearcade_headless.dylib in Embed Libraries */, 50 | ); 51 | name = "Embed Libraries"; 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | /* End PBXCopyFilesBuildPhase section */ 55 | 56 | /* Begin PBXFileReference section */ 57 | 050B7E8823775A04000ECB19 /* driver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = driver.h; path = deps/mame/src/osd/headless/public/driver.h; sourceTree = ""; }; 58 | 050B7E8923775A04000ECB19 /* oecommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = oecommon.h; path = deps/mame/src/osd/headless/public/oecommon.h; sourceTree = ""; }; 59 | 050B7E8A23775A04000ECB19 /* options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = options.h; path = deps/mame/src/osd/headless/public/options.h; sourceTree = ""; }; 60 | 050B7E8B23775A04000ECB19 /* headless.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = headless.h; path = deps/mame/src/osd/headless/public/headless.h; sourceTree = ""; }; 61 | 0510AA1B230081F3002028C1 /* inputenum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = inputenum.h; path = deps/mame/src/osd/headless/public/inputenum.h; sourceTree = ""; }; 62 | 0510AA1C230081F3002028C1 /* osd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = osd.h; path = deps/mame/src/osd/headless/public/osd.h; sourceTree = ""; }; 63 | 0510AA1D2300825D002028C1 /* mamearcade_headless.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = mamearcade_headless.dylib; path = deps/mame/mamearcade_headless.dylib; sourceTree = ""; }; 64 | 05334A951C52AEEF0066D493 /* CoreMIDI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = System/Library/Frameworks/CoreMIDI.framework; sourceTree = SDKROOT; }; 65 | 05334A981C52AF0E0066D493 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; }; 66 | 8C3132F7177F667D0002D0B9 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; 67 | D00A068A1763763000C99008 /* MAME.oecoreplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MAME.oecoreplugin; sourceTree = BUILT_PRODUCTS_DIR; }; 68 | D00A068D1763763000C99008 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 69 | D00A06921763763000C99008 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 70 | D00A069F17637AB600C99008 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 71 | D00A06A417637E9100C99008 /* MAMEGameCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MAMEGameCore.h; sourceTree = ""; }; 72 | D00A06A517637E9100C99008 /* MAMEGameCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MAMEGameCore.m; sourceTree = ""; }; 73 | D00A06A717637EB500C99008 /* OEArcadeSystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OEArcadeSystemResponderClient.h; path = ../OpenEmu/SystemPlugins/Arcade/OEArcadeSystemResponderClient.h; sourceTree = ""; }; 74 | D0AADE2F176381FB00759E26 /* MAME_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MAME_Prefix.pch; sourceTree = ""; }; 75 | D0AADE30176382F900759E26 /* OpenEmuBase.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = OpenEmuBase.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 76 | D0AADE331763838A00759E26 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 77 | D0AADE341763838A00759E26 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 78 | /* End PBXFileReference section */ 79 | 80 | /* Begin PBXFrameworksBuildPhase section */ 81 | D00A06871763763000C99008 /* Frameworks */ = { 82 | isa = PBXFrameworksBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | 0510AA1E2300825E002028C1 /* mamearcade_headless.dylib in Frameworks */, 86 | D00A068E1763763000C99008 /* Cocoa.framework in Frameworks */, 87 | D0AADE31176382F900759E26 /* OpenEmuBase.framework in Frameworks */, 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | /* End PBXFrameworksBuildPhase section */ 92 | 93 | /* Begin PBXGroup section */ 94 | D00A06811763762F00C99008 = { 95 | isa = PBXGroup; 96 | children = ( 97 | D00A06A317637BDD00C99008 /* Classes */, 98 | D0AADE2E176381E900759E26 /* Other Sources */, 99 | D00A06931763763000C99008 /* Resources */, 100 | D00A068C1763763000C99008 /* Frameworks */, 101 | D00A068B1763763000C99008 /* Products */, 102 | ); 103 | sourceTree = ""; 104 | }; 105 | D00A068B1763763000C99008 /* Products */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | D00A068A1763763000C99008 /* MAME.oecoreplugin */, 109 | ); 110 | name = Products; 111 | sourceTree = ""; 112 | }; 113 | D00A068C1763763000C99008 /* Frameworks */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | 0510AA1D2300825D002028C1 /* mamearcade_headless.dylib */, 117 | D0AADE30176382F900759E26 /* OpenEmuBase.framework */, 118 | D00A068F1763763000C99008 /* Linked Frameworks */, 119 | D0AADE321763833600759E26 /* Other Frameworks */, 120 | ); 121 | name = Frameworks; 122 | sourceTree = ""; 123 | }; 124 | D00A068F1763763000C99008 /* Linked Frameworks */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 05334A951C52AEEF0066D493 /* CoreMIDI.framework */, 128 | 05334A981C52AF0E0066D493 /* CoreAudio.framework */, 129 | D00A068D1763763000C99008 /* Cocoa.framework */, 130 | 8C3132F7177F667D0002D0B9 /* OpenGL.framework */, 131 | ); 132 | name = "Linked Frameworks"; 133 | sourceTree = ""; 134 | }; 135 | D00A06931763763000C99008 /* Resources */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | D00A069F17637AB600C99008 /* Info.plist */, 139 | ); 140 | name = Resources; 141 | sourceTree = ""; 142 | }; 143 | D00A06A317637BDD00C99008 /* Classes */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | D00A06A717637EB500C99008 /* OEArcadeSystemResponderClient.h */, 147 | D00A06A417637E9100C99008 /* MAMEGameCore.h */, 148 | D00A06A517637E9100C99008 /* MAMEGameCore.m */, 149 | D0BA5A9517645D630033A910 /* osd */, 150 | ); 151 | name = Classes; 152 | sourceTree = ""; 153 | }; 154 | D0AADE2E176381E900759E26 /* Other Sources */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | D0AADE2F176381FB00759E26 /* MAME_Prefix.pch */, 158 | ); 159 | name = "Other Sources"; 160 | sourceTree = ""; 161 | }; 162 | D0AADE321763833600759E26 /* Other Frameworks */ = { 163 | isa = PBXGroup; 164 | children = ( 165 | D0AADE331763838A00759E26 /* AppKit.framework */, 166 | D0AADE341763838A00759E26 /* CoreData.framework */, 167 | D00A06921763763000C99008 /* Foundation.framework */, 168 | ); 169 | name = "Other Frameworks"; 170 | sourceTree = ""; 171 | }; 172 | D0BA5A9517645D630033A910 /* osd */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | 050B7E8823775A04000ECB19 /* driver.h */, 176 | 050B7E8B23775A04000ECB19 /* headless.h */, 177 | 050B7E8923775A04000ECB19 /* oecommon.h */, 178 | 050B7E8A23775A04000ECB19 /* options.h */, 179 | 0510AA1B230081F3002028C1 /* inputenum.h */, 180 | 0510AA1C230081F3002028C1 /* osd.h */, 181 | ); 182 | name = osd; 183 | sourceTree = ""; 184 | }; 185 | /* End PBXGroup section */ 186 | 187 | /* Begin PBXNativeTarget section */ 188 | D00A06891763763000C99008 /* MAME */ = { 189 | isa = PBXNativeTarget; 190 | buildConfigurationList = D00A069C1763763000C99008 /* Build configuration list for PBXNativeTarget "MAME" */; 191 | buildPhases = ( 192 | D00A06861763763000C99008 /* Sources */, 193 | D00A06871763763000C99008 /* Frameworks */, 194 | D00A06881763763000C99008 /* Resources */, 195 | 0510AA2023008294002028C1 /* Embed Libraries */, 196 | 0510AA2123008883002028C1 /* ShellScript */, 197 | ); 198 | buildRules = ( 199 | ); 200 | dependencies = ( 201 | ); 202 | name = MAME; 203 | productName = MAME; 204 | productReference = D00A068A1763763000C99008 /* MAME.oecoreplugin */; 205 | productType = "com.apple.product-type.bundle"; 206 | }; 207 | /* End PBXNativeTarget section */ 208 | 209 | /* Begin PBXProject section */ 210 | D00A06821763762F00C99008 /* Project object */ = { 211 | isa = PBXProject; 212 | attributes = { 213 | BuildIndependentTargetsInParallel = YES; 214 | LastUpgradeCheck = 1330; 215 | ORGANIZATIONNAME = OpenEmu; 216 | }; 217 | buildConfigurationList = D00A06851763762F00C99008 /* Build configuration list for PBXProject "MAME" */; 218 | compatibilityVersion = "Xcode 10.0"; 219 | developmentRegion = English; 220 | hasScannedForEncodings = 0; 221 | knownRegions = ( 222 | English, 223 | en, 224 | ); 225 | mainGroup = D00A06811763762F00C99008; 226 | productRefGroup = D00A068B1763763000C99008 /* Products */; 227 | projectDirPath = ""; 228 | projectRoot = ""; 229 | targets = ( 230 | D00A06891763763000C99008 /* MAME */, 231 | D0AADE271763813100759E26 /* Build & Install MAME */, 232 | ); 233 | }; 234 | /* End PBXProject section */ 235 | 236 | /* Begin PBXResourcesBuildPhase section */ 237 | D00A06881763763000C99008 /* Resources */ = { 238 | isa = PBXResourcesBuildPhase; 239 | buildActionMask = 2147483647; 240 | files = ( 241 | ); 242 | runOnlyForDeploymentPostprocessing = 0; 243 | }; 244 | /* End PBXResourcesBuildPhase section */ 245 | 246 | /* Begin PBXShellScriptBuildPhase section */ 247 | 0510AA2123008883002028C1 /* ShellScript */ = { 248 | isa = PBXShellScriptBuildPhase; 249 | buildActionMask = 2147483647; 250 | files = ( 251 | ); 252 | inputFileListPaths = ( 253 | ); 254 | inputPaths = ( 255 | ); 256 | outputFileListPaths = ( 257 | ); 258 | outputPaths = ( 259 | ); 260 | runOnlyForDeploymentPostprocessing = 0; 261 | shellPath = /bin/sh; 262 | shellScript = "install_name_tool -change mamearcade_headless.dylib @rpath/mamearcade_headless.dylib ${TARGET_BUILD_DIR}/${EXECUTABLE_PATH}\n"; 263 | }; 264 | D0AADE2D1763815000759E26 /* ShellScript */ = { 265 | isa = PBXShellScriptBuildPhase; 266 | buildActionMask = 2147483647; 267 | files = ( 268 | ); 269 | inputPaths = ( 270 | ); 271 | outputPaths = ( 272 | ); 273 | runOnlyForDeploymentPostprocessing = 0; 274 | shellPath = /bin/sh; 275 | shellScript = "mkdir -p \"$USER_LIBRARY_DIR/Application Support/OpenEmu/Cores\"\nrm -rf \"$USER_LIBRARY_DIR/Application Support/OpenEmu/Cores/$PROJECT_NAME.oecoreplugin\"{,.dSYM}\ncp -rf \"$BUILT_PRODUCTS_DIR/$PROJECT_NAME.oecoreplugin\"{,.dSYM} \"$USER_LIBRARY_DIR/Application Support/OpenEmu/Cores/\""; 276 | }; 277 | /* End PBXShellScriptBuildPhase section */ 278 | 279 | /* Begin PBXSourcesBuildPhase section */ 280 | D00A06861763763000C99008 /* Sources */ = { 281 | isa = PBXSourcesBuildPhase; 282 | buildActionMask = 2147483647; 283 | files = ( 284 | D00A06A617637E9100C99008 /* MAMEGameCore.m in Sources */, 285 | ); 286 | runOnlyForDeploymentPostprocessing = 0; 287 | }; 288 | /* End PBXSourcesBuildPhase section */ 289 | 290 | /* Begin PBXTargetDependency section */ 291 | D0AADE2C1763813900759E26 /* PBXTargetDependency */ = { 292 | isa = PBXTargetDependency; 293 | target = D00A06891763763000C99008 /* MAME */; 294 | targetProxy = D0AADE2B1763813900759E26 /* PBXContainerItemProxy */; 295 | }; 296 | /* End PBXTargetDependency section */ 297 | 298 | /* Begin XCBuildConfiguration section */ 299 | D00A069A1763763000C99008 /* Debug */ = { 300 | isa = XCBuildConfiguration; 301 | buildSettings = { 302 | ARCHS = x86_64; 303 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 304 | CLANG_CXX_LANGUAGE_STANDARD = "c++14"; 305 | CLANG_CXX_LIBRARY = "compiler-default"; 306 | CLANG_DEBUG_INFORMATION_LEVEL = default; 307 | CLANG_ENABLE_MODULES = YES; 308 | CLANG_ENABLE_OBJC_ARC = YES; 309 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 310 | CLANG_WARN_BOOL_CONVERSION = YES; 311 | CLANG_WARN_COMMA = YES; 312 | CLANG_WARN_CONSTANT_CONVERSION = YES; 313 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 314 | CLANG_WARN_EMPTY_BODY = YES; 315 | CLANG_WARN_ENUM_CONVERSION = YES; 316 | CLANG_WARN_INFINITE_RECURSION = YES; 317 | CLANG_WARN_INT_CONVERSION = YES; 318 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 319 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 320 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 321 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 322 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 323 | CLANG_WARN_STRICT_PROTOTYPES = YES; 324 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 325 | CLANG_WARN_UNREACHABLE_CODE = YES; 326 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 327 | COPY_PHASE_STRIP = YES; 328 | DEAD_CODE_STRIPPING = NO; 329 | DEBUG_INFORMATION_FORMAT = dwarf; 330 | ENABLE_STRICT_OBJC_MSGSEND = YES; 331 | ENABLE_TESTABILITY = YES; 332 | GCC_C_LANGUAGE_STANDARD = gnu89; 333 | GCC_INCREASE_PRECOMPILED_HEADER_SHARING = YES; 334 | GCC_INPUT_FILETYPE = sourcecode.cpp.cpp; 335 | GCC_NO_COMMON_BLOCKS = YES; 336 | GCC_OPTIMIZATION_LEVEL = 0; 337 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 338 | GCC_PREFIX_HEADER = ""; 339 | GCC_PREPROCESSOR_DEFINITIONS = ( 340 | "DEBUG=1", 341 | "$(inherited)", 342 | ); 343 | GCC_SYMBOLS_PRIVATE_EXTERN = YES; 344 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 345 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 346 | GCC_WARN_UNDECLARED_SELECTOR = YES; 347 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 348 | GCC_WARN_UNUSED_FUNCTION = YES; 349 | GCC_WARN_UNUSED_VALUE = NO; 350 | GCC_WARN_UNUSED_VARIABLE = YES; 351 | MACOSX_DEPLOYMENT_TARGET = 10.15; 352 | ONLY_ACTIVE_ARCH = YES; 353 | PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; 354 | SDKROOT = macosx; 355 | }; 356 | name = Debug; 357 | }; 358 | D00A069B1763763000C99008 /* Release */ = { 359 | isa = XCBuildConfiguration; 360 | buildSettings = { 361 | ARCHS = x86_64; 362 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 363 | CLANG_CXX_LANGUAGE_STANDARD = "c++14"; 364 | CLANG_CXX_LIBRARY = "compiler-default"; 365 | CLANG_DEBUG_INFORMATION_LEVEL = default; 366 | CLANG_ENABLE_MODULES = YES; 367 | CLANG_ENABLE_OBJC_ARC = YES; 368 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 369 | CLANG_WARN_BOOL_CONVERSION = YES; 370 | CLANG_WARN_COMMA = YES; 371 | CLANG_WARN_CONSTANT_CONVERSION = YES; 372 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 373 | CLANG_WARN_EMPTY_BODY = YES; 374 | CLANG_WARN_ENUM_CONVERSION = YES; 375 | CLANG_WARN_INFINITE_RECURSION = YES; 376 | CLANG_WARN_INT_CONVERSION = YES; 377 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 378 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 379 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 380 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 381 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 382 | CLANG_WARN_STRICT_PROTOTYPES = YES; 383 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 384 | CLANG_WARN_UNREACHABLE_CODE = YES; 385 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 386 | COPY_PHASE_STRIP = YES; 387 | DEAD_CODE_STRIPPING = NO; 388 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 389 | ENABLE_STRICT_OBJC_MSGSEND = YES; 390 | ENABLE_TESTABILITY = NO; 391 | GCC_C_LANGUAGE_STANDARD = gnu89; 392 | GCC_INCREASE_PRECOMPILED_HEADER_SHARING = YES; 393 | GCC_INPUT_FILETYPE = sourcecode.cpp.cpp; 394 | GCC_NO_COMMON_BLOCKS = YES; 395 | GCC_OPTIMIZATION_LEVEL = 3; 396 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 397 | GCC_PREFIX_HEADER = ""; 398 | GCC_SYMBOLS_PRIVATE_EXTERN = YES; 399 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 400 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 401 | GCC_WARN_UNDECLARED_SELECTOR = YES; 402 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 403 | GCC_WARN_UNUSED_FUNCTION = YES; 404 | GCC_WARN_UNUSED_VALUE = NO; 405 | GCC_WARN_UNUSED_VARIABLE = YES; 406 | MACOSX_DEPLOYMENT_TARGET = 10.15; 407 | PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; 408 | SDKROOT = macosx; 409 | }; 410 | name = Release; 411 | }; 412 | D00A069D1763763000C99008 /* Debug */ = { 413 | isa = XCBuildConfiguration; 414 | buildSettings = { 415 | COMBINE_HIDPI_IMAGES = YES; 416 | CURRENT_PROJECT_VERSION = 0.250.0.1; 417 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 418 | GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; 419 | GCC_PRECOMPILE_PREFIX_HEADER = NO; 420 | HEADER_SEARCH_PATHS = ( 421 | "$(inherited)", 422 | "\"$(SRCROOT)/../OpenEmu/Arcade\"", 423 | "$(SRCROOT)/deps/mame/src/osd/headless/public", 424 | ); 425 | INFOPLIST_FILE = Info.plist; 426 | INSTALL_PATH = "\"$(USER_LIBRARY_DIR)/Application Support/OpenEmu/Cores\""; 427 | LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; 428 | LIBRARY_SEARCH_PATHS = ( 429 | "$(inherited)", 430 | "$(PROJECT_DIR)/deps/mame", 431 | ); 432 | PRODUCT_BUNDLE_IDENTIFIER = "org.openemu.${PRODUCT_NAME:rfc1034identifier}"; 433 | PRODUCT_NAME = "$(TARGET_NAME)"; 434 | SKIP_INSTALL = YES; 435 | WRAPPER_EXTENSION = oecoreplugin; 436 | }; 437 | name = Debug; 438 | }; 439 | D00A069E1763763000C99008 /* Release */ = { 440 | isa = XCBuildConfiguration; 441 | buildSettings = { 442 | COMBINE_HIDPI_IMAGES = YES; 443 | CURRENT_PROJECT_VERSION = 0.250.0.1; 444 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 445 | GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; 446 | GCC_PRECOMPILE_PREFIX_HEADER = NO; 447 | HEADER_SEARCH_PATHS = ( 448 | "$(inherited)", 449 | "\"$(SRCROOT)/../OpenEmu/Arcade\"", 450 | "$(SRCROOT)/deps/mame/src/osd/headless/public", 451 | ); 452 | INFOPLIST_FILE = Info.plist; 453 | INSTALL_PATH = "\"$(USER_LIBRARY_DIR)/Application Support/OpenEmu/Cores\""; 454 | LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; 455 | LIBRARY_SEARCH_PATHS = ( 456 | "$(inherited)", 457 | "$(PROJECT_DIR)/deps/mame", 458 | ); 459 | PRODUCT_BUNDLE_IDENTIFIER = "org.openemu.${PRODUCT_NAME:rfc1034identifier}"; 460 | PRODUCT_NAME = "$(TARGET_NAME)"; 461 | SKIP_INSTALL = YES; 462 | WRAPPER_EXTENSION = oecoreplugin; 463 | }; 464 | name = Release; 465 | }; 466 | D0AADE291763813100759E26 /* Debug */ = { 467 | isa = XCBuildConfiguration; 468 | buildSettings = { 469 | PRODUCT_NAME = "$(TARGET_NAME)"; 470 | }; 471 | name = Debug; 472 | }; 473 | D0AADE2A1763813100759E26 /* Release */ = { 474 | isa = XCBuildConfiguration; 475 | buildSettings = { 476 | PRODUCT_NAME = "$(TARGET_NAME)"; 477 | }; 478 | name = Release; 479 | }; 480 | /* End XCBuildConfiguration section */ 481 | 482 | /* Begin XCConfigurationList section */ 483 | D00A06851763762F00C99008 /* Build configuration list for PBXProject "MAME" */ = { 484 | isa = XCConfigurationList; 485 | buildConfigurations = ( 486 | D00A069A1763763000C99008 /* Debug */, 487 | D00A069B1763763000C99008 /* Release */, 488 | ); 489 | defaultConfigurationIsVisible = 0; 490 | defaultConfigurationName = Release; 491 | }; 492 | D00A069C1763763000C99008 /* Build configuration list for PBXNativeTarget "MAME" */ = { 493 | isa = XCConfigurationList; 494 | buildConfigurations = ( 495 | D00A069D1763763000C99008 /* Debug */, 496 | D00A069E1763763000C99008 /* Release */, 497 | ); 498 | defaultConfigurationIsVisible = 0; 499 | defaultConfigurationName = Release; 500 | }; 501 | D0AADE281763813100759E26 /* Build configuration list for PBXAggregateTarget "Build & Install MAME" */ = { 502 | isa = XCConfigurationList; 503 | buildConfigurations = ( 504 | D0AADE291763813100759E26 /* Debug */, 505 | D0AADE2A1763813100759E26 /* Release */, 506 | ); 507 | defaultConfigurationIsVisible = 0; 508 | defaultConfigurationName = Release; 509 | }; 510 | /* End XCConfigurationList section */ 511 | }; 512 | rootObject = D00A06821763762F00C99008 /* Project object */; 513 | } 514 | -------------------------------------------------------------------------------- /MAME.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MAMEGameCore.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013, OpenEmu Team 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the OpenEmu Team nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY OpenEmu Team ''AS IS'' AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL OpenEmu Team BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #import 28 | #import 29 | #import "OEArcadeSystemResponderClient.h" 30 | #import "osd.h" 31 | 32 | OE_EXPORTED_CLASS 33 | @interface MAMEGameCore : OEGameCore 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /MAMEGameCore.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013, OpenEmu Team 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the OpenEmu Team nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY OpenEmu Team ''AS IS'' AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL OpenEmu Team BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #import "MAMEGameCore.h" 28 | 29 | #import 30 | #import 31 | #import 32 | 33 | @interface MAMEAuditResult: NSObject 34 | 35 | /*! Returns the unique identifier of this result 36 | * 37 | * @remarks 38 | * 39 | * Identifier which groups resources by their driver, parent or CHD name 40 | */ 41 | @property (nonatomic, readonly) NSString *identifier; 42 | @property (nonatomic, readonly) NSString *fileName; 43 | 44 | - (instancetype)initWithDriver:(NSString *)driver auditRecord:(AuditRecord *)record; 45 | - (BOOL)checkSetExistsInDir:(NSURL *)dir; 46 | 47 | @end 48 | 49 | @interface MAMEGameCore () 50 | { 51 | uint32_t _buttons[8][OEArcadeButtonCount]; 52 | uint32_t _axes[8][InputMaxAxis]; 53 | 54 | uint32_t *_buffer; 55 | OEIntSize _bufferSize; 56 | OEIntRect _screenRect; 57 | OEIntSize _aspectSize; 58 | 59 | NSTimeInterval _frameInterval; 60 | 61 | 62 | // dylib 63 | void *_handle; 64 | OSD *_osd; 65 | BOOL _supportsRewinding; 66 | } 67 | 68 | @end 69 | 70 | static int32_t joystick_get_state(void *device_internal, void *item_internal) 71 | { 72 | return *(int32_t *)item_internal; 73 | } 74 | 75 | static os_log_t OE_CORE_LOG, OE_CORE_AUDIT_LOG; 76 | 77 | @implementation MAMEGameCore 78 | 79 | #pragma mark - Lifecycle 80 | 81 | + (void)initialize 82 | { 83 | OE_CORE_LOG = os_log_create("org.openemu.MAME", ""); 84 | OE_CORE_AUDIT_LOG = os_log_create("org.openemu.MAME", "audit"); 85 | } 86 | 87 | - (id)init 88 | { 89 | self = [super init]; 90 | if(!self) 91 | { 92 | return nil; 93 | } 94 | 95 | // Sensible defaults 96 | _bufferSize = OEIntSizeMake(1024, 1024); 97 | _frameInterval = 60; 98 | _screenRect = { {0,0}, _bufferSize }; 99 | _aspectSize = { 4, 3 }; 100 | 101 | _osd = [OSD shared]; 102 | _osd.delegate = self; 103 | 104 | return self; 105 | } 106 | 107 | #pragma mark - OSDDelegate 108 | 109 | - (void)didInitialize 110 | { 111 | // initialize joysticks 112 | for (int i = 0; i < 8; i++) { 113 | NSString *name = [NSString stringWithFormat:@"OpenEmu Player %d", i]; 114 | InputDevice *dev = [_osd.joystick addDeviceNamed:name]; 115 | [dev addItemNamed:@"X Axis" id:InputItemID_XAXIS getter:joystick_get_state context:&_axes[i][0]]; 116 | [dev addItemNamed:@"Y Axis" id:InputItemID_YAXIS getter:joystick_get_state context:&_axes[i][1]]; 117 | [dev addItemNamed:@"Start" id:InputItemID_START getter:joystick_get_state context:&_buttons[i][OEArcadeButtonP1Start]]; 118 | [dev addItemNamed:@"Insert Coin" id:InputItemID_SELECT getter:joystick_get_state context:&_buttons[i][OEArcadeButtonInsertCoin]]; 119 | [dev addItemNamed:@"Button 1" id:InputItemID_BUTTON1 getter:joystick_get_state context:&_buttons[i][OEArcadeButton1]]; 120 | [dev addItemNamed:@"Button 2" id:InputItemID_BUTTON2 getter:joystick_get_state context:&_buttons[i][OEArcadeButton2]]; 121 | [dev addItemNamed:@"Button 3" id:InputItemID_BUTTON3 getter:joystick_get_state context:&_buttons[i][OEArcadeButton3]]; 122 | [dev addItemNamed:@"Button 4" id:InputItemID_BUTTON4 getter:joystick_get_state context:&_buttons[i][OEArcadeButton4]]; 123 | [dev addItemNamed:@"Button 5" id:InputItemID_BUTTON5 getter:joystick_get_state context:&_buttons[i][OEArcadeButton5]]; 124 | [dev addItemNamed:@"Button 6" id:InputItemID_BUTTON6 getter:joystick_get_state context:&_buttons[i][OEArcadeButton6]]; 125 | } 126 | 127 | // Special keys 128 | InputDevice *kb = [_osd.keyboard addDeviceNamed:@"OpenEmu Keyboard"]; 129 | [kb addItemNamed:@"Service" id:InputItemID_F2 getter:joystick_get_state context:&_buttons[0][OEArcadeButtonService]]; 130 | [kb addItemNamed:@"UI Configure" id:InputItemID_TAB getter:joystick_get_state context:&_buttons[0][OEArcadeUIConfigure]]; 131 | } 132 | 133 | - (void)didChangeDisplayBounds:(NSSize)bounds fps:(double)fps aspect:(NSSize)aspect 134 | { 135 | _screenRect = {{0, 0}, OEIntSizeMake(bounds.width, bounds.height)}; 136 | 137 | // for single screen games: 138 | BOOL singleScreen = YES; 139 | if (singleScreen) 140 | { 141 | CGFloat newHeight = (aspect.height / aspect.width) * bounds.width; 142 | _aspectSize = OEIntSizeMake(bounds.width, newHeight); 143 | } 144 | else 145 | { 146 | _aspectSize = OEIntSizeMake(bounds.width, bounds.height); 147 | } 148 | 149 | _frameInterval = fps; 150 | } 151 | 152 | - (void)updateAudioBuffer:(const int16_t *)buffer samples:(NSInteger)samples 153 | { 154 | id buf = [self audioBufferAtIndex:0]; 155 | [buf write:buffer maxLength:samples * 2 * sizeof(int16_t)]; 156 | } 157 | 158 | - (void)logLevel:(OSDLogLevel)level message:(NSString *)msg 159 | { 160 | switch (level) { 161 | case OSDLogLevelError: 162 | os_log_error(OE_CORE_LOG, "%{public}s", msg.UTF8String); 163 | break; 164 | 165 | case OSDLogLevelVerbose: 166 | os_log_debug(OE_CORE_LOG, "%{public}s", msg.UTF8String); 167 | break; 168 | 169 | default: 170 | os_log_info(OE_CORE_LOG, "%{public}s", msg.UTF8String); 171 | break; 172 | } 173 | } 174 | 175 | #pragma mark - Execution 176 | 177 | BOOL driverIsNotWorking(GameDriverOptions o) 178 | { 179 | if ((o & GameDriverMachineNotWorking) == GameDriverMachineNotWorking) { 180 | return YES; 181 | } 182 | 183 | if ((o & GameDriverMachineIsSkeleton) == GameDriverMachineIsSkeleton) { 184 | return YES; 185 | } 186 | 187 | return NO; 188 | } 189 | 190 | - (BOOL)validateGameDriver:(GameDriver *)driver error:(NSError **)error 191 | { 192 | GameDriverOptions o = driver.flags; 193 | 194 | if (o & (GameDriverMachineClickableArtwork | GameDriverMachineRequiresArtwork | GameDriverMachineMechanical)) 195 | { 196 | if (error != nil) 197 | { 198 | *error = [NSError errorWithDomain:OEGameCoreErrorDomain code:OEGameCoreCouldNotLoadROMError userInfo:@{ 199 | NSLocalizedDescriptionKey : @"Unable to load ROM.", 200 | NSLocalizedRecoverySuggestionErrorKey: [NSString stringWithFormat:@"\"%@\" (%@).\n\nMechanical systems or systems which require artwork to operate are not supported.", driver.fullName, driver.name], 201 | }]; 202 | } 203 | return NO; 204 | } 205 | 206 | if (driverIsNotWorking(o)) { 207 | if (error != nil) 208 | { 209 | *error = [NSError errorWithDomain:OEGameCoreErrorDomain code:OEGameCoreCouldNotLoadROMError userInfo:@{ 210 | NSLocalizedDescriptionKey : @"Unable to load ROM.", 211 | NSLocalizedRecoverySuggestionErrorKey: [NSString stringWithFormat:@"\"%@\" (%@).\n\nThis machine does not work and the emulation is not yet complete. There is nothing you can do to fix this problem except wait for the MAME developers to improve the emulation.", driver.fullName, driver.name], 212 | }]; 213 | } 214 | return NO; 215 | } 216 | 217 | return YES; 218 | } 219 | 220 | - (BOOL)loadFileAtPath:(NSString *)path error:(NSError **)error 221 | { 222 | NSString *romDir = [path stringByDeletingLastPathComponent]; 223 | Options *opts = _osd.options; 224 | [opts setBasePath:self.supportDirectoryPath]; 225 | opts.romsPath = romDir; 226 | BOOL prev; 227 | prev = opts.autoStretchXY; 228 | opts.autoStretchXY = NO; 229 | prev = opts.unevenStretchX; 230 | opts.unevenStretchX = NO; 231 | prev = opts.unevenStretchY; 232 | opts.unevenStretchY = NO; 233 | prev = opts.unevenStretch; 234 | opts.unevenStretch = NO; 235 | opts.keepAspect = YES; 236 | 237 | _osd.verboseOutput = NO; // TODO: debug only; remove later 238 | 239 | NSString *rom = [[path lastPathComponent] stringByDeletingPathExtension]; 240 | AuditResult *ar; 241 | BOOL success = [_osd setDriver:rom withAuditResult:&ar error:error]; 242 | if (!success) 243 | { 244 | return NO; 245 | } 246 | 247 | if (![self validateGameDriver:_osd.driver error:error]) 248 | { 249 | return NO; 250 | } 251 | 252 | if (ar.summary == AuditSummaryIncorrect || ar.summary == AuditSummaryNotFound) 253 | { 254 | if (error != nil) 255 | { 256 | *error = [self processAuditResult:ar forRomDir:romDir]; 257 | } 258 | return NO; 259 | } 260 | 261 | if (![_osd initializeWithError:error]) 262 | { 263 | return NO; 264 | } 265 | 266 | _supportsRewinding = _osd.supportsSave && _osd.stateSize < 1e6; 267 | if (_osd.supportsSave && !_supportsRewinding) 268 | { 269 | os_log_info(OE_CORE_LOG, "disabling rewind support, save state size too big %{iec-bytes}ld", _osd.stateSize); 270 | } 271 | 272 | return YES; 273 | } 274 | 275 | - (NSError *)processAuditResult:(AuditResult *)ar forRomDir:(NSString *)romDir 276 | { 277 | GameDriver *driver = _osd.driver; 278 | NSString *gameDriverName = driver.name; 279 | NSMutableOrderedSet *results = [NSMutableOrderedSet new]; 280 | 281 | for (AuditRecord *rec in ar.records) { 282 | 283 | switch (rec.substatus) { 284 | case AuditSubstatusGood: 285 | continue; 286 | 287 | case AuditSubstatusFoundNodump: 288 | case AuditSubstatusGoodNeedsRedump: 289 | case AuditSubstatusNotFoundNoDump: 290 | case AuditSubstatusNotFoundOptional: 291 | // acceptable conditions, based on audit.cpp:media_auditor::summarize method, 292 | // which all result in a BEST_AVAILABLE status 293 | continue; 294 | 295 | // bad conditions 296 | 297 | case AuditSubstatusFoundWrongLength: { 298 | os_log_debug(OE_CORE_AUDIT_LOG, "wrong length: %{public}@, media type %ld", rec.name, rec.mediaType); 299 | [results addObject:[[MAMEAuditResult alloc] initWithDriver:gameDriverName auditRecord:rec]]; 300 | break; 301 | } 302 | 303 | case AuditSubstatusFoundBadChecksum: { 304 | os_log_debug(OE_CORE_AUDIT_LOG, "bad checksum: %{public}@, media type %ld", rec.name, rec.mediaType); 305 | [results addObject:[[MAMEAuditResult alloc] initWithDriver:gameDriverName auditRecord:rec]]; 306 | break; 307 | } 308 | 309 | case AuditSubstatusNotFound: { 310 | os_log_debug(OE_CORE_AUDIT_LOG, "not found: %{public}@, media type %ld", rec.name, rec.mediaType); 311 | [results addObject:[[MAMEAuditResult alloc] initWithDriver:gameDriverName auditRecord:rec]]; 312 | break; 313 | } 314 | 315 | case AuditSubstatusUnverified: 316 | default: 317 | continue; 318 | } 319 | } 320 | 321 | // Sort missing files by ascending order 322 | NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self" 323 | ascending:YES]; 324 | [results sortUsingDescriptors:@[sortDescriptor]]; 325 | 326 | // Determine if ROMs exist with missing files, or are not found 327 | NSURL *romDirURL = [NSURL fileURLWithPath:romDir isDirectory:YES]; 328 | NSMutableString *missingFilesList = [NSMutableString string]; 329 | for(MAMEAuditResult *result in results) 330 | { 331 | if ([result checkSetExistsInDir:romDirURL]) 332 | { 333 | [missingFilesList appendString:[NSString stringWithFormat:@"%@ \t- INCORRECT SET\n", result.fileName]]; 334 | } 335 | else 336 | { 337 | [missingFilesList appendString:[NSString stringWithFormat:@"%@ \t- NOT FOUND\n", result.fileName]]; 338 | } 339 | } 340 | 341 | // Give an audit report to the user 342 | NSString *game = [NSString stringWithFormat:@"%@ (%@.zip)", driver.fullName, gameDriverName]; 343 | NSString *versionRequired = [[[[[self owner] bundle] infoDictionary] objectForKey:@"CFBundleVersion"] substringToIndex:5]; 344 | 345 | NSError *outErr = [NSError errorWithDomain:OEGameCoreErrorDomain code:OEGameCoreCouldNotLoadROMError userInfo:@{ 346 | NSLocalizedDescriptionKey : @"Required files are missing.", 347 | NSLocalizedRecoverySuggestionErrorKey : [NSString stringWithFormat:@"%@ requires:\n\n%@\nThese ROMs must be from a MAME %@ ROM set. Some of these files can be parent/device/BIOS ROMs, which are not part of the game, but are still required. Delete files already imported and reimport with correct files.", game, missingFilesList, versionRequired], 348 | }]; 349 | 350 | return outErr; 351 | } 352 | 353 | - (void)resetEmulation 354 | { 355 | [_osd scheduleHardReset]; 356 | } 357 | 358 | #pragma mark - Video 359 | 360 | - (const void *)getVideoBufferWithHint:(void *)hint 361 | { 362 | _buffer = (uint32_t *)hint; 363 | [_osd setBuffer:hint size:NSSizeFromOEIntSize(_bufferSize)]; 364 | return _buffer; 365 | } 366 | 367 | - (OEIntSize)bufferSize 368 | { 369 | return _bufferSize; 370 | } 371 | 372 | - (OEIntRect)screenRect { 373 | return _screenRect; 374 | } 375 | 376 | - (OEIntSize)aspectSize 377 | { 378 | return _aspectSize; 379 | } 380 | 381 | - (GLenum)pixelFormat 382 | { 383 | return GL_BGRA; 384 | } 385 | 386 | - (GLenum)pixelType 387 | { 388 | return GL_UNSIGNED_INT_8_8_8_8_REV; 389 | } 390 | 391 | #pragma mark - execution 392 | 393 | - (void)executeFrame 394 | { 395 | [_osd execute]; 396 | } 397 | 398 | - (void)stopEmulation 399 | { 400 | [_osd unload]; 401 | _osd.delegate = nil; 402 | [super stopEmulation]; 403 | } 404 | 405 | - (NSTimeInterval)frameInterval 406 | { 407 | return _frameInterval; 408 | } 409 | 410 | #pragma mark - Audio 411 | 412 | - (double)audioSampleRate 413 | { 414 | return 48000; 415 | } 416 | 417 | - (NSUInteger)channelCount 418 | { 419 | return 2; 420 | } 421 | 422 | #pragma mark - Input 423 | 424 | - (void)setState:(BOOL)pressed ofButton:(OEArcadeButton)button forPlayer:(NSUInteger)player 425 | { 426 | _buttons[player-1][button] = pressed ? 1 : 0; 427 | _axes[player-1][0] = _buttons[player-1][OEArcadeButtonLeft] ? InputAbsoluteMin : (_buttons[player-1][OEArcadeButtonRight] ? InputAbsoluteMax : 0); 428 | _axes[player-1][1] = _buttons[player-1][OEArcadeButtonUp] ? InputAbsoluteMin : (_buttons[player-1][OEArcadeButtonDown] ? InputAbsoluteMax : 0); 429 | } 430 | 431 | - (oneway void)didPushArcadeButton:(OEArcadeButton)button forPlayer:(NSUInteger)player 432 | { 433 | [self setState:YES ofButton:button forPlayer:player]; 434 | } 435 | 436 | - (oneway void)didReleaseArcadeButton:(OEArcadeButton)button forPlayer:(NSUInteger)player 437 | { 438 | [self setState:NO ofButton:button forPlayer:player]; 439 | } 440 | 441 | #pragma mark - Save State 442 | 443 | - (void)saveStateToFileAtPath:(NSString *)fileName completionHandler:(void (^)(BOOL, NSError *))block 444 | { 445 | BOOL res = NO; 446 | NSError *err = nil; 447 | 448 | if (_osd.supportsSave) 449 | { 450 | res = [_osd saveStateFromFileAtPath:fileName error:&err]; 451 | } 452 | else 453 | { 454 | err = [NSError errorWithDomain:OEGameCoreErrorDomain code:OEGameCoreCouldNotSaveStateError userInfo:@{ 455 | NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Game \"%@\" does not not support save states.", _osd.driver.fullName], 456 | }]; 457 | } 458 | 459 | block(res, err); 460 | } 461 | 462 | - (void)loadStateFromFileAtPath:(NSString *)fileName completionHandler:(void (^)(BOOL, NSError *))block 463 | { 464 | BOOL res = NO; 465 | NSError *err = nil; 466 | 467 | if (_osd.supportsSave) 468 | { 469 | res = [_osd loadStateFromFileAtPath:fileName error:&err]; 470 | } 471 | else 472 | { 473 | err = [NSError errorWithDomain:OEGameCoreErrorDomain code:OEGameCoreCouldNotSaveStateError userInfo:@{ 474 | NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Game \"%@\" does not not support save states.", _osd.driver.fullName], 475 | }]; 476 | } 477 | 478 | block(res, err); 479 | } 480 | 481 | - (BOOL)supportsRewinding 482 | { 483 | return _supportsRewinding; 484 | } 485 | 486 | - (NSData *)serializeStateWithError:(NSError *__autoreleasing *)outError 487 | { 488 | return [_osd serializeState]; 489 | } 490 | 491 | - (BOOL)deserializeState:(NSData *)state withError:(NSError *__autoreleasing *)outError 492 | { 493 | return [_osd deserializeState:state]; 494 | } 495 | 496 | @end 497 | 498 | @implementation MAMEAuditResult 499 | { 500 | NSString *_driver; 501 | AuditRecord *_record; 502 | } 503 | 504 | - (instancetype)initWithDriver:(NSString *)driver auditRecord:(AuditRecord *)record 505 | { 506 | if ((self = [super init])) 507 | { 508 | _driver = driver; 509 | _record = record; 510 | } 511 | return self; 512 | } 513 | 514 | - (NSString *)identifier 515 | { 516 | if (_record.mediaType == AuditMediaTypeDisk) 517 | { 518 | // a CHD 519 | return _record.name; 520 | } 521 | 522 | Device *parent = _record.sharedDevice; 523 | if (parent) 524 | { 525 | return parent.shortName; 526 | } 527 | 528 | return _driver; 529 | } 530 | 531 | - (NSArray *)extensions 532 | { 533 | if (_record.mediaType == AuditMediaTypeDisk) 534 | { 535 | return @[@".chd"]; 536 | } 537 | 538 | return @[@".zip", @".7z"]; 539 | } 540 | 541 | - (BOOL)isEqual:(id)object 542 | { 543 | if (object == nil || ![object isKindOfClass:self.class]) 544 | { 545 | return NO; 546 | } 547 | 548 | MAMEAuditResult *other = (MAMEAuditResult *)object; 549 | return self.identifier == other.identifier; 550 | } 551 | 552 | - (NSComparisonResult)compare:(MAMEAuditResult *)other 553 | { 554 | return [self.identifier compare:other.identifier]; 555 | } 556 | 557 | /*! Returns the first valid file name for this result 558 | */ 559 | - (NSString *)fileName 560 | { 561 | return [self.identifier stringByAppendingString:[[self extensions] firstObject]]; 562 | } 563 | 564 | /*! Determines if the ROM set exists 565 | */ 566 | - (BOOL)checkSetExistsInDir:(NSURL *)dir 567 | { 568 | for (NSString *ext in [self extensions]) 569 | { 570 | NSURL *missingFileURL = [dir URLByAppendingPathComponent:[self.identifier stringByAppendingString:ext]]; 571 | 572 | if([missingFileURL checkResourceIsReachableAndReturnError:nil]) 573 | { 574 | return YES; 575 | } 576 | } 577 | return NO; 578 | } 579 | 580 | - (NSUInteger)hash 581 | { 582 | return self.identifier.hash; 583 | } 584 | 585 | @end 586 | -------------------------------------------------------------------------------- /MAME_Prefix.pch: -------------------------------------------------------------------------------- 1 | #include "osd_config.h" 2 | #include "osdcomm.h" 3 | 4 | #ifdef __OBJC__ 5 | #import 6 | #endif 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | UME-Core 2 | ======== 3 | 4 | OpenEmu Core plugin for UME 5 | 6 | Building 7 | -------- 8 | 9 | You must build the `mamearcade_headless.dylib` dynamic library before building the MAME Game core: 10 | 11 | ```sh 12 | $ cd deps/mame 13 | $ make macosx_x64_clang OSD="headless" verbose=1 TARGETOS="macosx" CONFIG="release" TARGET=mame SUBTARGET=arcade MACOSX_DEPLOYMENT_TARGET=12.4 -j8 14 | $ install_name_tool -id mamearcade_headless.dylib mamearcade_headless.dylib 15 | ``` 16 | 17 | Depending on your hardware, this could take a _long_ time, but if successful, you will have a file named `mamearcade_headless.dylib` in the current directory. 18 | 19 | Build the UME project, which will link and embed this binary and update the loader path automatically. 20 | 21 | --------------------------------------------------------------------------------