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

  ViewVC Help
Powered by ViewVC 1.1.22