mirror of
https://github.com/OpenEmu/OpenEmuKit.git
synced 2025-11-01 11:08:14 +00:00
Port OECorePlugin to Swift
This commit is contained in:
@@ -67,9 +67,8 @@
|
||||
05E6BA1324CCD56200ACFB35 /* OpenEmuSystem.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05E6BA1224CCD56200ACFB35 /* OpenEmuSystem.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
05E6BA1D24CCD71D00ACFB35 /* OESystemPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05E6BA1724CCD71600ACFB35 /* OESystemPlugin.swift */; };
|
||||
05E6BA1E24CCD71D00ACFB35 /* OEPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 05E6BA1824CCD71800ACFB35 /* OEPlugin.m */; };
|
||||
05E6BA2024CCD71D00ACFB35 /* OECorePlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 05E6BA1A24CCD71B00ACFB35 /* OECorePlugin.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
05E6BA2124CCD71D00ACFB35 /* OEPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 05E6BA1B24CCD71C00ACFB35 /* OEPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
05E6BA2224CCD71D00ACFB35 /* OECorePlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 05E6BA1C24CCD71D00ACFB35 /* OECorePlugin.m */; };
|
||||
05E6BA2224CCD71D00ACFB35 /* OECorePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05E6BA1C24CCD71D00ACFB35 /* OECorePlugin.swift */; };
|
||||
05E6BA3024CCD77600ACFB35 /* OEGameLayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05E6BA2D24CCD77300ACFB35 /* OEGameLayerView.swift */; };
|
||||
05E6BA3D24CCD79600ACFB35 /* OELogging.m in Sources */ = {isa = PBXBuildFile; fileRef = 05E6BA3724CCD79300ACFB35 /* OELogging.m */; };
|
||||
05E6BA3E24CCD79600ACFB35 /* OEThreadProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 05E6BA3824CCD79500ACFB35 /* OEThreadProxy.m */; };
|
||||
@@ -178,9 +177,8 @@
|
||||
05E6BA1224CCD56200ACFB35 /* OpenEmuSystem.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OpenEmuSystem.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
05E6BA1724CCD71600ACFB35 /* OESystemPlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OESystemPlugin.swift; sourceTree = "<group>"; };
|
||||
05E6BA1824CCD71800ACFB35 /* OEPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OEPlugin.m; sourceTree = "<group>"; };
|
||||
05E6BA1A24CCD71B00ACFB35 /* OECorePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OECorePlugin.h; sourceTree = "<group>"; };
|
||||
05E6BA1B24CCD71C00ACFB35 /* OEPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OEPlugin.h; sourceTree = "<group>"; };
|
||||
05E6BA1C24CCD71D00ACFB35 /* OECorePlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OECorePlugin.m; sourceTree = "<group>"; };
|
||||
05E6BA1C24CCD71D00ACFB35 /* OECorePlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OECorePlugin.swift; sourceTree = "<group>"; };
|
||||
05E6BA2D24CCD77300ACFB35 /* OEGameLayerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OEGameLayerView.swift; sourceTree = "<group>"; };
|
||||
05E6BA3624CCD79200ACFB35 /* OEThreadProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OEThreadProxy.h; sourceTree = "<group>"; };
|
||||
05E6BA3724CCD79300ACFB35 /* OELogging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OELogging.m; sourceTree = "<group>"; };
|
||||
@@ -410,8 +408,7 @@
|
||||
children = (
|
||||
05E6BA1B24CCD71C00ACFB35 /* OEPlugin.h */,
|
||||
05E6BA1824CCD71800ACFB35 /* OEPlugin.m */,
|
||||
05E6BA1A24CCD71B00ACFB35 /* OECorePlugin.h */,
|
||||
05E6BA1C24CCD71D00ACFB35 /* OECorePlugin.m */,
|
||||
05E6BA1C24CCD71D00ACFB35 /* OECorePlugin.swift */,
|
||||
05E6BA1724CCD71600ACFB35 /* OESystemPlugin.swift */,
|
||||
);
|
||||
name = Plugins;
|
||||
@@ -506,7 +503,6 @@
|
||||
05E6BA3F24CCD79600ACFB35 /* OELogging.h in Headers */,
|
||||
05E6BA2124CCD71D00ACFB35 /* OEPlugin.h in Headers */,
|
||||
054A2C0C278CDA6A00A2F241 /* KeyValueScanner+Private.h in Headers */,
|
||||
05E6BA2024CCD71D00ACFB35 /* OECorePlugin.h in Headers */,
|
||||
054A2C0A278CDA5A00A2F241 /* KeyValueScanner.h in Headers */,
|
||||
05E6958424CA5D4200ACFB35 /* OpenEmuKit.h in Headers */,
|
||||
);
|
||||
@@ -698,7 +694,7 @@
|
||||
05201D6F277D316E0028CBE0 /* UserDefaultsPresetStorage.swift in Sources */,
|
||||
0572A424287B89CD00AC32F8 /* OEGameStartupInfo.swift in Sources */,
|
||||
05E6BA1E24CCD71D00ACFB35 /* OEPlugin.m in Sources */,
|
||||
05E6BA2224CCD71D00ACFB35 /* OECorePlugin.m in Sources */,
|
||||
05E6BA2224CCD71D00ACFB35 /* OECorePlugin.swift in Sources */,
|
||||
0572A4132878D76C00AC32F8 /* GameRenderer.swift in Sources */,
|
||||
0553DE2E27B5B83F0085512F /* String+Extensions.swift in Sources */,
|
||||
054A2C0E278CDA7800A2F241 /* KeyValueScanner.m in Sources */,
|
||||
|
||||
@@ -33,5 +33,4 @@ FOUNDATION_EXPORT const unsigned char OpenEmuKitVersionString[];
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <OpenEmuKit/PublicHeader.h>
|
||||
|
||||
#import <OpenEmuKit/OEPlugin.h>
|
||||
#import <OpenEmuKit/OECorePlugin.h>
|
||||
#import <OpenEmuKit/NSFileManager+ExtendedAttributes.h>
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2009, OpenEmu Team
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the OpenEmu Team nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY OpenEmu Team ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL OpenEmu Team BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
@import Cocoa;
|
||||
#import <OpenEmuKit/OEPlugin.h>
|
||||
|
||||
@class OEGameCoreController;
|
||||
|
||||
@interface OECorePlugin : OEPlugin
|
||||
|
||||
@property(readonly) OEGameCoreController *controller;
|
||||
|
||||
@property(readonly) Class gameCoreClass;
|
||||
@property(readonly) NSString *bundleIdentifier;
|
||||
@property(readonly) NSArray<NSString *> *systemIdentifiers;
|
||||
@property(readonly) NSArray *requiredFiles;
|
||||
@property(readonly) NSDictionary *coreOptions;
|
||||
|
||||
@property(class, readonly) NSArray <OECorePlugin *> *allPlugins;
|
||||
|
||||
+ (OECorePlugin *)corePluginWithBundleAtPath:(NSString *)bundlePath;
|
||||
+ (OECorePlugin *)corePluginWithBundleIdentifier:(NSString *)identifier;
|
||||
+ (NSArray<OECorePlugin *> *)corePluginsForSystemIdentifier:(NSString *)systemIdentifier;
|
||||
+ (NSArray *)requiredFiles;
|
||||
|
||||
@end
|
||||
@@ -1,239 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2009, OpenEmu Team
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the OpenEmu Team nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY OpenEmu Team ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL OpenEmu Team BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#import "OECorePlugin.h"
|
||||
#import <OpenEmuBase/OpenEmuBase.h>
|
||||
|
||||
@implementation OECorePlugin
|
||||
@synthesize controller = _controller, gameCoreClass = _gameCoreClass;
|
||||
|
||||
static NSArray *_cachedRequiredFiles = nil;
|
||||
|
||||
- (OEGameCoreController *)controller
|
||||
{
|
||||
if (_controller == nil)
|
||||
{
|
||||
Class principalClass = [[self bundle] principalClass];
|
||||
_controller = [self newPluginControllerWithClass:principalClass];
|
||||
}
|
||||
return _controller;
|
||||
}
|
||||
|
||||
+ (NSArray <OECorePlugin *> *)allPlugins
|
||||
{
|
||||
return [OEPlugin pluginsForType:self];
|
||||
}
|
||||
|
||||
+ (NSString *)pluginFolder
|
||||
{
|
||||
return @"Cores";
|
||||
}
|
||||
|
||||
+ (NSString *)pluginExtension
|
||||
{
|
||||
return @"oecoreplugin";
|
||||
}
|
||||
|
||||
+ (OECorePlugin *)corePluginWithBundleAtPath:(NSString *)bundlePath
|
||||
{
|
||||
return [self pluginWithBundleAtPath:bundlePath type:self];
|
||||
}
|
||||
|
||||
+ (OECorePlugin *)corePluginWithBundleIdentifier:(NSString *)identifier
|
||||
{
|
||||
NSArray *cores = [OECorePlugin pluginsForType:self];
|
||||
for(OECorePlugin *plugin in cores)
|
||||
if([[plugin bundleIdentifier] caseInsensitiveCompare:identifier] == NSOrderedSame)
|
||||
return plugin;
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (NSArray *)corePluginsForSystemIdentifier:(NSString *)systemIdentifier;
|
||||
{
|
||||
NSArray *cores = [self allPlugins];
|
||||
NSMutableArray *validCores = [NSMutableArray array];
|
||||
|
||||
for(OECorePlugin *plugin in cores)
|
||||
if([[plugin systemIdentifiers] containsObject:systemIdentifier])
|
||||
[validCores addObject:plugin];
|
||||
|
||||
return validCores;
|
||||
}
|
||||
|
||||
+ (NSArray *)requiredFiles;
|
||||
{
|
||||
if(_cachedRequiredFiles == nil)
|
||||
{
|
||||
NSMutableArray *files = [[NSMutableArray alloc] init];
|
||||
for(OECorePlugin *plugin in [OEPlugin pluginsForType:self])
|
||||
if([plugin requiredFiles] != nil) [files addObjectsFromArray:[plugin requiredFiles]];
|
||||
|
||||
_cachedRequiredFiles = [files copy];
|
||||
}
|
||||
|
||||
return _cachedRequiredFiles;
|
||||
}
|
||||
|
||||
- (instancetype)initWithBundleAtPath:(NSString *)aPath name:(NSString *)aName error:(NSError *__autoreleasing *)outError
|
||||
{
|
||||
if((self = [super initWithBundleAtPath:aPath name:aName error:outError]))
|
||||
{
|
||||
// invalidate global cache
|
||||
_cachedRequiredFiles = nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)newPluginControllerWithClass:(Class)bundleClass
|
||||
{
|
||||
if(![bundleClass isSubclassOfClass:[OEGameCoreController class]]) return nil;
|
||||
|
||||
return [[bundleClass alloc] initWithBundle:[self bundle]];
|
||||
}
|
||||
|
||||
- (NSString *)bundleIdentifier
|
||||
{
|
||||
return [[self infoDictionary] objectForKey:@"CFBundleIdentifier"];
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)systemIdentifiers;
|
||||
{
|
||||
return [[self infoDictionary] objectForKey:OEGameCoreSystemIdentifiersKey];
|
||||
}
|
||||
|
||||
- (NSDictionary *)coreOptions
|
||||
{
|
||||
return [[self infoDictionary] objectForKey:OEGameCoreOptionsKey];
|
||||
}
|
||||
|
||||
- (NSArray *)requiredFiles
|
||||
{
|
||||
id options = [self coreOptions];
|
||||
NSMutableArray *allRequiredFiles = [NSMutableArray array];
|
||||
|
||||
for (id key in options) {
|
||||
id resultDict = [options objectForKey:key];
|
||||
if([resultDict objectForKey:OEGameCoreRequiredFilesKey] != nil)
|
||||
[allRequiredFiles addObjectsFromArray:[resultDict objectForKey:OEGameCoreRequiredFilesKey]];
|
||||
}
|
||||
|
||||
if([allRequiredFiles count] > 0)
|
||||
return [allRequiredFiles copy];
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (Class)gameCoreClass
|
||||
{
|
||||
if (_gameCoreClass == Nil)
|
||||
{
|
||||
[[self bundle] load];
|
||||
_gameCoreClass = NSClassFromString([[self infoDictionary] objectForKey:OEGameCoreClassKey]);
|
||||
}
|
||||
|
||||
return _gameCoreClass;
|
||||
}
|
||||
|
||||
- (BOOL)_isMarkedDeprecatedInInfoPlist
|
||||
{
|
||||
if (![self.infoDictionary[OEGameCoreDeprecatedKey] boolValue])
|
||||
return NO;
|
||||
|
||||
NSString *minOSXVer = self.infoDictionary[OEGameCoreDeprecatedMinMacOSVersionKey];
|
||||
if (!minOSXVer)
|
||||
return YES;
|
||||
NSArray *osxVerComponents = [minOSXVer componentsSeparatedByString:@"."];
|
||||
if (osxVerComponents.count < 2)
|
||||
return YES;
|
||||
NSOperatingSystemVersion minOsxVerParsed = (NSOperatingSystemVersion){
|
||||
atoi([osxVerComponents[0] UTF8String]),
|
||||
atoi([osxVerComponents[1] UTF8String]),
|
||||
osxVerComponents.count > 2 ? atoi([osxVerComponents[2] UTF8String]) : 0};
|
||||
if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:minOsxVerParsed])
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)isDeprecated
|
||||
{
|
||||
if (self.isOutOfSupport)
|
||||
return YES;
|
||||
return [self _isMarkedDeprecatedInInfoPlist];
|
||||
}
|
||||
|
||||
- (BOOL)isOutOfSupport
|
||||
{
|
||||
/* plugins deprecated 2017-11-04 */
|
||||
NSString *bundleName = [[[self bundle] bundleURL] lastPathComponent];
|
||||
NSArray *deprecatedPlugins = @[
|
||||
@"Dolphin-Core.oecoreplugin",
|
||||
@"NeoPop.oecoreplugin",
|
||||
@"TwoMbit.oecoreplugin",
|
||||
@"VisualBoyAdvance.oecoreplugin",
|
||||
@"Yabause.oecoreplugin"];
|
||||
if ([deprecatedPlugins containsObject:bundleName])
|
||||
return YES;
|
||||
|
||||
/* beta-era plugins */
|
||||
NSString *appcastURL = self.infoDictionary[@"SUFeedURL"];
|
||||
if ([appcastURL containsString:@"openemu.org/update"])
|
||||
return YES;
|
||||
|
||||
/* plugins marked as deprecated in the Info.plist keys */
|
||||
if ([self _isMarkedDeprecatedInInfoPlist]) {
|
||||
NSDate *deadline = self.infoDictionary[OEGameCoreSupportDeadlineKey];
|
||||
if (!deadline) return NO;
|
||||
if ([[NSDate date] compare:deadline] == NSOrderedDescending) {
|
||||
// we are past the support deadline; return YES to remove the core
|
||||
[self _prepareForRemoval];
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)_prepareForRemoval
|
||||
{
|
||||
NSDictionary *replacements = self.infoDictionary[OEGameCoreSuggestedReplacement];
|
||||
|
||||
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
|
||||
for (NSString *system in self.systemIdentifiers) {
|
||||
NSString *replacement = [replacements objectForKey:system];
|
||||
NSString *prefKey = [@"defaultCore." stringByAppendingString:system];
|
||||
NSString *currentCore = [ud stringForKey:prefKey];
|
||||
if (currentCore && [currentCore isEqual:self.bundleIdentifier]) {
|
||||
if (replacement)
|
||||
[ud setObject:replacement forKey:prefKey];
|
||||
else
|
||||
[ud removeObjectForKey:prefKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,224 @@
|
||||
// Copyright (c) 2021, OpenEmu Team
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the OpenEmu Team nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY OpenEmu Team ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL OpenEmu Team BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import Foundation
|
||||
import OpenEmuBase
|
||||
|
||||
public class OECorePlugin: OEPlugin {
|
||||
|
||||
override public class var pluginExtension: String {
|
||||
"oecoreplugin"
|
||||
}
|
||||
|
||||
override public class var pluginFolder: String {
|
||||
"Cores"
|
||||
}
|
||||
|
||||
@objc public class var allPlugins: [OECorePlugin] {
|
||||
return OEPlugin.plugins(forType: Self.self) as? [OECorePlugin] ?? []
|
||||
}
|
||||
|
||||
override public required init(bundleAtPath path: String, name: String?) throws {
|
||||
try super.init(bundleAtPath: path, name: name)
|
||||
|
||||
// invalidate global cache
|
||||
Self.cachedRequiredFiles = nil
|
||||
}
|
||||
|
||||
public static func corePlugin(bundleAtPath bundlePath: String) -> OECorePlugin? {
|
||||
return OEPlugin(bundleAtPath: bundlePath, type: Self.self) as? OECorePlugin
|
||||
}
|
||||
|
||||
public static func corePlugin(bundleIdentifier identifier: String) -> OECorePlugin? {
|
||||
return allPlugins.first(where: {
|
||||
$0.bundleIdentifier.caseInsensitiveCompare(identifier) == .orderedSame
|
||||
})
|
||||
}
|
||||
|
||||
public static func corePlugins(forSystemIdentifier identifier: String) -> [OECorePlugin] {
|
||||
var validCores: [OECorePlugin] = []
|
||||
|
||||
for plugin in allPlugins {
|
||||
if plugin.systemIdentifiers.contains(identifier) {
|
||||
validCores.append(plugin)
|
||||
}
|
||||
}
|
||||
|
||||
return validCores
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
typealias Controller = OEGameCoreController
|
||||
|
||||
private var _controller: Controller?
|
||||
public var controller: OEGameCoreController! {
|
||||
if _controller == nil,
|
||||
let principalClass = bundle.principalClass
|
||||
{
|
||||
_controller = newPluginController(with: principalClass)
|
||||
}
|
||||
return _controller
|
||||
}
|
||||
|
||||
private func newPluginController(with bundleClass: AnyClass) -> Controller? {
|
||||
guard bundleClass.isSubclass(of: Controller.self) else { return nil }
|
||||
return (bundleClass as! Controller.Type).init(bundle: bundle)
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
private static var cachedRequiredFiles: [[String : Any]]?
|
||||
public static var requiredFiles: [[String : Any]] {
|
||||
if cachedRequiredFiles == nil {
|
||||
var files: [[String : Any]] = []
|
||||
for plugin in allPlugins {
|
||||
files.append(contentsOf: plugin.requiredFiles)
|
||||
}
|
||||
|
||||
cachedRequiredFiles = files
|
||||
}
|
||||
|
||||
return cachedRequiredFiles!
|
||||
}
|
||||
|
||||
public var gameCoreClass: AnyClass? {
|
||||
return controller?.gameCoreClass
|
||||
}
|
||||
|
||||
public var bundleIdentifier: String {
|
||||
return infoDictionary["CFBundleIdentifier"] as! String
|
||||
}
|
||||
|
||||
public var systemIdentifiers: [String] {
|
||||
return infoDictionary[OEGameCoreSystemIdentifiersKey] as? [String] ?? []
|
||||
}
|
||||
|
||||
public var coreOptions: [String : Any] {
|
||||
return infoDictionary[OEGameCoreOptionsKey] as? [String : Any] ?? [:]
|
||||
}
|
||||
|
||||
public var requiredFiles: [[String : Any]] {
|
||||
var allRequiredFiles: [[String : Any]] = []
|
||||
|
||||
for value in coreOptions.values {
|
||||
if let resultDict = value as? [String : Any],
|
||||
let object = resultDict[OEGameCoreRequiredFilesKey] as? [[String : Any]]
|
||||
{
|
||||
allRequiredFiles.append(contentsOf: object)
|
||||
}
|
||||
}
|
||||
|
||||
return allRequiredFiles
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
private var isMarkedDeprecatedInInfoPlist: Bool {
|
||||
if infoDictionary[OEGameCoreDeprecatedKey] as? Bool != true {
|
||||
return false
|
||||
}
|
||||
|
||||
func isValidVersionString(_ string: String) -> Bool {
|
||||
if string.isEmpty { return false }
|
||||
let validCharacters: Set<Character> = [".", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
|
||||
return Set(string).isSubset(of: validCharacters)
|
||||
}
|
||||
|
||||
guard let minMacOSVer = self.infoDictionary[OEGameCoreDeprecatedMinMacOSVersionKey] as? String,
|
||||
isValidVersionString(minMacOSVer)
|
||||
else { return true }
|
||||
|
||||
let macOSVerComponents = minMacOSVer.components(separatedBy: ".")
|
||||
if macOSVerComponents.count < 2 {
|
||||
return true
|
||||
}
|
||||
let minMacOSVerParsed = OperatingSystemVersion(majorVersion: Int(macOSVerComponents[0])!,
|
||||
minorVersion: Int(macOSVerComponents[1])!,
|
||||
patchVersion: macOSVerComponents.count > 2 ? Int(macOSVerComponents[2])! : 0)
|
||||
if ProcessInfo.processInfo.isOperatingSystemAtLeast(minMacOSVerParsed) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override public var isDeprecated: Bool {
|
||||
if isOutOfSupport {
|
||||
return true
|
||||
}
|
||||
return isMarkedDeprecatedInInfoPlist
|
||||
}
|
||||
|
||||
override public var isOutOfSupport: Bool {
|
||||
// plugins deprecated 2017-11-04
|
||||
let bundleFileName = bundle.bundleURL.lastPathComponent
|
||||
let deprecatedPlugins = [
|
||||
"Dolphin-Core.oecoreplugin",
|
||||
"NeoPop.oecoreplugin",
|
||||
"TwoMbit.oecoreplugin",
|
||||
"VisualBoyAdvance.oecoreplugin",
|
||||
"Yabause.oecoreplugin",
|
||||
]
|
||||
if deprecatedPlugins.contains(bundleFileName) {
|
||||
return true
|
||||
}
|
||||
|
||||
// beta-era plugins
|
||||
if let appcastURL = infoDictionary["SUFeedURL"] as? String,
|
||||
appcastURL.contains("openemu.org/update")
|
||||
{
|
||||
return true
|
||||
}
|
||||
|
||||
// plugins marked as deprecated in the Info.plist keys
|
||||
if isMarkedDeprecatedInInfoPlist,
|
||||
let deadline = infoDictionary[OEGameCoreSupportDeadlineKey] as? Date,
|
||||
Date().compare(deadline) == .orderedDescending
|
||||
{
|
||||
// we are past the support deadline; return true to remove the core
|
||||
prepareForRemoval()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private func prepareForRemoval() {
|
||||
let replacements = infoDictionary[OEGameCoreSuggestedReplacement] as? [String : String]
|
||||
|
||||
let defaults = UserDefaults.standard
|
||||
for systemIdentifier in systemIdentifiers {
|
||||
let prefKey = "defaultCore." + systemIdentifier
|
||||
if let currentCore = defaults.string(forKey: prefKey),
|
||||
currentCore == bundleIdentifier
|
||||
{
|
||||
if let replacement = replacements?[systemIdentifier] {
|
||||
defaults.set(replacement, forKey: prefKey)
|
||||
} else {
|
||||
defaults.removeObject(forKey: prefKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -251,7 +251,7 @@ extension OSLog {
|
||||
_systemController = OESystemPlugin.systemPlugin(bundleAtPath: info.systemPluginPath)!.controller
|
||||
_systemResponder = _systemController.newGameSystemResponder()
|
||||
|
||||
_gameController = OECorePlugin(bundleAtPath: info.corePluginPath).controller
|
||||
_gameController = OECorePlugin.corePlugin(bundleAtPath: info.corePluginPath)!.controller
|
||||
gameCore = _gameController.newGameCore()
|
||||
|
||||
let systemIdentifier = _systemController.systemIdentifier!
|
||||
|
||||
Reference in New Issue
Block a user