pcsxr-1.9.92
[pcsx_rearmed.git] / macosx / PcsxPlugin.m
CommitLineData
ef79bbde
P
1//
2// PcsxPlugin.m
3// Pcsx
4//
5// Created by Gil Pedersen on Fri Oct 03 2003.
6// Copyright (c) 2003 __MyCompanyName__. All rights reserved.
7//
8
9#import <Cocoa/Cocoa.h>
10#import "PcsxPlugin.h"
11#include "psxcommon.h"
12#include "plugins.h"
13
14@implementation PcsxPlugin
15
16+ (NSString *)getPrefixForType:(int)aType
17{
18 switch (aType) {
19 case PSE_LT_GPU: return @"GPU";
20 case PSE_LT_CDR: return @"CDR";
21 case PSE_LT_SPU: return @"SPU";
22 case PSE_LT_PAD: return @"PAD";
23 case PSE_LT_NET: return @"NET";
24 }
25
26 return @"";
27}
28
29+ (NSString *)getDefaultKeyForType:(int)aType
30{
31 //return @"Plugin" [PcsxPlugin getPrefixForType:aType];
32 switch (aType) {
33 case PSE_LT_GPU: return @"PluginGPU";
34 case PSE_LT_CDR: return @"PluginCDR";
35 case PSE_LT_SPU: return @"PluginSPU";
36 case PSE_LT_PAD: return @"PluginPAD";
37 case PSE_LT_NET: return @"PluginNET";
38 }
39
40 return @"";
41}
42
43+ (char **)getConfigEntriesForType:(int)aType
44{
45 static char *gpu[2] = {(char *)&Config.Gpu, NULL};
46 static char *cdr[2] = {(char *)&Config.Cdr, NULL};
47 static char *spu[2] = {(char *)&Config.Spu, NULL};
48 static char *pad[3] = {(char *)&Config.Pad1, (char *)&Config.Pad2, NULL};
49 static char *net[2] = {(char *)&Config.Net, NULL};
50
51 switch (aType) {
52 case PSE_LT_GPU: return (char **)gpu;
53 case PSE_LT_CDR: return (char **)cdr;
54 case PSE_LT_SPU: return (char **)spu;
55 case PSE_LT_PAD: return (char **)pad;
56 case PSE_LT_NET: return (char **)net;
57 }
58
59 return nil;
60}
61
62- (id)initWithPath:(NSString *)aPath
63{
64 if (!(self = [super init])) {
65 return nil;
66 }
67
68 PSEgetLibType PSE_getLibType = NULL;
69 PSEgetLibVersion PSE_getLibVersion = NULL;
70 PSEgetLibName PSE_getLibName = NULL;
71
72 pluginRef = nil;
73 name = nil;
74 path = [aPath retain];
75 NSString *fullPath = [[NSString stringWithCString:Config.PluginsDir] stringByAppendingPathComponent:path];
76
77 pluginRef = SysLoadLibrary([fullPath fileSystemRepresentation]);
78 if (pluginRef == nil) {
79 [self release];
80 return nil;
81 }
82
83 // TODO: add support for plugins with multiple functionalities???
84 PSE_getLibType = (PSEgetLibType) SysLoadSym(pluginRef, "PSEgetLibType");
85 if (SysLibError() != nil) {
86 if (([path rangeOfString: @"gpu" options:NSCaseInsensitiveSearch]).length != 0)
87 type = PSE_LT_GPU;
88 else if (([path rangeOfString: @"cdr" options:NSCaseInsensitiveSearch]).length != 0)
89 type = PSE_LT_CDR;
90 else if (([path rangeOfString: @"spu" options:NSCaseInsensitiveSearch]).length != 0)
91 type = PSE_LT_SPU;
92 else if (([path rangeOfString: @"pad" options:NSCaseInsensitiveSearch]).length != 0)
93 type = PSE_LT_PAD;
94 else {
95 [self release];
96 return nil;
97 }
98 } else {
99 type = (int)PSE_getLibType();
100 if (type != PSE_LT_GPU && type != PSE_LT_CDR && type != PSE_LT_SPU && type != PSE_LT_PAD) {
101 [self release];
102 return nil;
103 }
104 }
105
106 PSE_getLibName = (PSEgetLibName) SysLoadSym(pluginRef, "PSEgetLibName");
107 if (SysLibError() == nil) {
108 name = [[NSString alloc] initWithCString:PSE_getLibName()];
109 }
110
111 PSE_getLibVersion = (PSEgetLibVersion) SysLoadSym(pluginRef, "PSEgetLibVersion");
112 if (SysLibError() == nil) {
113 version = PSE_getLibVersion();
114 }
115 else {
116 version = -1;
117 }
118
119 // save the current modification date
120 NSDictionary *fattrs = [[NSFileManager defaultManager] fileAttributesAtPath:fullPath traverseLink:YES];
121 modDate = [[fattrs fileModificationDate] retain];
122
123 active = 0;
124
125 return self;
126}
127
128- (void)dealloc
129{
130 int i;
131
132 // shutdown if we had previously been inited
133 for (i=0; i<32; i++) {
134 if (active & (1 << i)) {
135 [self shutdownAs:(1 << i)];
136 }
137 }
138
139 if (pluginRef) SysCloseLibrary(pluginRef);
140
141 [path release];
142 [name release];
143
144 [super dealloc];
145}
146
147- (void)runCommand:(id)arg
148{
149 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
150 NSString *funcName = [arg objectAtIndex:0];
151 long (*func)(void);
152
153 func = SysLoadSym(pluginRef, [funcName lossyCString]);
154 if (SysLibError() == nil) {
155 func();
156 } else {
157 NSBeep();
158 }
159
160 [arg release];
161 [pool release];
162 return;
163}
164
165- (long)initAs:(int)aType
166{
167 char symbol[255];
168 long (*init)(void);
169 long (*initArg)(long arg);
170 int res = PSE_ERR_FATAL;
171
172 if ((active & aType) == aType) {
173 return 0;
174 }
175
176 sprintf(symbol, "%sinit", [[PcsxPlugin getPrefixForType:aType] lossyCString]);
177 init = initArg = SysLoadSym(pluginRef, symbol);
178 if (SysLibError() == nil) {
179 if (aType != PSE_LT_PAD)
180 res = init();
181 else
182 res = initArg(1|2);
183 }
184
185 if (0 == res) {
186 active |= aType;
187 } else {
188 NSRunCriticalAlertPanel(NSLocalizedString(@"Plugin Initialization Failed!", nil),
189 [NSString stringWithFormat:NSLocalizedString(@"Pcsx failed to initialize the selected %s plugin (error=%i).\nThe plugin might not work with your system.", nil), [PcsxPlugin getPrefixForType:aType], res],
190 nil, nil, nil);
191 }
192
193 return res;
194}
195
196- (long)shutdownAs:(int)aType
197{
198 char symbol[255];
199 long (*shutdown)(void);
200
201 sprintf(symbol, "%sshutdown", [[PcsxPlugin getPrefixForType:aType] lossyCString]);
202 shutdown = SysLoadSym(pluginRef, symbol);
203 if (SysLibError() == nil) {
204 active &= ~aType;
205 return shutdown();
206 }
207
208 return PSE_ERR_FATAL;
209}
210
211- (BOOL)hasAboutAs:(int)aType
212{
213 char symbol[255];
214
215 sprintf(symbol, "%sabout", [[PcsxPlugin getPrefixForType:aType] lossyCString]);
216 SysLoadSym(pluginRef, symbol);
217
218 return (SysLibError() == nil);
219}
220
221- (BOOL)hasConfigureAs:(int)aType
222{
223 char symbol[255];
224
225 sprintf(symbol, "%sconfigure", [[PcsxPlugin getPrefixForType:aType] lossyCString]);
226 SysLoadSym(pluginRef, symbol);
227
228 return (SysLibError() == nil);
229}
230
231- (void)aboutAs:(int)aType
232{
233 NSArray *arg;
234 char symbol[255];
235
236 sprintf(symbol, "%sabout", [[PcsxPlugin getPrefixForType:aType] lossyCString]);
237 arg = [[NSArray alloc] initWithObjects:[NSString stringWithCString:symbol],
238 [NSNumber numberWithInt:0], nil];
239
240 // detach a new thread
241 [NSThread detachNewThreadSelector:@selector(runCommand:) toTarget:self
242 withObject:arg];
243}
244
245- (void)configureAs:(int)aType
246{
247 NSArray *arg;
248 char symbol[255];
249
250 sprintf(symbol, "%sconfigure", [[PcsxPlugin getPrefixForType:aType] lossyCString]);
251 arg = [[NSArray alloc] initWithObjects:[NSString stringWithCString:symbol],
252 [NSNumber numberWithInt:1], nil];
253
254 // detach a new thread
255 [NSThread detachNewThreadSelector:@selector(runCommand:) toTarget:self
256 withObject:arg];
257}
258
259- (NSString *)getDisplayVersion
260{
261 if (version == -1)
262 return @"";
263
264 return [NSString stringWithFormat:@"v%ld.%ld.%ld", version>>16,(version>>8)&0xff,version&0xff];
265}
266
267- (int)getType
268{
269 return type;
270}
271
272- (NSString *)path
273{
274 return path;
275}
276
277- (unsigned)hash
278{
279 return [path hash];
280}
281
282- (NSString *)description
283{
284 if (name == nil)
285 return [path lastPathComponent];
286
287 return [NSString stringWithFormat:@"%@ %@ [%@]", name, [self getDisplayVersion], [path lastPathComponent]];
288}
289
290// the plugin will check if it's still valid and return the status
291- (BOOL)verifyOK
292{
293 // check that the file is still there with the same modification date
294 NSFileManager *dfm = [NSFileManager defaultManager];
295 NSString *fullPath = [[NSString stringWithCString:Config.PluginsDir] stringByAppendingPathComponent:path];
296 if (![dfm fileExistsAtPath:fullPath])
297 return NO;
298
299 NSDictionary *fattrs = [dfm fileAttributesAtPath:fullPath traverseLink:YES];
300 return [[fattrs fileModificationDate] isEqualToDate:modDate];
301}
302
303@end