pcsxr-1.9.92
[pcsx_rearmed.git] / macosx / PcsxPlugin.m
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