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

  ViewVC Help
Powered by ViewVC 1.1.22