2009-06-09 13:34:52 +02:00
//
2011-06-08 11:27:25 +02:00
// PcsxrPlugin . m
// Pcsxr
2009-06-09 13:34:52 +02:00
//
// Created by Gil Pedersen on Fri Oct 03 2003.
// Copyright ( c ) 2003 __MyCompanyName __ . All rights reserved .
//
# import < Cocoa / Cocoa . h >
2011-06-08 11:27:25 +02:00
# import "PcsxrPlugin.h"
2009-06-09 13:34:52 +02:00
# include "psxcommon.h"
# include "plugins.h"
2013-01-09 02:50:38 +01:00
# import "ARCBridge.h"
2009-06-09 13:34:52 +02:00
2011-06-08 11:27:25 +02:00
@ implementation PcsxrPlugin
2009-06-09 13:34:52 +02:00
2011-11-12 23:50:37 +01:00
+ ( NSString * ) prefixForType : ( int ) aType
2009-06-09 13:34:52 +02:00
{
switch ( aType ) {
2013-01-10 21:46:32 +01:00
case PSE_LT _GPU : return @ "GPU" ; break ;
case PSE_LT _CDR : return @ "CDR" ; break ;
case PSE_LT _SPU : return @ "SPU" ; break ;
case PSE_LT _PAD : return @ "PAD" ; break ;
case PSE_LT _NET : return @ "NET" ; break ;
2013-07-05 03:04:08 +02:00
case PSE_LT _SIO1 : return @ "SIO1" ; break ;
2009-06-09 13:34:52 +02:00
}
return @ "" ;
}
2011-11-12 23:50:37 +01:00
+ ( NSString * ) defaultKeyForType : ( int ) aType
2009-06-09 13:34:52 +02:00
{
2011-11-12 23:50:37 +01:00
// return @ "Plugin" [ PcsxrPlugin prefixForType : aType ] ;
2009-06-09 13:34:52 +02:00
switch ( aType ) {
2012-09-23 21:24:03 +02:00
case PSE_LT _GPU :
case PSE_LT _CDR :
case PSE_LT _SPU :
case PSE_LT _PAD :
case PSE_LT _NET :
2013-07-05 03:04:08 +02:00
case PSE_LT _SIO1 :
2013-01-14 23:10:02 +01:00
return [ NSString stringWithFormat : @ "Plugin%@" , [ self prefixForType : aType ] ] ;
2012-09-23 21:24:03 +02:00
break ;
default :
return @ "" ;
break ;
2009-06-09 13:34:52 +02:00
}
}
2011-11-12 23:50:37 +01:00
+ ( char * * ) configEntriesForType : ( int ) aType
2009-06-09 13:34:52 +02:00
{
static char * gpu [ 2 ] = { ( char * ) & Config . Gpu , NULL } ;
static char * cdr [ 2 ] = { ( char * ) & Config . Cdr , NULL } ;
static char * spu [ 2 ] = { ( char * ) & Config . Spu , NULL } ;
static char * pad [ 3 ] = { ( char * ) & Config . Pad1 , ( char * ) & Config . Pad2 , NULL } ;
static char * net [ 2 ] = { ( char * ) & Config . Net , NULL } ;
2013-07-05 03:04:08 +02:00
static char * sio1 [ 2 ] = { ( char * ) & Config . Sio1 , NULL } ;
2009-06-09 13:34:52 +02:00
switch ( aType ) {
case PSE_LT _GPU : return ( char * * ) gpu ;
case PSE_LT _CDR : return ( char * * ) cdr ;
case PSE_LT _SPU : return ( char * * ) spu ;
case PSE_LT _PAD : return ( char * * ) pad ;
case PSE_LT _NET : return ( char * * ) net ;
2013-07-05 03:04:08 +02:00
case PSE_LT _SIO1 : return ( char * * ) sio1 ;
2009-06-09 13:34:52 +02:00
}
return nil ;
}
2011-12-17 21:41:31 +01:00
+ ( NSArray * ) pluginsPaths
{
2012-09-23 21:24:03 +02:00
static NSArray * returnArray = nil ;
if ( returnArray = = nil )
{
2013-01-14 23:10:02 +01:00
@ autoreleasepool {
NSURL * supportURL = [ [ NSFileManager defaultManager ] URLForDirectory : NSApplicationSupportDirectory inDomain : NSUserDomainMask appropriateForURL : nil create : YES error : NULL ] ;
NSURL * libraryURL = [ [ NSFileManager defaultManager ] URLForDirectory : NSLibraryDirectory inDomain : NSUserDomainMask appropriateForURL : nil create : YES error : NULL ] ;
NSURL * localSupportURL = [ [ NSFileManager defaultManager ] URLForDirectory : NSApplicationSupportDirectory inDomain : NSLocalDomainMask appropriateForURL : nil create : YES error : NULL ] ;
NSURL * localLibraryURL = [ [ NSFileManager defaultManager ] URLForDirectory : NSLibraryDirectory inDomain : NSLocalDomainMask appropriateForURL : nil create : YES error : NULL ] ;
NSMutableArray * mutArray = [ NSMutableArray arrayWithCapacity : 5 ] ;
[ mutArray addObject : [ [ NSFileManager defaultManager ] stringWithFileSystemRepresentation : Config . PluginsDir length : strlen ( Config . PluginsDir ) ] ] ;
NSURL * url = [ localLibraryURL URLByAppendingPathComponent : @ "Playstation Emulator Plugins" ] ;
if ( [ url checkResourceIsReachableAndReturnError : NULL ] )
[ mutArray addObject : [ url path ] ] ;
url = [ [ localSupportURL URLByAppendingPathComponent : @ "Pcsxr" ] URLByAppendingPathComponent : @ "PlugIns" ] ;
if ( [ url checkResourceIsReachableAndReturnError : NULL ] )
[ mutArray addObject : [ url path ] ] ;
url = [ libraryURL URLByAppendingPathComponent : @ "Playstation Emulator Plugins" ] ;
if ( [ url checkResourceIsReachableAndReturnError : NULL ] )
[ mutArray addObject : [ url path ] ] ;
url = [ [ supportURL URLByAppendingPathComponent : @ "Pcsxr" ] URLByAppendingPathComponent : @ "PlugIns" ] ;
if ( [ url checkResourceIsReachableAndReturnError : NULL ] )
[ mutArray addObject : [ url path ] ] ;
returnArray = [ [ NSArray alloc ] initWithArray : mutArray ] ;
}
2012-09-23 21:24:03 +02:00
}
return returnArray ;
2011-12-17 21:41:31 +01:00
}
2013-01-10 02:02:14 +01:00
@ synthesize path ;
@ synthesize name ;
2009-06-09 13:34:52 +02:00
- ( id ) initWithPath : ( NSString * ) aPath
{
if ( ! ( self = [ super init ] ) ) {
return nil ;
}
PSEgetLibType PSE_getLibType = NULL ;
PSEgetLibVersion PSE_getLibVersion = NULL ;
PSEgetLibName PSE_getLibName = NULL ;
2013-01-10 02:02:14 +01:00
NSFileManager * fm = [ NSFileManager defaultManager ] ;
2013-01-29 20:16:02 +01:00
pluginRef = NULL ;
2009-06-09 13:34:52 +02:00
name = nil ;
2012-10-13 22:39:01 +02:00
path = [ aPath copy ] ;
2011-12-17 21:41:31 +01:00
NSString * goodPath = nil ;
2013-01-10 02:02:14 +01:00
if ( [ aPath isAbsolutePath ] ) {
goodPath = aPath ;
} else {
long tempVers = 0 ;
for ( NSString * plugDir in [ PcsxrPlugin pluginsPaths ] )
{
NSString * fullPath = [ plugDir stringByAppendingPathComponent : path ] ;
if ( [ fm fileExistsAtPath : fullPath ] ) {
void * tempHandle = SysLoadLibrary ( [ fullPath fileSystemRepresentation ] ) ;
if ( tempHandle ! = NULL )
2011-12-20 01:20:40 +01:00
{
2013-01-10 02:02:14 +01:00
PSEgetLibVersion tempLibVersion = SysLoadSym ( tempHandle , "PSEgetLibVersion" ) ;
if ( SysLibError ( ) = = NULL )
{
long tempVers2 = tempLibVersion ( ) ;
2013-01-10 21:46:32 +01:00
if ( tempVers < tempVers2 ) {
2013-01-10 02:02:14 +01:00
goodPath = fullPath ;
tempVers = tempVers2 ;
if ( ! [ plugDir isEqualToString : [ fm stringWithFileSystemRepresentation : Config . PluginsDir length : strlen ( Config . PluginsDir ) ] ] ) {
RELEASEOBJ ( path ) ;
path = [ goodPath copy ] ;
}
}
2011-12-20 01:20:40 +01:00
}
2013-01-10 02:02:14 +01:00
SysCloseLibrary ( tempHandle ) ;
2013-07-05 09:11:57 +02:00
} else {
SysLibError ( ) ;
2011-12-20 01:20:40 +01:00
}
2011-12-18 01:46:51 +01:00
}
2011-12-17 21:41:31 +01:00
}
2009-06-09 13:34:52 +02:00
}
2011-12-29 01:03:28 +01:00
if ( goodPath = = nil ) {
2013-01-29 20:16:02 +01:00
AUTORELEASEOBJNORETURN ( self ) ;
2011-12-29 01:03:28 +01:00
return nil ;
}
2011-12-17 21:41:31 +01:00
pluginRef = SysLoadLibrary ( [ goodPath fileSystemRepresentation ] ) ;
2013-01-10 02:02:14 +01:00
if ( pluginRef = = NULL ) {
2013-01-29 20:16:02 +01:00
AUTORELEASEOBJNORETURN ( self ) ;
2012-10-13 22:39:01 +02:00
return nil ;
}
2011-12-17 21:41:31 +01:00
2009-06-09 13:34:52 +02:00
// TODO : add support for plugins with multiple functionalities ? ? ?
PSE_getLibType = ( PSEgetLibType ) SysLoadSym ( pluginRef , "PSEgetLibType" ) ;
if ( SysLibError ( ) ! = nil ) {
if ( ( [ path rangeOfString : @ "gpu" options : NSCaseInsensitiveSearch ] ) . length ! = 0 )
type = PSE_LT _GPU ;
else if ( ( [ path rangeOfString : @ "cdr" options : NSCaseInsensitiveSearch ] ) . length ! = 0 )
type = PSE_LT _CDR ;
else if ( ( [ path rangeOfString : @ "spu" options : NSCaseInsensitiveSearch ] ) . length ! = 0 )
type = PSE_LT _SPU ;
else if ( ( [ path rangeOfString : @ "pad" options : NSCaseInsensitiveSearch ] ) . length ! = 0 )
type = PSE_LT _PAD ;
2011-11-30 00:47:19 +01:00
else if ( ( [ path rangeOfString : @ "net" options : NSCaseInsensitiveSearch ] ) . length ! = 0 )
type = PSE_LT _NET ;
2013-07-05 03:04:08 +02:00
else if ( ( [ path rangeOfString : @ "sio1" options : NSCaseInsensitiveSearch ] ) . length ! = 0 )
type = PSE_LT _SIO1 ;
2009-06-09 13:34:52 +02:00
else {
2013-01-29 20:16:02 +01:00
AUTORELEASEOBJNORETURN ( self ) ;
2009-06-09 13:34:52 +02:00
return nil ;
}
} else {
type = ( int ) PSE_getLibType ( ) ;
2013-07-05 03:04:08 +02:00
if ( type ! = PSE_LT _GPU && type ! = PSE_LT _CDR && type ! = PSE_LT _SPU && type ! = PSE_LT _PAD && type ! = PSE_LT _NET && type ! = PSE_LT _SIO1 ) {
2013-01-29 20:16:02 +01:00
AUTORELEASEOBJNORETURN ( self ) ;
2009-06-09 13:34:52 +02:00
return nil ;
}
}
PSE_getLibName = ( PSEgetLibName ) SysLoadSym ( pluginRef , "PSEgetLibName" ) ;
if ( SysLibError ( ) = = nil ) {
2011-11-09 21:49:54 +01:00
name = [ [ NSString alloc ] initWithCString : PSE_getLibName ( ) encoding : NSUTF8StringEncoding ] ;
2009-06-09 13:34:52 +02:00
}
PSE_getLibVersion = ( PSEgetLibVersion ) SysLoadSym ( pluginRef , "PSEgetLibVersion" ) ;
if ( SysLibError ( ) = = nil ) {
version = PSE_getLibVersion ( ) ;
2012-10-13 22:39:01 +02:00
} else {
2009-06-09 13:34:52 +02:00
version = -1 ;
}
// save the current modification date
2013-01-14 23:10:02 +01:00
NSDictionary * fattrs = [ fm attributesOfItemAtPath : [ goodPath stringByResolvingSymlinksInPath ] error : NULL ] ;
2013-01-09 02:50:38 +01:00
modDate = RETAINOBJ ( [ fattrs fileModificationDate ] ) ;
fullPlugPath = RETAINOBJ ( goodPath ) ;
2009-06-09 13:34:52 +02:00
active = 0 ;
return self ;
}
- ( void ) dealloc
{
int i ;
// shutdown if we had previously been inited
for ( i = 0 ; i < 32 ; i + + ) {
if ( active & ( 1 < < i ) ) {
[ self shutdownAs : ( 1 < < i ) ] ;
}
}
if ( pluginRef ) SysCloseLibrary ( pluginRef ) ;
2013-01-14 23:10:02 +01:00
# if ! __has _feature ( objc_arc )
[ modDate release ] ;
[ path release ] ;
[ name release ] ;
[ fullPlugPath release ] ;
2009-06-09 13:34:52 +02:00
2013-01-14 23:10:02 +01:00
[ super dealloc ] ;
# endif
2009-06-09 13:34:52 +02:00
}
- ( void ) runCommand : ( id ) arg
{
2013-01-09 02:50:38 +01:00
@ autoreleasepool {
NSString * funcName = [ arg objectAtIndex : 0 ] ;
long ( * func ) ( void ) ;
func = SysLoadSym ( pluginRef , [ funcName cStringUsingEncoding : NSASCIIStringEncoding ] ) ;
if ( SysLibError ( ) = = nil ) {
func ( ) ;
} else {
NSBeep ( ) ;
}
RELEASEOBJ ( arg ) ;
return ;
2009-06-09 13:34:52 +02:00
}
}
2012-10-13 22:39:01 +02:00
- ( long ) runAs : ( int ) aType
2009-06-09 13:34:52 +02:00
{
char symbol [ 255 ] ;
2011-11-09 21:49:54 +01:00
long ( * init ) ( ) ;
2009-06-09 13:34:52 +02:00
long ( * initArg ) ( long arg ) ;
int res = PSE_ERR _FATAL ;
if ( ( active & aType ) = = aType ) {
return 0 ;
}
2012-09-23 21:24:03 +02:00
sprintf ( symbol , "%sinit" , [ [ PcsxrPlugin prefixForType : aType ] cStringUsingEncoding : NSASCIIStringEncoding ] ) ;
2009-06-09 13:34:52 +02:00
init = initArg = SysLoadSym ( pluginRef , symbol ) ;
if ( SysLibError ( ) = = nil ) {
2012-10-13 22:39:01 +02:00
if ( aType ! = PSE_LT _PAD ) {
2009-06-09 13:34:52 +02:00
res = init ( ) ;
2012-10-13 22:39:01 +02:00
} else {
2009-06-09 13:34:52 +02:00
res = initArg ( 1 | 2 ) ;
2012-10-13 22:39:01 +02:00
}
2009-06-09 13:34:52 +02:00
}
if ( 0 = = res ) {
active | = aType ;
} else {
NSRunCriticalAlertPanel ( NSLocalizedString ( @ "Plugin Initialization Failed!" , nil ) ,
2012-10-13 22:39:01 +02:00
[ NSString stringWithFormat : NSLocalizedString ( @ "Pcsxr failed to initialize the selected %@ plugin (error=%i).\nThe plugin might not work with your system." , nil ) , [ PcsxrPlugin prefixForType : aType ] , res ] ,
2009-06-09 13:34:52 +02:00
nil , nil , nil ) ;
}
return res ;
}
- ( long ) shutdownAs : ( int ) aType
{
char symbol [ 255 ] ;
long ( * shutdown ) ( void ) ;
2012-09-23 21:24:03 +02:00
sprintf ( symbol , "%sshutdown" , [ [ PcsxrPlugin prefixForType : aType ] cStringUsingEncoding : NSASCIIStringEncoding ] ) ;
2009-06-09 13:34:52 +02:00
shutdown = SysLoadSym ( pluginRef , symbol ) ;
if ( SysLibError ( ) = = nil ) {
active & = ~ aType ;
return shutdown ( ) ;
}
return PSE_ERR _FATAL ;
}
- ( BOOL ) hasAboutAs : ( int ) aType
{
char symbol [ 255 ] ;
2012-09-23 21:24:03 +02:00
sprintf ( symbol , "%sabout" , [ [ PcsxrPlugin prefixForType : aType ] cStringUsingEncoding : NSASCIIStringEncoding ] ) ;
2009-06-09 13:34:52 +02:00
SysLoadSym ( pluginRef , symbol ) ;
return ( SysLibError ( ) = = nil ) ;
}
- ( BOOL ) hasConfigureAs : ( int ) aType
{
char symbol [ 255 ] ;
2012-09-23 21:24:03 +02:00
sprintf ( symbol , "%sconfigure" , [ [ PcsxrPlugin prefixForType : aType ] cStringUsingEncoding : NSASCIIStringEncoding ] ) ;
2009-06-09 13:34:52 +02:00
SysLoadSym ( pluginRef , symbol ) ;
return ( SysLibError ( ) = = nil ) ;
}
- ( void ) aboutAs : ( int ) aType
{
NSArray * arg ;
char symbol [ 255 ] ;
2012-09-23 21:24:03 +02:00
sprintf ( symbol , "%sabout" , [ [ PcsxrPlugin prefixForType : aType ] cStringUsingEncoding : NSASCIIStringEncoding ] ) ;
arg = [ [ NSArray alloc ] initWithObjects : [ NSString stringWithCString : symbol encoding : NSASCIIStringEncoding ] ,
2009-06-09 13:34:52 +02:00
[ NSNumber numberWithInt : 0 ] , nil ] ;
// detach a new thread
[ NSThread detachNewThreadSelector : @ selector ( runCommand : ) toTarget : self
withObject : arg ] ;
2012-09-23 21:24:03 +02:00
// NOTE : the runCommand releases the arg command . Probably not the best way to do it . . .
2013-01-10 05:21:36 +01:00
// This is not an issue with ARC ( 64 - bit ) code
2009-06-09 13:34:52 +02:00
}
- ( void ) configureAs : ( int ) aType
{
NSArray * arg ;
char symbol [ 255 ] ;
2012-09-23 21:24:03 +02:00
sprintf ( symbol , "%sconfigure" , [ [ PcsxrPlugin prefixForType : aType ] cStringUsingEncoding : NSASCIIStringEncoding ] ) ;
arg = [ [ NSArray alloc ] initWithObjects : [ NSString stringWithCString : symbol encoding : NSASCIIStringEncoding ] ,
2009-06-09 13:34:52 +02:00
[ NSNumber numberWithInt : 1 ] , nil ] ;
// detach a new thread
[ NSThread detachNewThreadSelector : @ selector ( runCommand : ) toTarget : self
withObject : arg ] ;
2012-09-23 21:24:03 +02:00
// NOTE : the runCommand releases the arg command . Probably not the best way to do it . . .
2013-01-10 05:21:36 +01:00
// This is not an issue with ARC ( 64 - bit ) code
2009-06-09 13:34:52 +02:00
}
2011-11-12 23:50:37 +01:00
- ( NSString * ) displayVersion
2009-06-09 13:34:52 +02:00
{
if ( version = = -1 )
return @ "" ;
return [ NSString stringWithFormat : @ "v%ld.%ld.%ld" , version > > 16 , ( version > > 8 ) & 0 xff , version & 0 xff ] ;
}
2011-11-12 23:50:37 +01:00
- ( int ) type
2009-06-09 13:34:52 +02:00
{
return type ;
}
2011-11-12 21:07:20 +01:00
- ( NSUInteger ) hash
2009-06-09 13:34:52 +02:00
{
return [ path hash ] ;
}
- ( NSString * ) description
{
if ( name = = nil )
return [ path lastPathComponent ] ;
2011-11-12 23:50:37 +01:00
return [ NSString stringWithFormat : @ "%@ %@ [%@]" , name , [ self displayVersion ] , [ path lastPathComponent ] ] ;
2009-06-09 13:34:52 +02:00
}
2013-01-10 21:46:32 +01:00
- ( NSString * ) debugDescription
{
if ( name = = nil ) {
return fullPlugPath ;
}
2013-01-14 23:10:02 +01:00
return [ NSString stringWithFormat : @ "%@, %@ [%@]" , name , [ self displayVersion ] , fullPlugPath ] ;
2013-01-10 21:46:32 +01:00
}
2009-06-09 13:34:52 +02:00
// the plugin will check if it ' s still valid and return the status
- ( BOOL ) verifyOK
{
// check that the file is still there with the same modification date
NSFileManager * dfm = [ NSFileManager defaultManager ] ;
2011-12-17 22:44:51 +01:00
if ( ! [ dfm fileExistsAtPath : fullPlugPath ] )
2009-06-09 13:34:52 +02:00
return NO ;
2011-12-17 22:44:51 +01:00
NSDictionary * fattrs = [ dfm attributesOfItemAtPath : [ fullPlugPath stringByResolvingSymlinksInPath ] error : NULL ] ;
2009-06-09 13:34:52 +02:00
return [ [ fattrs fileModificationDate ] isEqualToDate : modDate ] ;
}
@ end