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

Contents of /trunk/pcsx2/PluginManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (show annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (9 years, 4 months ago) by william
File size: 47196 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug in ./trunk
1 /* PCSX2 - PS2 Emulator for PCs
2 * Copyright (C) 2002-2010 PCSX2 Dev Team
3 *
4 * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU Lesser General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with PCSX2.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 #include "PrecompiledHeader.h"
17 #include "IopCommon.h"
18
19 #include <wx/dir.h>
20 #include <wx/file.h>
21
22 #include "GS.h"
23 #include "CDVD/CDVDisoReader.h"
24
25 #include "Utilities/ScopedPtr.h"
26
27 #if _MSC_VER
28 # include "svnrev.h"
29 #endif
30
31 SysPluginBindings SysPlugins;
32
33 bool SysPluginBindings::McdIsPresent( uint port, uint slot )
34 {
35 return !!Mcd->McdIsPresent( (PS2E_THISPTR) Mcd, port, slot );
36 }
37
38 void SysPluginBindings::McdGetSizeInfo( uint port, uint slot, PS2E_McdSizeInfo& outways )
39 {
40 if( Mcd->McdGetSizeInfo )
41 Mcd->McdGetSizeInfo( (PS2E_THISPTR) Mcd, port, slot, &outways );
42 }
43
44 void SysPluginBindings::McdRead( uint port, uint slot, u8 *dest, u32 adr, int size )
45 {
46 Mcd->McdRead( (PS2E_THISPTR) Mcd, port, slot, dest, adr, size );
47 }
48
49 void SysPluginBindings::McdSave( uint port, uint slot, const u8 *src, u32 adr, int size )
50 {
51 Mcd->McdSave( (PS2E_THISPTR) Mcd, port, slot, src, adr, size );
52 }
53
54 void SysPluginBindings::McdEraseBlock( uint port, uint slot, u32 adr )
55 {
56 Mcd->McdEraseBlock( (PS2E_THISPTR) Mcd, port, slot, adr );
57 }
58
59 u64 SysPluginBindings::McdGetCRC( uint port, uint slot )
60 {
61 return Mcd->McdGetCRC( (PS2E_THISPTR) Mcd, port, slot );
62 }
63
64
65 // ----------------------------------------------------------------------------
66 // Yay, order of this array shouldn't be important. :)
67 //
68 const PluginInfo tbl_PluginInfo[] =
69 {
70 { "GS", PluginId_GS, PS2E_LT_GS, PS2E_GS_VERSION },
71 { "PAD", PluginId_PAD, PS2E_LT_PAD, PS2E_PAD_VERSION },
72 { "SPU2", PluginId_SPU2, PS2E_LT_SPU2, PS2E_SPU2_VERSION },
73 { "CDVD", PluginId_CDVD, PS2E_LT_CDVD, PS2E_CDVD_VERSION },
74 { "USB", PluginId_USB, PS2E_LT_USB, PS2E_USB_VERSION },
75 { "FW", PluginId_FW, PS2E_LT_FW, PS2E_FW_VERSION },
76 { "DEV9", PluginId_DEV9, PS2E_LT_DEV9, PS2E_DEV9_VERSION },
77
78 { NULL },
79
80 // See PluginEnums_t for details on the MemoryCard plugin hack.
81 { "Mcd", PluginId_Mcd, 0, 0 },
82 };
83
84 typedef void CALLBACK VoidMethod();
85 typedef void CALLBACK vMeth(); // shorthand for VoidMethod
86
87 // ----------------------------------------------------------------------------
88 struct LegacyApi_CommonMethod
89 {
90 const char* MethodName;
91
92 // fallback is used if the method is null. If the method is null and fallback is null
93 // also, the plugin is considered incomplete or invalid, and an error is generated.
94 VoidMethod* Fallback;
95
96 // returns the method name as a wxString, converted from UTF8.
97 wxString GetMethodName( PluginsEnum_t pid ) const
98 {
99 return tbl_PluginInfo[pid].GetShortname() + fromUTF8( MethodName );
100 }
101 };
102
103 // ----------------------------------------------------------------------------
104 struct LegacyApi_ReqMethod
105 {
106 const char* MethodName;
107 VoidMethod** Dest; // Target function where the binding is saved.
108
109 // fallback is used if the method is null. If the method is null and fallback is null
110 // also, the plugin is considered incomplete or invalid, and an error is generated.
111 VoidMethod* Fallback;
112
113 // returns the method name as a wxString, converted from UTF8.
114 wxString GetMethodName( ) const
115 {
116 return fromUTF8( MethodName );
117 }
118 };
119
120 // ----------------------------------------------------------------------------
121 struct LegacyApi_OptMethod
122 {
123 const char* MethodName;
124 VoidMethod** Dest; // Target function where the binding is saved.
125
126 // returns the method name as a wxString, converted from UTF8.
127 wxString GetMethodName() const { return fromUTF8( MethodName ); }
128 };
129
130
131 static s32 CALLBACK fallback_freeze(int mode, freezeData *data)
132 {
133 if( mode == FREEZE_SIZE ) data->size = 0;
134 return 0;
135 }
136
137 static void CALLBACK fallback_keyEvent(keyEvent *ev) {}
138 static void CALLBACK fallback_setSettingsDir(const char* dir) {}
139 static void CALLBACK fallback_setLogDir(const char* dir) {}
140 static void CALLBACK fallback_configure() {}
141 static void CALLBACK fallback_about() {}
142 static s32 CALLBACK fallback_test() { return 0; }
143
144 _GSvsync GSvsync;
145 _GSopen GSopen;
146 _GSopen2 GSopen2;
147 _GSgifTransfer GSgifTransfer;
148 _GSgifTransfer1 GSgifTransfer1;
149 _GSgifTransfer2 GSgifTransfer2;
150 _GSgifTransfer3 GSgifTransfer3;
151 _GSgifSoftReset GSgifSoftReset;
152 _GSreadFIFO GSreadFIFO;
153 _GSreadFIFO2 GSreadFIFO2;
154 _GSchangeSaveState GSchangeSaveState;
155 _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 // 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
205 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 // 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 _SPU2reset SPU2reset;
258 _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 { "setLogDir", (vMeth*)fallback_setLogDir },
342
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 { "GSgifTransfer", (vMeth**)&GSgifTransfer, (vMeth*)GS_gifTransferLegacy },
360 { "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 { "GSgifTransfer1", (vMeth**)&GSgifTransfer1 },
388 { 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
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 static const LegacyApi_ReqMethod s_MethMessReq_SPU2[] =
542 {
543 { "SPU2open", (vMeth**)&SPU2open, NULL },
544 { "SPU2reset", (vMeth**)&SPU2reset, SPU2_Reset },
545 { "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 SysCorePlugins *g_plugins = NULL;
672
673 // ---------------------------------------------------------------------------------
674 // Plugin-related Exception Implementations
675 // ---------------------------------------------------------------------------------
676
677 Exception::PluginOpenError::PluginOpenError( PluginsEnum_t pid )
678 {
679 PluginId = pid;
680 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 }
683
684 Exception::PluginInitError::PluginInitError( PluginsEnum_t pid )
685 {
686 PluginId = pid;
687 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 }
690
691 Exception::PluginLoadError::PluginLoadError( PluginsEnum_t pid )
692 {
693 PluginId = pid;
694 }
695
696 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 );
724 }
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 );
738 }
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 SysCorePlugins::PluginStatus_t::PluginStatus_t( PluginsEnum_t _pid, const wxString& srcfile )
782 : Filename( srcfile )
783 {
784 pid = _pid;
785
786 IsInitialized = false;
787 IsOpened = false;
788
789 if( Filename.IsEmpty() )
790 throw Exception::PluginInitError( pid ).SetDiagMsg( L"Empty plugin filename" );
791
792 if( !wxFile::Exists( Filename ) )
793 throw Exception::PluginLoadError( pid ).SetStreamName(srcfile)
794 .SetBothMsgs(wxLt("The configured %s plugin file was not found"));
795
796 if( !Lib.Load( Filename ) )
797 throw Exception::PluginLoadError( pid ).SetStreamName(Filename)
798 .SetBothMsgs(wxLt("The configured %s plugin file is not a valid dynamic library"));
799
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 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
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 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 }
843
844 void SysCorePlugins::PluginStatus_t::BindCommon( PluginsEnum_t pid )
845 {
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 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 }
864
865 target++;
866 current++;
867 }
868 }
869
870 void SysCorePlugins::PluginStatus_t::BindRequired( PluginsEnum_t pid )
871 {
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 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 }
890
891 current++;
892 }
893 }
894
895 void SysCorePlugins::PluginStatus_t::BindOptional( PluginsEnum_t pid )
896 {
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 // SysCorePlugins Implementations
911 // =====================================================================================
912
913 SysCorePlugins::SysCorePlugins()
914 {
915 }
916
917 SysCorePlugins::~SysCorePlugins() throw()
918 {
919 try
920 {
921 Unload();
922 }
923 DESTRUCTOR_CATCHALL
924
925 // All library unloading done automatically by wx.
926 }
927
928 void SysCorePlugins::Load( PluginsEnum_t pid, const wxString& srcfile )
929 {
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 void SysCorePlugins::Load( const wxString (&folders)[PluginId_Count] )
937 {
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 indent.LeaveScope();
952
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 throw Exception::PluginLoadError( PluginId_Mcd ).SetDiagMsg(L"Internal Memorycard Plugin failed to load.");
988 }
989
990 SendLogFolder();
991 SendSettingsFolder();
992 }
993
994 void SysCorePlugins::Unload(PluginsEnum_t pid)
995 {
996 ScopedLock lock( m_mtx_PluginStatus );
997 pxAssume( (uint)pid < PluginId_Count );
998 m_info[pid].Delete();
999 }
1000
1001 void SysCorePlugins::Unload()
1002 {
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 bool SysCorePlugins::OpenPlugin_CDVD()
1028 {
1029 return DoCDVDopen();
1030 }
1031
1032 bool SysCorePlugins::OpenPlugin_GS()
1033 {
1034 GetMTGS().Resume();
1035 return true;
1036 }
1037
1038 bool SysCorePlugins::OpenPlugin_PAD()
1039 {
1040 return !PADopen( (void*)&pDsp );
1041 }
1042
1043 bool SysCorePlugins::OpenPlugin_SPU2()
1044 {
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 bool SysCorePlugins::OpenPlugin_DEV9()
1058 {
1059 dev9Handler = NULL;
1060
1061 if( DEV9open( (void*)&pDsp ) ) return false;
1062 DEV9irqCallback( dev9Irq );
1063 dev9Handler = DEV9irqHandler();
1064 return true;
1065 }
1066
1067 bool SysCorePlugins::OpenPlugin_USB()
1068 {
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 bool SysCorePlugins::OpenPlugin_FW()
1080 {
1081 if( FWopen((void*)&pDsp) ) return false;
1082 FWirqCallback( fwIrq );
1083 return true;
1084 }
1085
1086 bool SysCorePlugins::OpenPlugin_Mcd()
1087 {
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 void SysCorePlugins::Open( PluginsEnum_t pid )
1098 {
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 void SysCorePlugins::Open()
1127 {
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 void SysCorePlugins::_generalclose( PluginsEnum_t pid )
1156 {
1157 ScopedLock lock( m_mtx_PluginStatus );
1158 if( m_info[pid] ) m_info[pid]->CommonBindings.Close();
1159 }
1160
1161 void SysCorePlugins::ClosePlugin_GS()
1162 {
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 void SysCorePlugins::ClosePlugin_CDVD()
1175 {
1176 DoCDVDclose();
1177 }
1178
1179 void SysCorePlugins::ClosePlugin_PAD()
1180 {
1181 _generalclose( PluginId_PAD );
1182 }
1183
1184 void SysCorePlugins::ClosePlugin_SPU2()
1185 {
1186 _generalclose( PluginId_SPU2 );
1187 }
1188
1189 void SysCorePlugins::ClosePlugin_DEV9()
1190 {
1191 _generalclose( PluginId_DEV9 );
1192 }
1193
1194 void SysCorePlugins::ClosePlugin_USB()
1195 {
1196 _generalclose( PluginId_USB );
1197 }
1198
1199 void SysCorePlugins::ClosePlugin_FW()
1200 {
1201 _generalclose( PluginId_FW );
1202 }
1203
1204 void SysCorePlugins::ClosePlugin_Mcd()
1205 {
1206 ScopedLock lock( m_mtx_PluginStatus );
1207 if( SysPlugins.Mcd ) SysPlugins.Mcd->Base.EmuClose( (PS2E_THISPTR) SysPlugins.Mcd );
1208 }
1209
1210 void SysCorePlugins::Close( PluginsEnum_t pid )
1211 {
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 void SysCorePlugins::Close()
1238 {
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 Console.WriteLn( Color_StrongBlue, "Closing plugins..." );
1245
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 Console.WriteLn( Color_StrongBlue, "Plugins closed successfully." );
1256 }
1257
1258 void SysCorePlugins::Init( PluginsEnum_t pid )
1259 {
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 void SysCorePlugins::Shutdown( PluginsEnum_t pid )
1272 {
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 // 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 // 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 bool SysCorePlugins::Init()
1293 {
1294 if( !NeedsInit() ) return false;
1295
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 throw Exception::PluginInitError( PluginId_Mcd )
1308 .SetBothMsgs(wxLt("Internal Memorycard Plugin failed to initialize."));
1309 }
1310 }
1311
1312 Console.WriteLn( Color_StrongBlue, "Plugins initialized successfully.\n" );
1313
1314 return true;
1315 }
1316
1317
1318 // Shuts down all plugins. Plugins are closed first, if necessary.
1319 // 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 //
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 bool SysCorePlugins::Shutdown()
1327 {
1328 if( !NeedsShutdown() ) return false;
1329
1330 pxAssertDev( !NeedsClose(), "Cannot shut down plugins prior to Close()" );
1331
1332 GetMTGS().Cancel(); // cancel it for speedier shutdown!
1333
1334 Console.WriteLn( Color_StrongGreen, "Shutting down plugins..." );
1335
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 Console.WriteLn( Color_StrongGreen, "Plugins shutdown successfully." );
1353
1354 return true;
1355 }
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 bool SysCorePlugins::DoFreeze( PluginsEnum_t pid, int mode, freezeData* data )
1360 {
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 void SysCorePlugins::Freeze( PluginsEnum_t pid, SaveStateBase& state )
1382 {
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 bool SysCorePlugins::KeyEvent( const keyEvent& evt )
1431 {
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 void SysCorePlugins::SendSettingsFolder()
1448 {
1449 ScopedLock lock( m_mtx_PluginStatus );
1450 if( m_SettingsFolder.IsEmpty() ) return;
1451
1452 pxToUTF8 utf8buffer( m_SettingsFolder );
1453
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 void SysCorePlugins::SetSettingsFolder( const wxString& folder )
1460 {
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 void SysCorePlugins::SendLogFolder()
1474 {
1475 ScopedLock lock( m_mtx_PluginStatus );
1476 if( m_LogFolder.IsEmpty() ) return;
1477
1478 pxToUTF8 utf8buffer( m_LogFolder );
1479
1480 const PluginInfo* pi = tbl_PluginInfo; do {
1481 if( m_info[pi->id] ) m_info[pi->id]->CommonBindings.SetLogDir( utf8buffer );
1482 } while( ++pi, pi->shortname != NULL );
1483 }
1484
1485 void SysCorePlugins::SetLogFolder( const wxString& folder )
1486 {
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 void SysCorePlugins::Configure( PluginsEnum_t pid )
1500 {
1501 ScopedLock lock( m_mtx_PluginStatus );
1502 if( m_info[pid] ) m_info[pid]->CommonBindings.Configure();
1503 }
1504
1505 bool SysCorePlugins::AreLoaded() const
1506 {
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 bool SysCorePlugins::AreOpen() const
1517 {
1518 ScopedLock lock( m_mtx_PluginStatus );
1519 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 for( int i=0; i<PluginId_Count; ++i )
1530 {
1531 if( m_info[i] ) return true;
1532 }
1533
1534 return false;
1535 }
1536
1537 bool SysCorePlugins::AreAnyInitialized() const
1538 {
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 bool SysCorePlugins::IsOpen( PluginsEnum_t pid ) const
1548 {
1549 pxAssume( (uint)pid < PluginId_Count );
1550 ScopedLock lock( m_mtx_PluginStatus );
1551 return m_info[pid] && m_info[pid]->IsInitialized && m_info[pid]->IsOpened;
1552 }
1553
1554 bool SysCorePlugins::IsInitialized( PluginsEnum_t pid ) const
1555 {
1556 pxAssume( (uint)pid < PluginId_Count );
1557 ScopedLock lock( m_mtx_PluginStatus );
1558 return m_info[pid] && m_info[pid]->IsInitialized;
1559 }
1560
1561 bool SysCorePlugins::IsLoaded( PluginsEnum_t pid ) const
1562 {
1563 pxAssume( (uint)pid < PluginId_Count );
1564 return !!m_info[pid];
1565 }
1566
1567 bool SysCorePlugins::NeedsLoad() const
1568 {
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 bool SysCorePlugins::NeedsUnload() const
1577 {
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 bool SysCorePlugins::NeedsInit() const
1586 {
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 bool SysCorePlugins::NeedsShutdown() const
1597 {
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 bool SysCorePlugins::NeedsOpen() const
1608 {
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 bool SysCorePlugins::NeedsClose() const
1617 {
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 const wxString SysCorePlugins::GetName( PluginsEnum_t pid ) const
1626 {
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 const wxString SysCorePlugins::GetVersion( PluginsEnum_t pid ) const
1633 {
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