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

  ViewVC Help
Powered by ViewVC 1.1.22