/[pcsx2_0.9.7]/trunk/pcsx2/PluginManager.cpp
ViewVC logotype

Contents of /trunk/pcsx2/PluginManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (9 years, 5 months ago) by william
File size: 44329 byte(s)
committing r3113 initial commit again...
1 /* PCSX2 - PS2 Emulator for PCs
2 * Copyright (C) 2002-2010 PCSX2 Dev Team
3 *
4 * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU Lesser General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with PCSX2.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 #include "PrecompiledHeader.h"
17 #include "IopCommon.h"
18
19 #include <wx/dir.h>
20 #include <wx/file.h>
21
22 #include "GS.h"
23 #include "HostGui.h"
24 #include "CDVD/CDVDisoReader.h"
25
26 #include "Utilities/ScopedPtr.h"
27
28 #if _MSC_VER
29 # include "svnrev.h"
30 #endif
31
32 SysPluginBindings SysPlugins;
33
34 bool SysPluginBindings::McdIsPresent( uint port, uint slot )
35 {
36 return !!Mcd->McdIsPresent( (PS2E_THISPTR) Mcd, port, slot );
37 }
38
39 void SysPluginBindings::McdGetSizeInfo( uint port, uint slot, PS2E_McdSizeInfo& outways )
40 {
41 if( Mcd->McdGetSizeInfo )
42 Mcd->McdGetSizeInfo( (PS2E_THISPTR) Mcd, port, slot, &outways );
43 }
44
45 void SysPluginBindings::McdRead( uint port, uint slot, u8 *dest, u32 adr, int size )
46 {
47 Mcd->McdRead( (PS2E_THISPTR) Mcd, port, slot, dest, adr, size );
48 }
49
50 void SysPluginBindings::McdSave( uint port, uint slot, const u8 *src, u32 adr, int size )
51 {
52 Mcd->McdSave( (PS2E_THISPTR) Mcd, port, slot, src, adr, size );
53 }
54
55 void SysPluginBindings::McdEraseBlock( uint port, uint slot, u32 adr )
56 {
57 Mcd->McdEraseBlock( (PS2E_THISPTR) Mcd, port, slot, adr );
58 }
59
60 u64 SysPluginBindings::McdGetCRC( uint port, uint slot )
61 {
62 return Mcd->McdGetCRC( (PS2E_THISPTR) Mcd, port, slot );
63 }
64
65
66 // ----------------------------------------------------------------------------
67 // Yay, order of this array shouldn't be important. :)
68 //
69 const PluginInfo tbl_PluginInfo[] =
70 {
71 { "GS", PluginId_GS, PS2E_LT_GS, PS2E_GS_VERSION },
72 { "PAD", PluginId_PAD, PS2E_LT_PAD, PS2E_PAD_VERSION },
73 { "SPU2", PluginId_SPU2, PS2E_LT_SPU2, PS2E_SPU2_VERSION },
74 { "CDVD", PluginId_CDVD, PS2E_LT_CDVD, PS2E_CDVD_VERSION },
75 { "USB", PluginId_USB, PS2E_LT_USB, PS2E_USB_VERSION },
76 { "FW", PluginId_FW, PS2E_LT_FW, PS2E_FW_VERSION },
77 { "DEV9", PluginId_DEV9, PS2E_LT_DEV9, PS2E_DEV9_VERSION },
78
79 { NULL },
80
81 // See PluginEnums_t for details on the MemoryCard plugin hack.
82 { "Mcd", PluginId_Mcd, 0, 0 },
83 };
84
85 typedef void CALLBACK VoidMethod();
86 typedef void CALLBACK vMeth(); // shorthand for VoidMethod
87
88 // ----------------------------------------------------------------------------
89 struct LegacyApi_CommonMethod
90 {
91 const char* MethodName;
92
93 // fallback is used if the method is null. If the method is null and fallback is null
94 // also, the plugin is considered incomplete or invalid, and an error is generated.
95 VoidMethod* Fallback;
96
97 // returns the method name as a wxString, converted from UTF8.
98 wxString GetMethodName( PluginsEnum_t pid ) const
99 {
100 return tbl_PluginInfo[pid].GetShortname() + fromUTF8( MethodName );
101 }
102 };
103
104 // ----------------------------------------------------------------------------
105 struct LegacyApi_ReqMethod
106 {
107 const char* MethodName;
108 VoidMethod** Dest; // Target function where the binding is saved.
109
110 // fallback is used if the method is null. If the method is null and fallback is null
111 // also, the plugin is considered incomplete or invalid, and an error is generated.
112 VoidMethod* Fallback;
113
114 // returns the method name as a wxString, converted from UTF8.
115 wxString GetMethodName( ) const
116 {
117 return fromUTF8( MethodName );
118 }
119 };
120
121 // ----------------------------------------------------------------------------
122 struct LegacyApi_OptMethod
123 {
124 const char* MethodName;
125 VoidMethod** Dest; // Target function where the binding is saved.
126
127 // returns the method name as a wxString, converted from UTF8.
128 wxString GetMethodName() const { return fromUTF8( MethodName ); }
129 };
130
131
132 static s32 CALLBACK fallback_freeze(int mode, freezeData *data)
133 {
134 if( mode == FREEZE_SIZE ) data->size = 0;
135 return 0;
136 }
137
138 static void CALLBACK fallback_keyEvent(keyEvent *ev) {}
139 static void CALLBACK fallback_setSettingsDir(const char* dir) {}
140 static void CALLBACK fallback_SetLogFolder(const char* dir) {}
141 static void CALLBACK fallback_configure() {}
142 static void CALLBACK fallback_about() {}
143 static s32 CALLBACK fallback_test() { return 0; }
144
145 _GSvsync GSvsync;
146 _GSopen GSopen;
147 _GSopen2 GSopen2;
148 _GSgifTransfer1 GSgifTransfer1;
149 _GSgifTransfer2 GSgifTransfer2;
150 _GSgifTransfer3 GSgifTransfer3;
151 _GSgifSoftReset GSgifSoftReset;
152 _GSreadFIFO GSreadFIFO;
153 _GSreadFIFO2 GSreadFIFO2;
154 _GSchangeSaveState GSchangeSaveState;
155 _GSgetTitleInfo GSgetTitleInfo;
156 _GSmakeSnapshot GSmakeSnapshot;
157 _GSmakeSnapshot2 GSmakeSnapshot2;
158 _GSirqCallback GSirqCallback;
159 _GSprintf GSprintf;
160 _GSsetBaseMem GSsetBaseMem;
161 _GSsetGameCRC GSsetGameCRC;
162 _GSsetFrameSkip GSsetFrameSkip;
163 _GSsetVsync GSsetVsync;
164 _GSsetExclusive GSsetExclusive;
165 _GSsetupRecording GSsetupRecording;
166 _GSreset GSreset;
167 _GSwriteCSR GSwriteCSR;
168
169 static void CALLBACK GS_makeSnapshot(const char *path) {}
170 static void CALLBACK GS_setGameCRC(u32 crc, int gameopts) {}
171 static void CALLBACK GS_irqCallback(void (*callback)()) {}
172 static void CALLBACK GS_setFrameSkip(int frameskip) {}
173 static void CALLBACK GS_setVsync(int enabled) {}
174 static void CALLBACK GS_setExclusive(int isExcl) {}
175 static void CALLBACK GS_changeSaveState( int, const char* filename ) {}
176 static void CALLBACK GS_printf(int timeout, char *fmt, ...)
177 {
178 va_list list;
179 char msg[512];
180
181 va_start(list, fmt);
182 vsprintf(msg, fmt, list);
183 va_end(list);
184
185 Console.WriteLn(msg);
186 }
187
188 void CALLBACK GS_getTitleInfo( char dest[128] )
189 {
190 dest[0] = 'G';
191 dest[1] = 'S';
192 dest[2] = 0;
193 }
194
195
196 // PAD
197 _PADinit PADinit;
198 _PADopen PADopen;
199 _PADstartPoll PADstartPoll;
200 _PADpoll PADpoll;
201 _PADquery PADquery;
202 _PADupdate PADupdate;
203 _PADkeyEvent PADkeyEvent;
204 _PADsetSlot PADsetSlot;
205 _PADqueryMtap PADqueryMtap;
206
207 static void PAD_update( u32 padslot ) { }
208
209 // SPU2
210 _SPU2open SPU2open;
211 _SPU2write SPU2write;
212 _SPU2read SPU2read;
213 #ifdef ENABLE_NEW_IOPDMA_SPU2
214 _SPU2dmaRead SPU2dmaRead;
215 _SPU2dmaWrite SPU2dmaWrite;
216 _SPU2dmaInterrupt SPU2dmaInterrupt;
217 #else
218 _SPU2readDMA4Mem SPU2readDMA4Mem;
219 _SPU2writeDMA4Mem SPU2writeDMA4Mem;
220 _SPU2interruptDMA4 SPU2interruptDMA4;
221 _SPU2readDMA7Mem SPU2readDMA7Mem;
222 _SPU2writeDMA7Mem SPU2writeDMA7Mem;
223 _SPU2setDMABaseAddr SPU2setDMABaseAddr;
224 _SPU2interruptDMA7 SPU2interruptDMA7;
225 _SPU2ReadMemAddr SPU2ReadMemAddr;
226 _SPU2WriteMemAddr SPU2WriteMemAddr;
227 #endif
228 _SPU2setupRecording SPU2setupRecording;
229 _SPU2irqCallback SPU2irqCallback;
230
231 _SPU2setClockPtr SPU2setClockPtr;
232 _SPU2async SPU2async;
233
234
235 // DEV9
236 _DEV9open DEV9open;
237 _DEV9read8 DEV9read8;
238 _DEV9read16 DEV9read16;
239 _DEV9read32 DEV9read32;
240 _DEV9write8 DEV9write8;
241 _DEV9write16 DEV9write16;
242 _DEV9write32 DEV9write32;
243 #ifdef ENABLE_NEW_IOPDMA_DEV9
244 _DEV9dmaRead DEV9dmaRead;
245 _DEV9dmaWrite DEV9dmaWrite;
246 _DEV9dmaInterrupt DEV9dmaInterrupt;
247 #else
248 _DEV9readDMA8Mem DEV9readDMA8Mem;
249 _DEV9writeDMA8Mem DEV9writeDMA8Mem;
250 #endif
251 _DEV9irqCallback DEV9irqCallback;
252 _DEV9irqHandler DEV9irqHandler;
253
254 // USB
255 _USBopen USBopen;
256 _USBread8 USBread8;
257 _USBread16 USBread16;
258 _USBread32 USBread32;
259 _USBwrite8 USBwrite8;
260 _USBwrite16 USBwrite16;
261 _USBwrite32 USBwrite32;
262 _USBasync USBasync;
263
264 _USBirqCallback USBirqCallback;
265 _USBirqHandler USBirqHandler;
266 _USBsetRAM USBsetRAM;
267
268 // FW
269 _FWopen FWopen;
270 _FWread32 FWread32;
271 _FWwrite32 FWwrite32;
272 _FWirqCallback FWirqCallback;
273
274 DEV9handler dev9Handler;
275 USBhandler usbHandler;
276 uptr pDsp;
277
278 static s32 CALLBACK _hack_PADinit()
279 {
280 return PADinit( 3 );
281 }
282
283 // ----------------------------------------------------------------------------
284 // Important: Contents of this array must match the order of the contents of the
285 // LegacyPluginAPI_Common structure defined in Plugins.h.
286 //
287 static const LegacyApi_CommonMethod s_MethMessCommon[] =
288 {
289 { "init", NULL },
290 { "close", NULL },
291 { "shutdown", NULL },
292
293 { "keyEvent", (vMeth*)fallback_keyEvent },
294 { "setSettingsDir", (vMeth*)fallback_setSettingsDir },
295 { "SetLogFolder", (vMeth*)fallback_SetLogFolder },
296
297 { "freeze", (vMeth*)fallback_freeze },
298 { "test", (vMeth*)fallback_test },
299 { "configure", fallback_configure },
300 { "about", fallback_about },
301
302 { NULL }
303
304 };
305
306 // ----------------------------------------------------------------------------
307 // GS Mess!
308 // ----------------------------------------------------------------------------
309 static const LegacyApi_ReqMethod s_MethMessReq_GS[] =
310 {
311 { "GSopen", (vMeth**)&GSopen, NULL },
312 { "GSvsync", (vMeth**)&GSvsync, NULL },
313 { "GSgifTransfer1", (vMeth**)&GSgifTransfer1, NULL },
314 { "GSgifTransfer2", (vMeth**)&GSgifTransfer2, NULL },
315 { "GSgifTransfer3", (vMeth**)&GSgifTransfer3, NULL },
316 { "GSreadFIFO2", (vMeth**)&GSreadFIFO2, NULL },
317
318 { "GSmakeSnapshot", (vMeth**)&GSmakeSnapshot, (vMeth*)GS_makeSnapshot },
319 { "GSirqCallback", (vMeth**)&GSirqCallback, (vMeth*)GS_irqCallback },
320 { "GSprintf", (vMeth**)&GSprintf, (vMeth*)GS_printf },
321 { "GSsetBaseMem", (vMeth**)&GSsetBaseMem, NULL },
322 { "GSwriteCSR", (vMeth**)&GSwriteCSR, NULL },
323 { "GSsetGameCRC", (vMeth**)&GSsetGameCRC, (vMeth*)GS_setGameCRC },
324
325 { "GSsetFrameSkip", (vMeth**)&GSsetFrameSkip, (vMeth*)GS_setFrameSkip },
326 { "GSsetVsync", (vMeth**)&GSsetVsync, (vMeth*)GS_setVsync },
327 { "GSsetExclusive", (vMeth**)&GSsetExclusive, (vMeth*)GS_setExclusive },
328 { "GSchangeSaveState",(vMeth**)&GSchangeSaveState,(vMeth*)GS_changeSaveState },
329 { "GSgetTitleInfo", (vMeth**)&GSgetTitleInfo, (vMeth*)GS_getTitleInfo },
330 { NULL }
331 };
332
333 static const LegacyApi_OptMethod s_MethMessOpt_GS[] =
334 {
335 { "GSopen2", (vMeth**)&GSopen2 },
336 { "GSreset", (vMeth**)&GSreset },
337 { "GSsetupRecording", (vMeth**)&GSsetupRecording },
338 { "GSmakeSnapshot2", (vMeth**)&GSmakeSnapshot2 },
339 { "GSgifSoftReset", (vMeth**)&GSgifSoftReset },
340 { "GSreadFIFO", (vMeth**)&GSreadFIFO },
341 { NULL }
342 };
343
344 // ----------------------------------------------------------------------------
345 // PAD Mess!
346 // ----------------------------------------------------------------------------
347 static s32 CALLBACK PAD_queryMtap( u8 slot ) { return 0; }
348 static s32 CALLBACK PAD_setSlot(u8 port, u8 slot) { return 0; }
349
350 static const LegacyApi_ReqMethod s_MethMessReq_PAD[] =
351 {
352 { "PADopen", (vMeth**)&PADopen, NULL },
353 { "PADstartPoll", (vMeth**)&PADstartPoll, NULL },
354 { "PADpoll", (vMeth**)&PADpoll, NULL },
355 { "PADquery", (vMeth**)&PADquery, NULL },
356 { "PADkeyEvent", (vMeth**)&PADkeyEvent, NULL },
357
358 // fixme - Following functions are new as of some revison post-0.9.6, and
359 // are for multitap support only. They should either be optional or offer
360 // NOP fallbacks, to allow older plugins to retain functionality.
361 { "PADsetSlot", (vMeth**)&PADsetSlot, (vMeth*)PAD_setSlot },
362 { "PADqueryMtap", (vMeth**)&PADqueryMtap, (vMeth*)PAD_queryMtap },
363 { NULL },
364 };
365
366 static const LegacyApi_OptMethod s_MethMessOpt_PAD[] =
367 {
368 { "PADupdate", (vMeth**)&PADupdate },
369 { NULL },
370 };
371
372 // ----------------------------------------------------------------------------
373 // CDVD Mess!
374 // ----------------------------------------------------------------------------
375 void CALLBACK CDVD_newDiskCB(void (*callback)()) {}
376
377 extern int lastReadSize, lastLSN;
378 static s32 CALLBACK CDVD_getBuffer2(u8* buffer)
379 {
380 // TEMP: until I fix all the plugins to use this function style
381 u8* pb = CDVD->getBuffer();
382 if(pb == NULL) return -2;
383
384 memcpy_fast( buffer, pb, lastReadSize );
385 return 0;
386 }
387
388 static s32 CALLBACK CDVD_readSector(u8* buffer, u32 lsn, int mode)
389 {
390 if(CDVD->readTrack(lsn,mode) < 0)
391 return -1;
392
393 // TEMP: until all the plugins use the new CDVDgetBuffer style
394 switch (mode)
395 {
396 case CDVD_MODE_2352:
397 lastReadSize = 2352;
398 break;
399 case CDVD_MODE_2340:
400 lastReadSize = 2340;
401 break;
402 case CDVD_MODE_2328:
403 lastReadSize = 2328;
404 break;
405 case CDVD_MODE_2048:
406 lastReadSize = 2048;
407 break;
408 }
409
410 lastLSN = lsn;
411 return CDVD->getBuffer2(buffer);
412 }
413
414 static s32 CALLBACK CDVD_getDualInfo(s32* dualType, u32* layer1Start)
415 {
416 u8 toc[2064];
417
418 // if error getting toc, settle for single layer disc ;)
419 if(CDVD->getTOC(toc))
420 return 0;
421
422 if(toc[14] & 0x60)
423 {
424 if(toc[14] & 0x10)
425 {
426 // otp dvd
427 *dualType = 2;
428 *layer1Start = (toc[25]<<16) + (toc[26]<<8) + (toc[27]) - 0x30000 + 1;
429 }
430 else
431 {
432 // ptp dvd
433 *dualType = 1;
434 *layer1Start = (toc[21]<<16) + (toc[22]<<8) + (toc[23]) - 0x30000 + 1;
435 }
436 }
437 else
438 {
439 // single layer dvd
440 *dualType = 0;
441 *layer1Start = (toc[21]<<16) + (toc[22]<<8) + (toc[23]) - 0x30000 + 1;
442 }
443
444 return 1;
445 }
446
447 CDVD_API CDVDapi_Plugin =
448 {
449 // All of these are filled by the plugin manager
450 NULL
451 };
452
453 CDVD_API* CDVD = NULL;
454
455 static const LegacyApi_ReqMethod s_MethMessReq_CDVD[] =
456 {
457 { "CDVDopen", (vMeth**)&CDVDapi_Plugin.open, NULL },
458 { "CDVDclose", (vMeth**)&CDVDapi_Plugin.close, NULL },
459 { "CDVDreadTrack", (vMeth**)&CDVDapi_Plugin.readTrack, NULL },
460 { "CDVDgetBuffer", (vMeth**)&CDVDapi_Plugin.getBuffer, NULL },
461 { "CDVDreadSubQ", (vMeth**)&CDVDapi_Plugin.readSubQ, NULL },
462 { "CDVDgetTN", (vMeth**)&CDVDapi_Plugin.getTN, NULL },
463 { "CDVDgetTD", (vMeth**)&CDVDapi_Plugin.getTD, NULL },
464 { "CDVDgetTOC", (vMeth**)&CDVDapi_Plugin.getTOC, NULL },
465 { "CDVDgetDiskType", (vMeth**)&CDVDapi_Plugin.getDiskType, NULL },
466 { "CDVDgetTrayStatus",(vMeth**)&CDVDapi_Plugin.getTrayStatus, NULL },
467 { "CDVDctrlTrayOpen", (vMeth**)&CDVDapi_Plugin.ctrlTrayOpen, NULL },
468 { "CDVDctrlTrayClose",(vMeth**)&CDVDapi_Plugin.ctrlTrayClose, NULL },
469 { "CDVDnewDiskCB", (vMeth**)&CDVDapi_Plugin.newDiskCB, (vMeth*)CDVD_newDiskCB },
470
471 { "CDVDreadSector", (vMeth**)&CDVDapi_Plugin.readSector, (vMeth*)CDVD_readSector },
472 { "CDVDgetBuffer2", (vMeth**)&CDVDapi_Plugin.getBuffer2, (vMeth*)CDVD_getBuffer2 },
473 { "CDVDgetDualInfo", (vMeth**)&CDVDapi_Plugin.getDualInfo, (vMeth*)CDVD_getDualInfo },
474
475 { NULL }
476 };
477
478 static const LegacyApi_OptMethod s_MethMessOpt_CDVD[] =
479 {
480 { NULL }
481 };
482
483 // ----------------------------------------------------------------------------
484 // SPU2 Mess!
485 // ----------------------------------------------------------------------------
486 static const LegacyApi_ReqMethod s_MethMessReq_SPU2[] =
487 {
488 { "SPU2open", (vMeth**)&SPU2open, NULL },
489 { "SPU2write", (vMeth**)&SPU2write, NULL },
490 { "SPU2read", (vMeth**)&SPU2read, NULL },
491 #ifdef ENABLE_NEW_IOPDMA_SPU2
492 { "SPU2dmaRead", (vMeth**)&SPU2dmaRead, NULL },
493 { "SPU2dmaWrite", (vMeth**)&SPU2dmaWrite, NULL },
494 { "SPU2dmaInterrupt", (vMeth**)&SPU2dmaInterrupt, NULL },
495 #else
496 { "SPU2readDMA4Mem", (vMeth**)&SPU2readDMA4Mem, NULL },
497 { "SPU2readDMA7Mem", (vMeth**)&SPU2readDMA7Mem, NULL },
498 { "SPU2writeDMA4Mem", (vMeth**)&SPU2writeDMA4Mem, NULL },
499 { "SPU2writeDMA7Mem", (vMeth**)&SPU2writeDMA7Mem, NULL },
500 { "SPU2interruptDMA4", (vMeth**)&SPU2interruptDMA4,NULL },
501 { "SPU2interruptDMA7", (vMeth**)&SPU2interruptDMA7,NULL },
502 { "SPU2ReadMemAddr", (vMeth**)&SPU2ReadMemAddr, NULL },
503 #endif
504 { "SPU2irqCallback", (vMeth**)&SPU2irqCallback, NULL },
505
506 { NULL }
507 };
508
509 static const LegacyApi_OptMethod s_MethMessOpt_SPU2[] =
510 {
511 { "SPU2setClockPtr", (vMeth**)&SPU2setClockPtr },
512 { "SPU2async", (vMeth**)&SPU2async },
513 #ifndef ENABLE_NEW_IOPDMA_SPU2
514 { "SPU2WriteMemAddr", (vMeth**)&SPU2WriteMemAddr },
515 { "SPU2setDMABaseAddr", (vMeth**)&SPU2setDMABaseAddr},
516 #endif
517 { "SPU2setupRecording", (vMeth**)&SPU2setupRecording},
518
519 { NULL }
520 };
521
522 // ----------------------------------------------------------------------------
523 // DEV9 Mess!
524 // ----------------------------------------------------------------------------
525 static const LegacyApi_ReqMethod s_MethMessReq_DEV9[] =
526 {
527 { "DEV9open", (vMeth**)&DEV9open, NULL },
528 { "DEV9read8", (vMeth**)&DEV9read8, NULL },
529 { "DEV9read16", (vMeth**)&DEV9read16, NULL },
530 { "DEV9read32", (vMeth**)&DEV9read32, NULL },
531 { "DEV9write8", (vMeth**)&DEV9write8, NULL },
532 { "DEV9write16", (vMeth**)&DEV9write16, NULL },
533 { "DEV9write32", (vMeth**)&DEV9write32, NULL },
534 #ifdef ENABLE_NEW_IOPDMA_DEV9
535 { "DEV9dmaRead", (vMeth**)&DEV9dmaRead, NULL },
536 { "DEV9dmaWrite", (vMeth**)&DEV9dmaWrite, NULL },
537 { "DEV9dmaInterrupt", (vMeth**)&DEV9dmaInterrupt, NULL },
538 #else
539 { "DEV9readDMA8Mem", (vMeth**)&DEV9readDMA8Mem, NULL },
540 { "DEV9writeDMA8Mem", (vMeth**)&DEV9writeDMA8Mem, NULL },
541 #endif
542 { "DEV9irqCallback", (vMeth**)&DEV9irqCallback, NULL },
543 { "DEV9irqHandler", (vMeth**)&DEV9irqHandler, NULL },
544
545 { NULL }
546 };
547
548 static const LegacyApi_OptMethod s_MethMessOpt_DEV9[] =
549 {
550 { NULL }
551 };
552
553 // ----------------------------------------------------------------------------
554 // USB Mess!
555 // ----------------------------------------------------------------------------
556 static const LegacyApi_ReqMethod s_MethMessReq_USB[] =
557 {
558 { "USBopen", (vMeth**)&USBopen, NULL },
559 { "USBread8", (vMeth**)&USBread8, NULL },
560 { "USBread16", (vMeth**)&USBread16, NULL },
561 { "USBread32", (vMeth**)&USBread32, NULL },
562 { "USBwrite8", (vMeth**)&USBwrite8, NULL },
563 { "USBwrite16", (vMeth**)&USBwrite16, NULL },
564 { "USBwrite32", (vMeth**)&USBwrite32, NULL },
565 { "USBirqCallback", (vMeth**)&USBirqCallback, NULL },
566 { "USBirqHandler", (vMeth**)&USBirqHandler, NULL },
567 { NULL }
568 };
569
570 static const LegacyApi_OptMethod s_MethMessOpt_USB[] =
571 {
572 { "USBasync", (vMeth**)&USBasync },
573 { NULL }
574 };
575
576 // ----------------------------------------------------------------------------
577 // FW Mess!
578 // ----------------------------------------------------------------------------
579 static const LegacyApi_ReqMethod s_MethMessReq_FW[] =
580 {
581 { "FWopen", (vMeth**)&FWopen, NULL },
582 { "FWread32", (vMeth**)&FWread32, NULL },
583 { "FWwrite32", (vMeth**)&FWwrite32, NULL },
584 { "FWirqCallback", (vMeth**)&FWirqCallback, NULL },
585 { NULL }
586 };
587
588 static const LegacyApi_OptMethod s_MethMessOpt_FW[] =
589 {
590 { NULL }
591 };
592
593 static const LegacyApi_ReqMethod* const s_MethMessReq[] =
594 {
595 s_MethMessReq_GS,
596 s_MethMessReq_PAD,
597 s_MethMessReq_SPU2,
598 s_MethMessReq_CDVD,
599 s_MethMessReq_USB,
600 s_MethMessReq_FW,
601 s_MethMessReq_DEV9
602 };
603
604 static const LegacyApi_OptMethod* const s_MethMessOpt[] =
605 {
606 s_MethMessOpt_GS,
607 s_MethMessOpt_PAD,
608 s_MethMessOpt_SPU2,
609 s_MethMessOpt_CDVD,
610 s_MethMessOpt_USB,
611 s_MethMessOpt_FW,
612 s_MethMessOpt_DEV9
613 };
614
615 PluginManager *g_plugins = NULL;
616
617 // ---------------------------------------------------------------------------------
618 // Plugin-related Exception Implementations
619 // ---------------------------------------------------------------------------------
620
621 Exception::PluginLoadError::PluginLoadError( PluginsEnum_t pid, const wxString& objname, const char* eng )
622 {
623 BaseException::InitBaseEx( eng );
624 StreamName = objname;
625 PluginId = pid;
626 }
627
628 Exception::PluginLoadError::PluginLoadError( PluginsEnum_t pid, const wxString& objname,
629 const wxString& eng_msg, const wxString& xlt_msg )
630 {
631 BaseException::InitBaseEx( eng_msg, xlt_msg );
632 StreamName = objname;
633 PluginId = pid;
634 }
635
636 wxString Exception::PluginLoadError::FormatDiagnosticMessage() const
637 {
638 return wxsFormat( m_message_diag, tbl_PluginInfo[PluginId].GetShortname().c_str() ) +
639 L"\n\n" + StreamName;
640 }
641
642 wxString Exception::PluginLoadError::FormatDisplayMessage() const
643 {
644 return wxsFormat( m_message_user, tbl_PluginInfo[PluginId].GetShortname().c_str() ) +
645 L"\n\n" + StreamName;
646 }
647
648 wxString Exception::PluginError::FormatDiagnosticMessage() const
649 {
650 return wxsFormat( m_message_diag, tbl_PluginInfo[PluginId].GetShortname().c_str() );
651 }
652
653 wxString Exception::PluginError::FormatDisplayMessage() const
654 {
655 return wxsFormat( m_message_user, tbl_PluginInfo[PluginId].GetShortname().c_str() );
656 }
657
658 wxString Exception::FreezePluginFailure::FormatDiagnosticMessage() const
659 {
660 return wxsFormat(
661 L"%s plugin returned an error while saving the state.\n\n",
662 tbl_PluginInfo[PluginId].shortname
663 ) + m_stacktrace;
664 }
665
666 wxString Exception::FreezePluginFailure::FormatDisplayMessage() const
667 {
668 // [TODO]
669 return m_message_user;
670 }
671
672 wxString Exception::ThawPluginFailure::FormatDiagnosticMessage() const
673 {
674 return wxsFormat(
675 L"%s plugin returned an error while loading the state.\n\n",
676 tbl_PluginInfo[PluginId].shortname
677 ) + m_stacktrace;
678 }
679
680 wxString Exception::ThawPluginFailure::FormatDisplayMessage() const
681 {
682 // [TODO]
683 return m_message_user;
684 }
685
686 // --------------------------------------------------------------------------------------
687 // PCSX2 Callbacks passed to Plugins
688 // --------------------------------------------------------------------------------------
689 // This is currently unimplemented, and should be provided by the AppHost (gui) rather
690 // than the EmuCore. But as a quickhackfix until the new plugin API is fleshed out, this
691 // will suit our needs nicely. :)
692
693 static BOOL PS2E_CALLBACK pcsx2_GetInt( const char* name, int* dest )
694 {
695 return FALSE; // not implemented...
696 }
697
698 static BOOL PS2E_CALLBACK pcsx2_GetBoolean( const char* name, BOOL* result )
699 {
700 return FALSE; // not implemented...
701 }
702
703 static BOOL PS2E_CALLBACK pcsx2_GetString( const char* name, char* dest, int maxlen )
704 {
705 return FALSE; // not implemented...
706 }
707
708 static char* PS2E_CALLBACK pcsx2_GetStringAlloc( const char* name, void* (PS2E_CALLBACK* allocator)(int size) )
709 {
710 return FALSE; // not implemented...
711 }
712
713 static void PS2E_CALLBACK pcsx2_OSD_WriteLn( int icon, const char* msg )
714 {
715 return; // not implemented...
716 }
717
718 // ---------------------------------------------------------------------------------
719 // PluginStatus_t Implementations
720 // ---------------------------------------------------------------------------------
721 PluginManager::PluginStatus_t::PluginStatus_t( PluginsEnum_t _pid, const wxString& srcfile )
722 : Filename( srcfile )
723 {
724 pid = _pid;
725
726 IsInitialized = false;
727 IsOpened = false;
728
729 if( Filename.IsEmpty() )
730 throw Exception::PluginInitError( pid, "Empty plugin filename." );
731
732 if( !wxFile::Exists( Filename ) )
733 throw Exception::PluginLoadError( pid, srcfile,
734 wxLt("The configured %s plugin file was not found")
735 );
736
737 if( !Lib.Load( Filename ) )
738 throw Exception::PluginLoadError( pid, Filename,
739 wxLt("The configured %s plugin file is not a valid dynamic library")
740 );
741
742
743 // Try to enumerate the new v2.0 plugin interface first.
744 // If that fails, fall back on the old style interface.
745
746 //m_libs[i].GetSymbol( L"PS2E_InitAPI" ); // on the TODO list!
747
748
749 // 2.0 API Failed; Enumerate the Old Stuff! -->
750
751 _PS2EgetLibName GetLibName = (_PS2EgetLibName) Lib.GetSymbol( L"PS2EgetLibName" );
752 _PS2EgetLibVersion2 GetLibVersion2 = (_PS2EgetLibVersion2) Lib.GetSymbol( L"PS2EgetLibVersion2" );
753 _PS2EsetEmuVersion SetEmuVersion = (_PS2EsetEmuVersion) Lib.GetSymbol( L"PS2EsetEmuVersion" );
754
755 if( GetLibName == NULL || GetLibVersion2 == NULL )
756 throw Exception::PluginLoadError( pid, Filename,
757 L"\nMethod binding failure on GetLibName or GetLibVersion2.\n",
758 _( "Configured plugin is not a PCSX2 plugin, or is for an older unsupported version of PCSX2." )
759 );
760
761 if( SetEmuVersion != NULL )
762 SetEmuVersion( "PCSX2", (0ul << 24) | (9ul<<16) | (7ul<<8) | 0 );
763
764 Name = fromUTF8( GetLibName() );
765 int version = GetLibVersion2( tbl_PluginInfo[pid].typemask );
766 Version.Printf( L"%d.%d.%d", (version>>8)&0xff, version&0xff, (version>>24)&0xff );
767
768
769 // Bind Required Functions
770 // (generate critical error if binding fails)
771
772 BindCommon( pid );
773 BindRequired( pid );
774 BindOptional( pid );
775
776 // Run Plugin's Functionality Test.
777 // A lot of plugins don't bother to implement this function and return 0 (success)
778 // regardless, but some do so let's go ahead and check it. I mean, we're supposed to. :)
779
780 int testres = CommonBindings.Test();
781 if( testres != 0 )
782 throw Exception::PluginLoadError( pid, Filename,
783 wxsFormat( L"Plugin Test failure, return code: %d", testres ),
784 _( "The plugin reports that your hardware or software/drivers are not supported." )
785 );
786 }
787
788 void PluginManager::PluginStatus_t::BindCommon( PluginsEnum_t pid )
789 {
790 const LegacyApi_CommonMethod* current = s_MethMessCommon;
791 VoidMethod** target = (VoidMethod**)&CommonBindings;
792
793 wxDoNotLogInThisScope please;
794
795 while( current->MethodName != NULL )
796 {
797 *target = (VoidMethod*)Lib.GetSymbol( current->GetMethodName( pid ) );
798
799 if( *target == NULL )
800 *target = current->Fallback;
801
802 if( *target == NULL )
803 {
804 throw Exception::PluginLoadError( pid, Filename,
805 wxsFormat( L"\nMethod binding failure on: %s\n", current->GetMethodName( pid ).c_str() ),
806 _( "Configured plugin is not a PCSX2 plugin, or is for an older unsupported version of PCSX2." )
807 );
808 }
809
810 target++;
811 current++;
812 }
813 }
814
815 void PluginManager::PluginStatus_t::BindRequired( PluginsEnum_t pid )
816 {
817 const LegacyApi_ReqMethod* current = s_MethMessReq[pid];
818 const wxDynamicLibrary& lib = Lib;
819
820 wxDoNotLogInThisScope please;
821
822 while( current->MethodName != NULL )
823 {
824 *(current->Dest) = (VoidMethod*)lib.GetSymbol( current->GetMethodName() );
825
826 if( *(current->Dest) == NULL )
827 *(current->Dest) = current->Fallback;
828
829 if( *(current->Dest) == NULL )
830 {
831 throw Exception::PluginLoadError( pid, Filename,
832 wxsFormat( L"\nMethod binding failure on: %s\n", current->GetMethodName().c_str() ),
833 _( "Configured plugin is not a valid PCSX2 plugin, or is for an older unsupported version of PCSX2." )
834 );
835 }
836
837 current++;
838 }
839 }
840
841 void PluginManager::PluginStatus_t::BindOptional( PluginsEnum_t pid )
842 {
843 const LegacyApi_OptMethod* current = s_MethMessOpt[pid];
844 const wxDynamicLibrary& lib = Lib;
845
846 wxDoNotLogInThisScope please;
847
848 while( current->MethodName != NULL )
849 {
850 *(current->Dest) = (VoidMethod*)lib.GetSymbol( current->GetMethodName() );
851 current++;
852 }
853 }
854
855 // =====================================================================================
856 // PluginManager Implementations
857 // =====================================================================================
858
859 PluginManager::PluginManager()
860 {
861 }
862
863 PluginManager::~PluginManager() throw()
864 {
865 try
866 {
867 Unload();
868 }
869 DESTRUCTOR_CATCHALL
870
871 // All library unloading done automatically by wx.
872 }
873
874 void PluginManager::Load( PluginsEnum_t pid, const wxString& srcfile )
875 {
876 ScopedLock lock( m_mtx_PluginStatus );
877 pxAssume( (uint)pid < PluginId_Count );
878 Console.Indent().WriteLn( L"Binding %s\t: %s ", tbl_PluginInfo[pid].GetShortname().c_str(), srcfile.c_str() );
879 m_info[pid] = new PluginStatus_t( pid, srcfile );
880 }
881
882 void PluginManager::Load( const wxString (&folders)[PluginId_Count] )
883 {
884 if( !NeedsLoad() ) return;
885
886 wxDoNotLogInThisScope please;
887
888 Console.WriteLn( Color_StrongBlue, "\nLoading plugins..." );
889
890 ConsoleIndentScope indent;
891 const PluginInfo* pi = tbl_PluginInfo; do
892 {
893 Load( pi->id, folders[pi->id] );
894 pxYield( 2 );
895
896 } while( ++pi, pi->shortname != NULL );
897 indent.EndScope();
898
899 CDVDapi_Plugin.newDiskCB( cdvdNewDiskCB );
900
901 // Hack for PAD's stupid parameter passed on Init
902 PADinit = (_PADinit)m_info[PluginId_PAD]->CommonBindings.Init;
903 m_info[PluginId_PAD]->CommonBindings.Init = _hack_PADinit;
904
905 Console.WriteLn( Color_StrongBlue, "Plugins loaded successfully.\n" );
906
907 // HACK! Manually bind the Internal MemoryCard plugin for now, until
908 // we get things more completed in the new plugin api.
909
910 static const PS2E_EmulatorInfo myself =
911 {
912 "PCSX2",
913
914 { 0, PCSX2_VersionHi, PCSX2_VersionLo, SVN_REV },
915
916 x86caps.PhysicalCores,
917 x86caps.LogicalCores,
918 sizeof(wchar_t),
919
920 0,0,0,0,0,0,
921
922 pcsx2_GetInt,
923 pcsx2_GetBoolean,
924 pcsx2_GetString,
925 pcsx2_GetStringAlloc,
926 pcsx2_OSD_WriteLn
927 };
928
929 m_mcdPlugin = FileMcd_InitAPI( &myself );
930 if( m_mcdPlugin == NULL )
931 {
932 // fixme: use plugin's GetLastError (not implemented yet!)
933 throw Exception::PluginLoadError( PluginId_Mcd, wxEmptyString, "Internal Memorycard Plugin failed to load." );
934 }
935
936 SendLogFolder();
937 SendSettingsFolder();
938 }
939
940 void PluginManager::Unload(PluginsEnum_t pid)
941 {
942 ScopedLock lock( m_mtx_PluginStatus );
943 pxAssume( (uint)pid < PluginId_Count );
944 m_info[pid].Delete();
945 }
946
947 void PluginManager::Unload()
948 {
949 if( NeedsShutdown() )
950 Console.Warning( "(SysCorePlugins) Warning: Unloading plugins prior to shutdown!" );
951
952 //Shutdown();
953
954 if( !NeedsUnload() ) return;
955
956 DbgCon.WriteLn( Color_StrongBlue, "Unloading plugins..." );
957
958 for( int i=PluginId_Count-1; i>=0; --i )
959 Unload( tbl_PluginInfo[i].id );
960
961 DbgCon.WriteLn( Color_StrongBlue, "Plugins unloaded successfully." );
962 }
963
964 // Exceptions:
965 // FileNotFound - Thrown if one of the configured plugins doesn't exist.
966 // NotPcsxPlugin - Thrown if one of the configured plugins is an invalid or unsupported DLL
967
968 extern bool renderswitch;
969 extern void spu2DMA4Irq();
970 extern void spu2DMA7Irq();
971 extern void spu2Irq();
972
973 bool PluginManager::OpenPlugin_CDVD()
974 {
975 return DoCDVDopen();
976 }
977
978 bool PluginManager::OpenPlugin_GS()
979 {
980 GetMTGS().Resume();
981 return true;
982 }
983
984 bool PluginManager::OpenPlugin_PAD()
985 {
986 return !PADopen( (void*)&pDsp );
987 }
988
989 bool PluginManager::OpenPlugin_SPU2()
990 {
991 if( SPU2open((void*)&pDsp) ) return false;
992
993 #ifdef ENABLE_NEW_IOPDMA_SPU2
994 SPU2irqCallback( spu2Irq );
995 #else
996 SPU2irqCallback( spu2Irq, spu2DMA4Irq, spu2DMA7Irq );
997 if( SPU2setDMABaseAddr != NULL ) SPU2setDMABaseAddr((uptr)psxM);
998 #endif
999 if( SPU2setClockPtr != NULL ) SPU2setClockPtr(&psxRegs.cycle);
1000 return true;
1001 }
1002
1003 bool PluginManager::OpenPlugin_DEV9()
1004 {
1005 dev9Handler = NULL;
1006
1007 if( DEV9open( (void*)&pDsp ) ) return false;
1008 DEV9irqCallback( dev9Irq );
1009 dev9Handler = DEV9irqHandler();
1010 return true;
1011 }
1012
1013 bool PluginManager::OpenPlugin_USB()
1014 {
1015 usbHandler = NULL;
1016
1017 if( USBopen((void*)&pDsp) ) return false;
1018 USBirqCallback( usbIrq );
1019 usbHandler = USBirqHandler();
1020 if( USBsetRAM != NULL )
1021 USBsetRAM(psxM);
1022 return true;
1023 }
1024
1025 bool PluginManager::OpenPlugin_FW()
1026 {
1027 if( FWopen((void*)&pDsp) ) return false;
1028 FWirqCallback( fwIrq );
1029 return true;
1030 }
1031
1032 bool PluginManager::OpenPlugin_Mcd()
1033 {
1034 ScopedLock lock( m_mtx_PluginStatus );
1035
1036 // [TODO] Fix up and implement PS2E_SessionInfo here!! (the currently NULL parameter)
1037 if( SysPlugins.Mcd )
1038 SysPlugins.Mcd->Base.EmuOpen( (PS2E_THISPTR) SysPlugins.Mcd, NULL );
1039
1040 return true;
1041 }
1042
1043 void PluginManager::Open( PluginsEnum_t pid )
1044 {
1045 pxAssume( (uint)pid < PluginId_Count );
1046 if( IsOpen(pid) ) return;
1047
1048 Console.Indent().WriteLn( "Opening %s", tbl_PluginInfo[pid].shortname );
1049
1050 // Each Open needs to be called explicitly. >_<
1051
1052 bool result = true;
1053 switch( pid )
1054 {
1055 case PluginId_GS: result = OpenPlugin_GS(); break;
1056 case PluginId_PAD: result = OpenPlugin_PAD(); break;
1057 case PluginId_CDVD: result = OpenPlugin_CDVD(); break;
1058 case PluginId_SPU2: result = OpenPlugin_SPU2(); break;
1059 case PluginId_USB: result = OpenPlugin_USB(); break;
1060 case PluginId_FW: result = OpenPlugin_FW(); break;
1061 case PluginId_DEV9: result = OpenPlugin_DEV9(); break;
1062
1063 jNO_DEFAULT;
1064 }
1065 if( !result )
1066 throw Exception::PluginOpenError( pid );
1067
1068 ScopedLock lock( m_mtx_PluginStatus );
1069 if( m_info[pid] ) m_info[pid]->IsOpened = true;
1070 }
1071
1072 void PluginManager::Open()
1073 {
1074 Init();
1075
1076 if( !NeedsOpen() ) return; // Spam stopper: returns before writing any logs. >_<
1077
1078 Console.WriteLn( Color_StrongBlue, "Opening plugins..." );
1079
1080 SendSettingsFolder();
1081
1082 const PluginInfo* pi = tbl_PluginInfo; do {
1083 Open( pi->id );
1084 // If GS doesn't support GSopen2, need to wait until call to GSopen
1085 // returns to populate pDsp. If it does, can initialize other plugins
1086 // at same time as GS, as long as GSopen2 does not subclass its window.
1087 if (pi->id == PluginId_GS && !GSopen2) GetMTGS().WaitForOpen();
1088 } while( ++pi, pi->shortname != NULL );
1089
1090 if (GSopen2) GetMTGS().WaitForOpen();
1091
1092 if( !AtomicExchange( m_mcdOpen, true ) )
1093 {
1094 DbgCon.Indent().WriteLn( "Opening Memorycards");
1095 OpenPlugin_Mcd();
1096 }
1097
1098 Console.WriteLn( Color_StrongBlue, "Plugins opened successfully." );
1099 }
1100
1101 void PluginManager::_generalclose( PluginsEnum_t pid )
1102 {
1103 ScopedLock lock( m_mtx_PluginStatus );
1104 if( m_info[pid] ) m_info[pid]->CommonBindings.Close();
1105 }
1106
1107 void PluginManager::ClosePlugin_GS()
1108 {
1109 // old-skool: force-close PAD before GS, because the PAD depends on the GS window.
1110
1111 if( GetMTGS().IsSelf() )
1112 _generalclose( PluginId_GS );
1113 else
1114 {
1115 if( !GSopen2 ) Close( PluginId_PAD );
1116 GetMTGS().Suspend();
1117 }
1118 }
1119
1120 void PluginManager::ClosePlugin_CDVD()
1121 {
1122 DoCDVDclose();
1123 }
1124
1125 void PluginManager::ClosePlugin_PAD()
1126 {
1127 _generalclose( PluginId_PAD );
1128 }
1129
1130 void PluginManager::ClosePlugin_SPU2()
1131 {
1132 _generalclose( PluginId_SPU2 );
1133 }
1134
1135 void PluginManager::ClosePlugin_DEV9()
1136 {
1137 _generalclose( PluginId_DEV9 );
1138 }
1139
1140 void PluginManager::ClosePlugin_USB()
1141 {
1142 _generalclose( PluginId_USB );
1143 }
1144
1145 void PluginManager::ClosePlugin_FW()
1146 {
1147 _generalclose( PluginId_FW );
1148 }
1149
1150 void PluginManager::ClosePlugin_Mcd()
1151 {
1152 ScopedLock lock( m_mtx_PluginStatus );
1153 if( SysPlugins.Mcd ) SysPlugins.Mcd->Base.EmuClose( (PS2E_THISPTR) SysPlugins.Mcd );
1154 }
1155
1156 void PluginManager::Close( PluginsEnum_t pid )
1157 {
1158 pxAssume( (uint)pid < PluginId_Count );
1159
1160 if( !IsOpen(pid) ) return;
1161
1162 if( !GetMTGS().IsSelf() ) // stop the spam!
1163 Console.Indent().WriteLn( "Closing %s", tbl_PluginInfo[pid].shortname );
1164
1165 switch( pid )
1166 {
1167 case PluginId_GS: ClosePlugin_GS(); break;
1168 case PluginId_PAD: ClosePlugin_PAD(); break;
1169 case PluginId_CDVD: ClosePlugin_CDVD(); break;
1170 case PluginId_SPU2: ClosePlugin_SPU2(); break;
1171 case PluginId_USB: ClosePlugin_USB(); break;
1172 case PluginId_FW: ClosePlugin_FW(); break;
1173 case PluginId_DEV9: ClosePlugin_DEV9(); break;
1174 case PluginId_Mcd: ClosePlugin_Mcd(); break;
1175
1176 jNO_DEFAULT;
1177 }
1178
1179 ScopedLock lock( m_mtx_PluginStatus );
1180 if( m_info[pid] ) m_info[pid]->IsOpened = false;
1181 }
1182
1183 void PluginManager::Close()
1184 {
1185 if( !NeedsClose() ) return; // Spam stopper; returns before writing any logs. >_<
1186
1187 // Close plugins in reverse order of the initialization procedure, which
1188 // ensures the GS gets closed last.
1189
1190 DbgCon.WriteLn( Color_StrongBlue, "Closing plugins..." );
1191
1192 if( AtomicExchange( m_mcdOpen, false ) )
1193 {
1194 DbgCon.Indent().WriteLn( "Closing Memorycards");
1195 ClosePlugin_Mcd();
1196 }
1197
1198 for( int i=PluginId_Count-1; i>=0; --i )
1199 Close( tbl_PluginInfo[i].id );
1200
1201 DbgCon.WriteLn( Color_StrongBlue, "Plugins closed successfully." );
1202 }
1203
1204 void PluginManager::Init( PluginsEnum_t pid )
1205 {
1206 ScopedLock lock( m_mtx_PluginStatus );
1207
1208 if( !m_info[pid] || m_info[pid]->IsInitialized ) return;
1209
1210 Console.Indent().WriteLn( "Init %s", tbl_PluginInfo[pid].shortname );
1211 if( NULL != m_info[pid]->CommonBindings.Init() )
1212 throw Exception::PluginInitError( pid );
1213
1214 m_info[pid]->IsInitialized = true;
1215 }
1216
1217 void PluginManager::Shutdown( PluginsEnum_t pid )
1218 {
1219 ScopedLock lock( m_mtx_PluginStatus );
1220
1221 if( !m_info[pid] || !m_info[pid]->IsInitialized ) return;
1222 DevCon.Indent().WriteLn( "Shutdown %s", tbl_PluginInfo[pid].shortname );
1223 m_info[pid]->IsInitialized = false;
1224 m_info[pid]->CommonBindings.Shutdown();
1225 }
1226
1227 // Initializes all plugins. Plugin initialization should be done once for every new emulation
1228 // session. During a session emulation can be paused/resumed using Open/Close, and should be
1229 // terminated using Shutdown().
1230 //
1231 // In a purist emulation sense, Init() and Shutdown() should only ever need be called for when
1232 // the PS2's hardware has received a *full* hard reset. Soft resets typically should rely on
1233 // the PS2's bios/kernel to re-initialize hardware on the fly.
1234 //
1235 void PluginManager::Init()
1236 {
1237 if( !NeedsInit() ) return;
1238
1239 Console.WriteLn( Color_StrongBlue, "\nInitializing plugins..." );
1240 const PluginInfo* pi = tbl_PluginInfo; do {
1241 Init( pi->id );
1242 } while( ++pi, pi->shortname != NULL );
1243
1244 if( SysPlugins.Mcd == NULL )
1245 {
1246 SysPlugins.Mcd = (PS2E_ComponentAPI_Mcd*)m_mcdPlugin->NewComponentInstance( PS2E_TYPE_Mcd );
1247 if( SysPlugins.Mcd == NULL )
1248 {
1249 // fixme: use plugin's GetLastError (not implemented yet!)
1250 throw Exception::PluginInitError( PluginId_Mcd, "Internal Memorycard Plugin failed to initialize." );
1251 }
1252 }
1253
1254 Console.WriteLn( Color_StrongBlue, "Plugins initialized successfully.\n" );
1255 }
1256
1257
1258 // Shuts down all plugins. Plugins are closed first, if necessary.
1259 //
1260 // In a purist emulation sense, Init() and Shutdown() should only ever need be called for when
1261 // the PS2's hardware has received a *full* hard reset. Soft resets typically should rely on
1262 // the PS2's bios/kernel to re-initialize hardware on the fly.
1263 //
1264 void PluginManager::Shutdown()
1265 {
1266 if( !NeedsShutdown() ) return;
1267
1268 pxAssumeDev( !NeedsClose(), "Cannot shut down plugins prior to Close()" );
1269
1270 GetMTGS().Cancel(); // cancel it for speedier shutdown!
1271
1272 DbgCon.WriteLn( Color_StrongGreen, "Shutting down plugins..." );
1273
1274 // Shutdown plugins in reverse order (probably doesn't matter...
1275 // ... but what the heck, right?)
1276
1277 for( int i=PluginId_Count-1; i>=0; --i )
1278 {
1279 Shutdown( tbl_PluginInfo[i].id );
1280 }
1281
1282 // More memorycard hacks!!
1283
1284 if( (SysPlugins.Mcd != NULL) && (m_mcdPlugin != NULL) )
1285 {
1286 m_mcdPlugin->DeleteComponentInstance( (PS2E_THISPTR)SysPlugins.Mcd );
1287 SysPlugins.Mcd = NULL;
1288 }
1289
1290 DbgCon.WriteLn( Color_StrongGreen, "Plugins shutdown successfully." );
1291 }
1292
1293 // For internal use only, unless you're the MTGS. Then it's for you too!
1294 // Returns false if the plugin returned an error.
1295 bool PluginManager::DoFreeze( PluginsEnum_t pid, int mode, freezeData* data )
1296 {
1297 if( (pid == PluginId_GS) && !GetMTGS().IsSelf() )
1298 {
1299 // GS needs some thread safety love...
1300
1301 MTGS_FreezeData woot = { data, 0 };
1302 GetMTGS().Freeze( mode, woot );
1303 return woot.retval != -1;
1304 }
1305 else
1306 {
1307 ScopedLock lock( m_mtx_PluginStatus );
1308 return !m_info[pid] || m_info[pid]->CommonBindings.Freeze( mode, data ) != -1;
1309 }
1310 }
1311
1312 // Thread Safety:
1313 // This function should only be called by the Main GUI thread and the GS thread (for GS states only),
1314 // as it has special handlers to ensure that GS freeze commands are executed appropriately on the
1315 // GS thread.
1316 //
1317 void PluginManager::Freeze( PluginsEnum_t pid, SaveStateBase& state )
1318 {
1319 // No locking leeded -- DoFreeze locks as needed, and this avoids MTGS deadlock.
1320 //ScopedLock lock( m_mtx_PluginStatus );
1321
1322 Console.Indent().WriteLn( "%s %s", state.IsSaving() ? "Saving" : "Loading",
1323 tbl_PluginInfo[pid].shortname );
1324
1325 freezeData fP = { 0, NULL };
1326 if( !DoFreeze( pid, FREEZE_SIZE, &fP ) )
1327 fP.size = 0;
1328
1329 int fsize = fP.size;
1330 state.Freeze( fsize );
1331
1332 if( state.IsLoading() && (fsize == 0) )
1333 {
1334 // no state data to read, but the plugin expects some state data.
1335 // Issue a warning to console...
1336 if( fP.size != 0 )
1337 Console.Indent().Warning( "Warning: No data for this plugin was found. Plugin status may be unpredictable." );
1338 return;
1339
1340 // Note: Size mismatch check could also be done here on loading, but
1341 // some plugins may have built-in version support for non-native formats or
1342 // older versions of a different size... or could give different sizes depending
1343 // on the status of the plugin when loading, so let's ignore it.
1344 }
1345
1346 fP.size = fsize;
1347 if( fP.size == 0 ) return;
1348
1349 state.PrepBlock( fP.size );
1350 fP.data = (s8*)state.GetBlockPtr();
1351
1352 if( state.IsSaving() )
1353 {
1354 if( !DoFreeze(pid, FREEZE_SAVE, &fP) )
1355 throw Exception::FreezePluginFailure( pid );
1356 }
1357 else
1358 {
1359 if( !DoFreeze(pid, FREEZE_LOAD, &fP) )
1360 throw Exception::ThawPluginFailure( pid );
1361 }
1362
1363 state.CommitBlock( fP.size );
1364 }
1365
1366 bool PluginManager::KeyEvent( const keyEvent& evt )
1367 {
1368 ScopedLock lock( m_mtx_PluginStatus );
1369
1370 // [TODO] : The plan here is to give plugins "first chance" handling of keys.
1371 // Handling order will be fixed (GS, SPU2, PAD, etc), and the first plugin to
1372 // pick up the key and return "true" (for handled) will cause the loop to break.
1373 // The current version of PS2E doesn't support it yet, though.
1374
1375 const PluginInfo* pi = tbl_PluginInfo; do {
1376 if( pi->id != PluginId_PAD && m_info[pi->id] )
1377 m_info[pi->id]->CommonBindings.KeyEvent( const_cast<keyEvent*>(&evt) );
1378 } while( ++pi, pi->shortname != NULL );
1379
1380 return false;
1381 }
1382
1383 void PluginManager::SendSettingsFolder()
1384 {
1385 ScopedLock lock( m_mtx_PluginStatus );
1386 if( m_SettingsFolder.IsEmpty() ) return;
1387
1388 wxCharBuffer utf8buffer( m_SettingsFolder.ToUTF8() );
1389
1390 const PluginInfo* pi = tbl_PluginInfo; do {
1391 if( m_info[pi->id] ) m_info[pi->id]->CommonBindings.SetSettingsDir( utf8buffer );
1392 } while( ++pi, pi->shortname != NULL );
1393 }
1394
1395 void PluginManager::SetSettingsFolder( const wxString& folder )
1396 {
1397 ScopedLock lock( m_mtx_PluginStatus );
1398
1399 wxString fixedfolder( folder );
1400 if( !fixedfolder.IsEmpty() && (fixedfolder[fixedfolder.length()-1] != wxFileName::GetPathSeparator() ) )
1401 {
1402 fixedfolder += wxFileName::GetPathSeparator();
1403 }
1404
1405 if( m_SettingsFolder == fixedfolder ) return;
1406 m_SettingsFolder = fixedfolder;
1407 SendSettingsFolder();
1408 }
1409
1410 void PluginManager::SendLogFolder()
1411 {
1412 ScopedLock lock( m_mtx_PluginStatus );
1413 if( m_LogFolder.IsEmpty() ) return;
1414
1415 wxCharBuffer utf8buffer( m_LogFolder.ToUTF8() );
1416
1417 const PluginInfo* pi = tbl_PluginInfo; do {
1418 if( m_info[pi->id] ) m_info[pi->id]->CommonBindings.SetLogFolder( utf8buffer );
1419 } while( ++pi, pi->shortname != NULL );
1420 }
1421
1422 void PluginManager::SetLogFolder( const wxString& folder )
1423 {
1424 ScopedLock lock( m_mtx_PluginStatus );
1425
1426 wxString fixedfolder( folder );
1427 if( !fixedfolder.IsEmpty() && (fixedfolder[fixedfolder.length()-1] != wxFileName::GetPathSeparator() ) )
1428 {
1429 fixedfolder += wxFileName::GetPathSeparator();
1430 }
1431
1432 if( m_LogFolder == fixedfolder ) return;
1433 m_LogFolder = fixedfolder;
1434 SendLogFolder();
1435 }
1436
1437 void PluginManager::Configure( PluginsEnum_t pid )
1438 {
1439 ScopedLock lock( m_mtx_PluginStatus );
1440 if( m_info[pid] ) m_info[pid]->CommonBindings.Configure();
1441 }
1442
1443 bool PluginManager::AreLoaded() const
1444 {
1445 ScopedLock lock( m_mtx_PluginStatus );
1446 for( int i=0; i<PluginId_Count; ++i )
1447 {
1448 if( !m_info[i] ) return false;
1449 }
1450
1451 return true;
1452 }
1453
1454 bool PluginManager::AreAnyLoaded() const
1455 {
1456 ScopedLock lock( m_mtx_PluginStatus );
1457 for( int i=0; i<PluginId_Count; ++i )
1458 {
1459 if( m_info[i] ) return true;
1460 }
1461
1462 return false;
1463 }
1464
1465 bool PluginManager::AreAnyInitialized() const
1466 {
1467 ScopedLock lock( m_mtx_PluginStatus );
1468 const PluginInfo* pi = tbl_PluginInfo; do {
1469 if( IsInitialized(pi->id) ) return true;
1470 } while( ++pi, pi->shortname != NULL );
1471
1472 return false;
1473 }
1474
1475 bool PluginManager::IsOpen( PluginsEnum_t pid ) const
1476 {
1477 pxAssume( (uint)pid < PluginId_Count );
1478 ScopedLock lock( m_mtx_PluginStatus );
1479 return m_info[pid] && m_info[pid]->IsOpened;
1480 }
1481
1482 bool PluginManager::IsInitialized( PluginsEnum_t pid ) const
1483 {
1484 pxAssume( (uint)pid < PluginId_Count );
1485 ScopedLock lock( m_mtx_PluginStatus );
1486 return m_info[pid] && m_info[pid]->IsInitialized;
1487 }
1488
1489 bool PluginManager::IsLoaded( PluginsEnum_t pid ) const
1490 {
1491 pxAssume( (uint)pid < PluginId_Count );
1492 return !!m_info[pid];
1493 }
1494
1495 bool PluginManager::NeedsLoad() const
1496 {
1497 const PluginInfo* pi = tbl_PluginInfo; do {
1498 if( !IsLoaded(pi->id) ) return true;
1499 } while( ++pi, pi->shortname != NULL );
1500
1501 return false;
1502 }
1503
1504 bool PluginManager::NeedsUnload() const
1505 {
1506 const PluginInfo* pi = tbl_PluginInfo; do {
1507 if( IsLoaded(pi->id) ) return true;
1508 } while( ++pi, pi->shortname != NULL );
1509
1510 return false;
1511 }
1512
1513 bool PluginManager::NeedsInit() const
1514 {
1515 ScopedLock lock( m_mtx_PluginStatus );
1516
1517 const PluginInfo* pi = tbl_PluginInfo; do {
1518 if( !IsInitialized(pi->id) ) return true;
1519 } while( ++pi, pi->shortname != NULL );
1520
1521 return false;
1522 }
1523
1524 bool PluginManager::NeedsShutdown() const
1525 {
1526 ScopedLock lock( m_mtx_PluginStatus );
1527
1528 const PluginInfo* pi = tbl_PluginInfo; do {
1529 if( IsInitialized(pi->id) ) return true;
1530 } while( ++pi, pi->shortname != NULL );
1531
1532 return false;
1533 }
1534
1535 bool PluginManager::NeedsOpen() const
1536 {
1537 const PluginInfo* pi = tbl_PluginInfo; do {
1538 if( !IsOpen(pi->id) ) return true;
1539 } while( ++pi, pi->shortname != NULL );
1540
1541 return false;
1542 }
1543
1544 bool PluginManager::NeedsClose() const
1545 {
1546 const PluginInfo* pi = tbl_PluginInfo; do {
1547 if( IsOpen(pi->id) ) return true;
1548 } while( ++pi, pi->shortname != NULL );
1549
1550 return false;
1551 }
1552
1553 const wxString PluginManager::GetName( PluginsEnum_t pid ) const
1554 {
1555 ScopedLock lock( m_mtx_PluginStatus );
1556 pxAssume( (uint)pid < PluginId_Count );
1557 return m_info[pid] ? m_info[pid]->Name : (wxString)_("Unloaded Plugin");
1558 }
1559
1560 const wxString PluginManager::GetVersion( PluginsEnum_t pid ) const
1561 {
1562 ScopedLock lock( m_mtx_PluginStatus );
1563 pxAssume( (uint)pid < PluginId_Count );
1564 return m_info[pid] ? m_info[pid]->Version : L"0.0";
1565 }

  ViewVC Help
Powered by ViewVC 1.1.22