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

Annotation of /trunk/pcsx2/PluginManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide 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 william 31 /* 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