Merge pull request #262 from retro-wertz/fix_input
[pcsx_rearmed.git] / libpcsxcore / plugins.c
1 /***************************************************************************
2  *   Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team              *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *   51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA.           *
18  ***************************************************************************/
19
20 /*
21 * Plugin library callback/access functions.
22 */
23
24 #include "plugins.h"
25 #include "cdriso.h"
26 #include "../plugins/dfinput/externals.h"
27
28 static char IsoFile[MAXPATHLEN] = "";
29 static s64 cdOpenCaseTime = 0;
30
31 GPUupdateLace         GPU_updateLace;
32 GPUinit               GPU_init;
33 GPUshutdown           GPU_shutdown;
34 GPUconfigure          GPU_configure;
35 GPUtest               GPU_test;
36 GPUabout              GPU_about;
37 GPUopen               GPU_open;
38 GPUclose              GPU_close;
39 GPUreadStatus         GPU_readStatus;
40 GPUreadData           GPU_readData;
41 GPUreadDataMem        GPU_readDataMem;
42 GPUwriteStatus        GPU_writeStatus;
43 GPUwriteData          GPU_writeData;
44 GPUwriteDataMem       GPU_writeDataMem;
45 GPUdmaChain           GPU_dmaChain;
46 GPUkeypressed         GPU_keypressed;
47 GPUdisplayText        GPU_displayText;
48 GPUmakeSnapshot       GPU_makeSnapshot;
49 GPUfreeze             GPU_freeze;
50 GPUgetScreenPic       GPU_getScreenPic;
51 GPUshowScreenPic      GPU_showScreenPic;
52 GPUclearDynarec       GPU_clearDynarec;
53 GPUvBlank             GPU_vBlank;
54
55 CDRinit               CDR_init;
56 CDRshutdown           CDR_shutdown;
57 CDRopen               CDR_open;
58 CDRclose              CDR_close;
59 CDRtest               CDR_test;
60 CDRgetTN              CDR_getTN;
61 CDRgetTD              CDR_getTD;
62 CDRreadTrack          CDR_readTrack;
63 CDRgetBuffer          CDR_getBuffer;
64 CDRplay               CDR_play;
65 CDRstop               CDR_stop;
66 CDRgetStatus          CDR_getStatus;
67 CDRgetDriveLetter     CDR_getDriveLetter;
68 CDRgetBufferSub       CDR_getBufferSub;
69 CDRconfigure          CDR_configure;
70 CDRabout              CDR_about;
71 CDRsetfilename        CDR_setfilename;
72 CDRreadCDDA           CDR_readCDDA;
73 CDRgetTE              CDR_getTE;
74
75 SPUconfigure          SPU_configure;
76 SPUabout              SPU_about;
77 SPUinit               SPU_init;
78 SPUshutdown           SPU_shutdown;
79 SPUtest               SPU_test;
80 SPUopen               SPU_open;
81 SPUclose              SPU_close;
82 SPUplaySample         SPU_playSample;
83 SPUwriteRegister      SPU_writeRegister;
84 SPUreadRegister       SPU_readRegister;
85 SPUwriteDMA           SPU_writeDMA;
86 SPUreadDMA            SPU_readDMA;
87 SPUwriteDMAMem        SPU_writeDMAMem;
88 SPUreadDMAMem         SPU_readDMAMem;
89 SPUplayADPCMchannel   SPU_playADPCMchannel;
90 SPUfreeze             SPU_freeze;
91 SPUregisterCallback   SPU_registerCallback;
92 SPUregisterScheduleCb SPU_registerScheduleCb;
93 SPUasync              SPU_async;
94 SPUplayCDDAchannel    SPU_playCDDAchannel;
95
96 PADconfigure          PAD1_configure;
97 PADabout              PAD1_about;
98 PADinit               PAD1_init;
99 PADshutdown           PAD1_shutdown;
100 PADtest               PAD1_test;
101 PADopen               PAD1_open;
102 PADclose              PAD1_close;
103 PADquery              PAD1_query;
104 PADreadPort1          PAD1_readPort1;
105 PADkeypressed         PAD1_keypressed;
106 PADstartPoll          PAD1_startPoll;
107 PADpoll               PAD1_poll;
108 PADsetSensitive       PAD1_setSensitive;
109
110 PADconfigure          PAD2_configure;
111 PADabout              PAD2_about;
112 PADinit               PAD2_init;
113 PADshutdown           PAD2_shutdown;
114 PADtest               PAD2_test;
115 PADopen               PAD2_open;
116 PADclose              PAD2_close;
117 PADquery              PAD2_query;
118 PADreadPort2          PAD2_readPort2;
119 PADkeypressed         PAD2_keypressed;
120 PADstartPoll          PAD2_startPoll;
121 PADpoll               PAD2_poll;
122 PADsetSensitive       PAD2_setSensitive;
123
124 NETinit               NET_init;
125 NETshutdown           NET_shutdown;
126 NETopen               NET_open;
127 NETclose              NET_close;
128 NETtest               NET_test;
129 NETconfigure          NET_configure;
130 NETabout              NET_about;
131 NETpause              NET_pause;
132 NETresume             NET_resume;
133 NETqueryPlayer        NET_queryPlayer;
134 NETsendData           NET_sendData;
135 NETrecvData           NET_recvData;
136 NETsendPadData        NET_sendPadData;
137 NETrecvPadData        NET_recvPadData;
138 NETsetInfo            NET_setInfo;
139 NETkeypressed         NET_keypressed;
140
141 #ifdef ENABLE_SIO1API
142
143 SIO1init              SIO1_init;
144 SIO1shutdown          SIO1_shutdown;
145 SIO1open              SIO1_open;
146 SIO1close             SIO1_close;
147 SIO1test              SIO1_test;
148 SIO1configure         SIO1_configure;
149 SIO1about             SIO1_about;
150 SIO1pause             SIO1_pause;
151 SIO1resume            SIO1_resume;
152 SIO1keypressed        SIO1_keypressed;
153 SIO1writeData8        SIO1_writeData8;
154 SIO1writeData16       SIO1_writeData16;
155 SIO1writeData32       SIO1_writeData32;
156 SIO1writeStat16       SIO1_writeStat16;
157 SIO1writeStat32       SIO1_writeStat32;
158 SIO1writeMode16       SIO1_writeMode16;
159 SIO1writeMode32       SIO1_writeMode32;
160 SIO1writeCtrl16       SIO1_writeCtrl16;
161 SIO1writeCtrl32       SIO1_writeCtrl32;
162 SIO1writeBaud16       SIO1_writeBaud16;
163 SIO1writeBaud32       SIO1_writeBaud32;
164 SIO1readData8         SIO1_readData8;
165 SIO1readData16        SIO1_readData16;
166 SIO1readData32        SIO1_readData32;
167 SIO1readStat16        SIO1_readStat16;
168 SIO1readStat32        SIO1_readStat32;
169 SIO1readMode16        SIO1_readMode16;
170 SIO1readMode32        SIO1_readMode32;
171 SIO1readCtrl16        SIO1_readCtrl16;
172 SIO1readCtrl32        SIO1_readCtrl32;
173 SIO1readBaud16        SIO1_readBaud16;
174 SIO1readBaud32        SIO1_readBaud32;
175 SIO1registerCallback  SIO1_registerCallback;
176
177 #endif
178
179 static const char *err;
180
181 #define CheckErr(func) { \
182         err = SysLibError(); \
183         if (err != NULL) { SysMessage(_("Error loading %s: %s"), func, err); return -1; } \
184 }
185
186 #define LoadSym(dest, src, name, checkerr) { \
187         dest = (src)SysLoadSym(drv, name); \
188         if (checkerr) { CheckErr(name); } else SysLibError(); \
189 }
190
191 void *hGPUDriver = NULL;
192
193 void CALLBACK GPU__displayText(char *pText) {
194         SysPrintf("%s\n", pText);
195 }
196
197 long CALLBACK GPU__configure(void) { return 0; }
198 long CALLBACK GPU__test(void) { return 0; }
199 void CALLBACK GPU__about(void) {}
200 void CALLBACK GPU__makeSnapshot(void) {}
201 void CALLBACK GPU__keypressed(int key) {}
202 long CALLBACK GPU__getScreenPic(unsigned char *pMem) { return -1; }
203 long CALLBACK GPU__showScreenPic(unsigned char *pMem) { return -1; }
204 void CALLBACK GPU__clearDynarec(void (CALLBACK *callback)(void)) {}
205 void CALLBACK GPU__vBlank(int val) {}
206
207 #define LoadGpuSym1(dest, name) \
208         LoadSym(GPU_##dest, GPU##dest, name, TRUE);
209
210 #define LoadGpuSym0(dest, name) \
211         LoadSym(GPU_##dest, GPU##dest, name, FALSE); \
212         if (GPU_##dest == NULL) GPU_##dest = (GPU##dest) GPU__##dest;
213
214 #define LoadGpuSymN(dest, name) \
215         LoadSym(GPU_##dest, GPU##dest, name, FALSE);
216
217 static int LoadGPUplugin(const char *GPUdll) {
218         void *drv;
219
220         hGPUDriver = SysLoadLibrary(GPUdll);
221         if (hGPUDriver == NULL) {
222                 GPU_configure = NULL;
223                 SysMessage (_("Could not load GPU plugin %s!"), GPUdll); return -1;
224         }
225         drv = hGPUDriver;
226         LoadGpuSym1(init, "GPUinit");
227         LoadGpuSym1(shutdown, "GPUshutdown");
228         LoadGpuSym1(open, "GPUopen");
229         LoadGpuSym1(close, "GPUclose");
230         LoadGpuSym1(readData, "GPUreadData");
231         LoadGpuSym1(readDataMem, "GPUreadDataMem");
232         LoadGpuSym1(readStatus, "GPUreadStatus");
233         LoadGpuSym1(writeData, "GPUwriteData");
234         LoadGpuSym1(writeDataMem, "GPUwriteDataMem");
235         LoadGpuSym1(writeStatus, "GPUwriteStatus");
236         LoadGpuSym1(dmaChain, "GPUdmaChain");
237         LoadGpuSym1(updateLace, "GPUupdateLace");
238         LoadGpuSym0(keypressed, "GPUkeypressed");
239         LoadGpuSym0(displayText, "GPUdisplayText");
240         LoadGpuSym0(makeSnapshot, "GPUmakeSnapshot");
241         LoadGpuSym1(freeze, "GPUfreeze");
242         LoadGpuSym0(getScreenPic, "GPUgetScreenPic");
243         LoadGpuSym0(showScreenPic, "GPUshowScreenPic");
244         LoadGpuSym0(clearDynarec, "GPUclearDynarec");
245     LoadGpuSym0(vBlank, "GPUvBlank");
246         LoadGpuSym0(configure, "GPUconfigure");
247         LoadGpuSym0(test, "GPUtest");
248         LoadGpuSym0(about, "GPUabout");
249
250         return 0;
251 }
252
253 void *hCDRDriver = NULL;
254
255 long CALLBACK CDR__play(unsigned char *sector) { return 0; }
256 long CALLBACK CDR__stop(void) { return 0; }
257
258 long CALLBACK CDR__getStatus(struct CdrStat *stat) {
259         if (cdOpenCaseTime < 0 || cdOpenCaseTime > (s64)time(NULL))
260                 stat->Status = 0x10;
261         else
262                 stat->Status = 0;
263
264         return 0;
265 }
266
267 char* CALLBACK CDR__getDriveLetter(void) { return NULL; }
268 long CALLBACK CDR__configure(void) { return 0; }
269 long CALLBACK CDR__test(void) { return 0; }
270 void CALLBACK CDR__about(void) {}
271 long CALLBACK CDR__setfilename(char*filename) { return 0; }
272
273 #define LoadCdrSym1(dest, name) \
274         LoadSym(CDR_##dest, CDR##dest, name, TRUE);
275
276 #define LoadCdrSym0(dest, name) \
277         LoadSym(CDR_##dest, CDR##dest, name, FALSE); \
278         if (CDR_##dest == NULL) CDR_##dest = (CDR##dest) CDR__##dest;
279
280 #define LoadCdrSymN(dest, name) \
281         LoadSym(CDR_##dest, CDR##dest, name, FALSE);
282
283 static int LoadCDRplugin(const char *CDRdll) {
284         void *drv;
285
286         if (CDRdll == NULL) {
287                 cdrIsoInit();
288                 return 0;
289         }
290
291         hCDRDriver = SysLoadLibrary(CDRdll);
292         if (hCDRDriver == NULL) {
293                 CDR_configure = NULL;
294                 SysMessage (_("Could not load CD-ROM plugin %s!"), CDRdll);  return -1;
295         }
296         drv = hCDRDriver;
297         LoadCdrSym1(init, "CDRinit");
298         LoadCdrSym1(shutdown, "CDRshutdown");
299         LoadCdrSym1(open, "CDRopen");
300         LoadCdrSym1(close, "CDRclose");
301         LoadCdrSym1(getTN, "CDRgetTN");
302         LoadCdrSym1(getTD, "CDRgetTD");
303         LoadCdrSym1(readTrack, "CDRreadTrack");
304         LoadCdrSym1(getBuffer, "CDRgetBuffer");
305         LoadCdrSym1(getBufferSub, "CDRgetBufferSub");
306         LoadCdrSym0(play, "CDRplay");
307         LoadCdrSym0(stop, "CDRstop");
308         LoadCdrSym0(getStatus, "CDRgetStatus");
309         LoadCdrSym0(getDriveLetter, "CDRgetDriveLetter");
310         LoadCdrSym0(configure, "CDRconfigure");
311         LoadCdrSym0(test, "CDRtest");
312         LoadCdrSym0(about, "CDRabout");
313         LoadCdrSym0(setfilename, "CDRsetfilename");
314         LoadCdrSymN(readCDDA, "CDRreadCDDA");
315         LoadCdrSymN(getTE, "CDRgetTE");
316
317         return 0;
318 }
319
320 void *hSPUDriver = NULL;
321
322 long CALLBACK SPU__configure(void) { return 0; }
323 void CALLBACK SPU__about(void) {}
324 long CALLBACK SPU__test(void) { return 0; }
325 void CALLBACK SPU__registerScheduleCb(void (CALLBACK *cb)(unsigned int)) {}
326
327 #define LoadSpuSym1(dest, name) \
328         LoadSym(SPU_##dest, SPU##dest, name, TRUE);
329
330 #define LoadSpuSym0(dest, name) \
331         LoadSym(SPU_##dest, SPU##dest, name, FALSE); \
332         if (SPU_##dest == NULL) SPU_##dest = (SPU##dest) SPU__##dest;
333
334 #define LoadSpuSymN(dest, name) \
335         LoadSym(SPU_##dest, SPU##dest, name, FALSE);
336
337 static int LoadSPUplugin(const char *SPUdll) {
338         void *drv;
339
340         hSPUDriver = SysLoadLibrary(SPUdll);
341         if (hSPUDriver == NULL) {
342                 SPU_configure = NULL;
343                 SysMessage (_("Could not load SPU plugin %s!"), SPUdll); return -1;
344         }
345         drv = hSPUDriver;
346         LoadSpuSym1(init, "SPUinit");
347         LoadSpuSym1(shutdown, "SPUshutdown");
348         LoadSpuSym1(open, "SPUopen");
349         LoadSpuSym1(close, "SPUclose");
350         LoadSpuSym0(configure, "SPUconfigure");
351         LoadSpuSym0(about, "SPUabout");
352         LoadSpuSym0(test, "SPUtest");
353         LoadSpuSym1(writeRegister, "SPUwriteRegister");
354         LoadSpuSym1(readRegister, "SPUreadRegister");
355         LoadSpuSym1(writeDMA, "SPUwriteDMA");
356         LoadSpuSym1(readDMA, "SPUreadDMA");
357         LoadSpuSym1(writeDMAMem, "SPUwriteDMAMem");
358         LoadSpuSym1(readDMAMem, "SPUreadDMAMem");
359         LoadSpuSym1(playADPCMchannel, "SPUplayADPCMchannel");
360         LoadSpuSym1(freeze, "SPUfreeze");
361         LoadSpuSym1(registerCallback, "SPUregisterCallback");
362         LoadSpuSym0(registerScheduleCb, "SPUregisterScheduleCb");
363         LoadSpuSymN(async, "SPUasync");
364         LoadSpuSymN(playCDDAchannel, "SPUplayCDDAchannel");
365
366         return 0;
367 }
368
369 void *hPAD1Driver = NULL;
370 void *hPAD2Driver = NULL;
371
372 static int multitap1 = -1;
373 static int multitap2 = -1;
374 //Pad information, keystate, mode, config mode, vibration
375 static PadDataS pad[8];
376
377 static int reqPos, respSize, req;
378 static int ledStateReq44[8];
379
380 static unsigned char buf[256];
381 static unsigned char bufMulti[34] = { 0x80, 0x5a,
382                                                                         0x41, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
383                                                                         0x41, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
384                                                                         0x41, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
385                                                                         0x41, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
386
387 unsigned char stdpar[8] = { 0x41, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
388 unsigned char multitappar[34] = { 0x80, 0x5a,
389                                                                         0x41, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
390                                                                         0x41, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
391                                                                         0x41, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
392                                                                         0x41, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
393
394 //response for request 44, 45, 46, 47, 4C, 4D
395 static unsigned char resp45[8]    = {0xF3, 0x5A, 0x01, 0x02, 0x00, 0x02, 0x01, 0x00};
396 static unsigned char resp46_00[8] = {0xF3, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A};
397 static unsigned char resp46_01[8] = {0xF3, 0x5A, 0x00, 0x00, 0x01, 0x01, 0x01, 0x14};
398 static unsigned char resp47[8]    = {0xF3, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00};
399 static unsigned char resp4C_00[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00};
400 static unsigned char resp4C_01[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00};
401 static unsigned char resp4D[8]    = {0xF3, 0x5A, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF};
402
403 //fixed reponse of request number 41, 48, 49, 4A, 4B, 4E, 4F
404 static unsigned char resp40[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
405 static unsigned char resp41[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
406 static unsigned char resp43[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
407 static unsigned char resp44[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
408 static unsigned char resp49[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
409 static unsigned char resp4A[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
410 static unsigned char resp4B[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
411 static unsigned char resp4E[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
412 static unsigned char resp4F[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
413
414 // Resquest of psx core
415 enum {
416         // REQUEST
417         // first call of this request for the pad, the pad is configured as an digital pad.
418         // 0x0X, 0x42, 0x0Y, 0xZZ, 0xAA, 0x00, 0x00, 0x00, 0x00
419         // X pad number (used for the multitap, first request response 0x00, 0x80, 0x5A, (8 bytes pad A), (8 bytes pad B), (8 bytes pad C), (8 bytes pad D)
420         // Y if 1 : psx request the full length response for the multitap, 3 bytes header and 4 block of 8 bytes per pad
421         // Y if 0 : psx request a pad key state
422         // ZZ rumble small motor 00-> OFF, 01 -> ON
423         // AA rumble large motor speed 0x00 -> 0xFF
424         // RESPONSE
425         // header 3 Bytes
426         // 0x00
427         // PadId -> 0x41 for digital pas, 0x73 for analog pad
428         // 0x5A mode has not change (no press on analog button on the center of pad), 0x00 the analog button have been pressed and the mode switch
429         // 6 Bytes for keystates
430         CMD_READ_DATA_AND_VIBRATE = 0x42,
431
432         // REQUEST
433         // Header
434         // 0x0N, 0x43, 0x00, XX, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
435         // XX = 00 -> Normal mode : Seconde bytes of response = padId
436         // XX = 01 -> Configuration mode : Seconde bytes of response = 0xF3
437         // RESPONSE
438         // enter in config mode example :
439         // req : 01 43 00 01 00 00 00 00 00 00
440         // res : 00 41 5A buttons state, analog states
441         // exit config mode :
442         // req : 01 43 00 00 00 00 00 00 00 00
443         // res : 00 F3 5A buttons state, analog states
444         CMD_CONFIG_MODE = 0x43,
445
446         // Set led State
447         // REQUEST
448         // 0x0N, 0x44, 0x00, VAL, SEL, 0x00, 0x00, 0x00, 0x00
449         // If sel = 2 then
450         // VAL = 00 -> OFF
451         // VAL = 01 -> ON
452         // RESPONSE
453         // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
454         CMD_SET_MODE_AND_LOCK = 0x44,
455
456         // Get Analog Led state
457         // REQUEST
458         // 0x0N, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
459         // RESPONSE
460         // 0x00, 0xF3, 0x5A, 0x01, 0x02, VAL, 0x02, 0x01, 0x00
461         // VAL = 00 Led OFF
462         // VAL = 01 Led ON
463         CMD_QUERY_MODEL_AND_MODE = 0x45,
464
465         //Get Variable A
466         // REQUEST
467         // 0x0N, 0x46, 0x00, 0xXX, 0x00, 0x00, 0x00, 0x00, 0x00
468         // RESPONSE
469         // XX=00
470         // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A
471         // XX=01
472         // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x01, 0x01, 0x01, 0x14
473         CMD_QUERY_ACT = 0x46,
474
475         // REQUEST
476         // 0x0N, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
477         // RESPONSE
478         // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00
479         CMD_QUERY_COMB = 0x47,
480
481         // REQUEST
482         // 0x0N, 0x4C, 0x00, 0xXX, 0x00, 0x00, 0x00, 0x00, 0x00
483         // RESPONSE
484         // XX = 0
485         // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00
486         // XX = 1
487         // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00
488         CMD_QUERY_MODE = 0x4C,
489
490         // REQUEST
491         // 0x0N, 0x4D, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
492         // RESPONSE
493         // 0x00, 0xF3, 0x5A, old value or
494         // AA = 01 unlock large motor (and swap VAL1 and VAL2)
495         // BB = 01 unlock large motor (default)
496         // CC, DD, EE, FF = all FF -> unlock small motor
497         //
498         // default repsonse for analog pad with 2 motor : 0x00 0xF3 0x5A 0x00 0x01 0xFF 0xFF 0xFF 0xFF
499         //
500         CMD_VIBRATION_TOGGLE = 0x4D,
501         REQ40 = 0x40,
502         REQ41 = 0x41,
503         REQ49 = 0x49,
504         REQ4A = 0x4A,
505         REQ4B = 0x4B,
506         REQ4E = 0x4E,
507         REQ4F = 0x4F
508 };
509
510 //NO MULTITAP
511
512 static void initBufForRequest(int padIndex, char value) {
513         switch (value) {
514                 //Pad keystate already in buffer
515                 //case CMD_READ_DATA_AND_VIBRATE :
516                 //      break;
517                 case CMD_CONFIG_MODE :
518                         if (pad[padIndex].configMode == 1) {
519                                 memcpy(buf, resp43, 8);
520                         }
521                         //else, not in config mode, pad keystate return (already in the buffer)
522                         break;
523                 case CMD_SET_MODE_AND_LOCK :
524                         memcpy(buf, resp44, 8);
525                         break;
526                 case CMD_QUERY_MODEL_AND_MODE :
527                         memcpy(buf, resp45, 8);
528                         break;
529                 case CMD_QUERY_ACT :
530                         memcpy(buf, resp46_00, 8);
531                         break;
532                 case CMD_QUERY_COMB :
533                         memcpy(buf, resp47, 8);
534                         break;
535                 case CMD_QUERY_MODE :
536                         memcpy(buf, resp4C_00, 8);
537                         break;
538                 case CMD_VIBRATION_TOGGLE :
539                         memcpy(buf, resp4D, 8);
540                         break;
541                 case REQ40 :
542                         memcpy(buf, resp40, 8);
543                         break;
544                 case REQ41 :
545                         memcpy(buf, resp41, 8);
546                         break;
547                 case REQ49 :
548                         memcpy(buf, resp49, 8);
549                         break;
550                 case REQ4A :
551                         memcpy(buf, resp4A, 8);
552                         break;
553                 case REQ4B :
554                         memcpy(buf, resp4B, 8);
555                         break;
556                 case REQ4E :
557                         memcpy(buf, resp4E, 8);
558                         break;
559                 case REQ4F :
560                         memcpy(buf, resp4F, 8);
561                         break;
562         }
563 }
564
565 static void reqIndex2Treatment(int padIndex, char value) {
566         switch (value) {
567                 case CMD_CONFIG_MODE :
568                         //0x43
569                         if (value == 0) {
570                                 pad[padIndex].configMode = 0;
571                         } else {
572                                 pad[padIndex].configMode = 1;
573                         }
574                         break;
575                 case CMD_SET_MODE_AND_LOCK :
576                         //0x44 store the led state for change mode if the next value = 0x02
577                         //0x01 analog ON
578                         //0x00 analog OFF
579                         ledStateReq44[padIndex] = value;
580                         break;
581                 case CMD_QUERY_ACT :
582                         //0x46
583                         if (value == 1) {
584                                 memcpy(buf, resp46_01, 8);
585                         }
586                         break;
587                 case CMD_QUERY_MODE :
588                         if (value == 1) {
589                                 memcpy(buf, resp4C_01, 8);
590                         }
591                         break;
592                 case CMD_VIBRATION_TOGGLE :
593                         //0x4D
594                         memcpy(buf, resp4D, 8);
595                         break;
596                 case CMD_READ_DATA_AND_VIBRATE:
597                         //mem the vibration value for small motor;
598                         pad[padIndex].Vib[0] = value;
599                         break;
600         }
601 }
602
603 void vibrate(int padIndex) {
604         if (pad[padIndex].Vib[0] != pad[padIndex].VibF[0] || pad[padIndex].Vib[1] != pad[padIndex].VibF[1]) {
605                 //value is different update Value and call libretro for vibration
606                 pad[padIndex].VibF[0] = pad[padIndex].Vib[0];
607                 pad[padIndex].VibF[1] = pad[padIndex].Vib[1];
608                 plat_trigger_vibrate(padIndex, pad[padIndex].VibF[0], pad[padIndex].VibF[1]);
609                 //printf("vibration pad %i", padIndex);
610         }
611 }
612
613 //Build response for 0x42 request Pad in port
614 void _PADstartPoll(PadDataS *pad) {
615     switch (pad->controllerType) {
616         case PSE_PAD_TYPE_MOUSE:
617                         stdpar[0] = 0x12;
618             stdpar[2] = pad->buttonStatus & 0xff;
619             stdpar[3] = pad->buttonStatus >> 8;
620             stdpar[4] = pad->moveX;
621             stdpar[5] = pad->moveY;
622             memcpy(buf, stdpar, 6);
623             respSize = 6;
624             break;
625         case PSE_PAD_TYPE_NEGCON: // npc101/npc104(slph00001/slph00069)
626             stdpar[0] = 0x23;
627             stdpar[2] = pad->buttonStatus & 0xff;
628             stdpar[3] = pad->buttonStatus >> 8;
629             stdpar[4] = pad->rightJoyX;
630             stdpar[5] = pad->rightJoyY;
631             stdpar[6] = pad->leftJoyX;
632             stdpar[7] = pad->leftJoyY;
633             memcpy(buf, stdpar, 8);
634             respSize = 8;
635             break;
636         case PSE_PAD_TYPE_ANALOGPAD: // scph1150
637             stdpar[0] = 0x73;
638             stdpar[2] = pad->buttonStatus & 0xff;
639             stdpar[3] = pad->buttonStatus >> 8;
640             stdpar[4] = pad->rightJoyX;
641             stdpar[5] = pad->rightJoyY;
642             stdpar[6] = pad->leftJoyX;
643             stdpar[7] = pad->leftJoyY;
644             memcpy(buf, stdpar, 8);
645             respSize = 8;
646             break;
647         case PSE_PAD_TYPE_ANALOGJOY: // scph1110
648             stdpar[0] = 0x53;
649             stdpar[2] = pad->buttonStatus & 0xff;
650             stdpar[3] = pad->buttonStatus >> 8;
651             stdpar[4] = pad->rightJoyX;
652             stdpar[5] = pad->rightJoyY;
653             stdpar[6] = pad->leftJoyX;
654             stdpar[7] = pad->leftJoyY;
655             memcpy(buf, stdpar, 8);
656             respSize = 8;
657             break;
658         case PSE_PAD_TYPE_STANDARD:
659         default:
660                 stdpar[0] = 0x41;
661             stdpar[2] = pad->buttonStatus & 0xff;
662             stdpar[3] = pad->buttonStatus >> 8;
663             //avoid analog value in multitap mode if change pad type in game.
664             stdpar[4] = 0xff;
665             stdpar[5] = 0xff;
666             stdpar[6] = 0xff;
667             stdpar[7] = 0xff;
668                 memcpy(buf, stdpar, 8);
669                 respSize = 8;
670     }
671 }
672
673 //Build response for 0x42 request Multitap in port
674 //Response header for multitap : 0x80, 0x5A, (Pad information port 1-2A), (Pad information port 1-2B), (Pad information port 1-2C), (Pad information port 1-2D)
675 void _PADstartPollMultitap(PadDataS* padd) {
676         int i, offset;
677         for(i = 0; i < 4; i++) {
678                 offset = 2 + (i * 8);
679                 _PADstartPoll(&padd[i]);
680                 memcpy(multitappar+offset, stdpar, 8);
681         }
682         memcpy(bufMulti, multitappar, 34);
683         respSize = 34;
684 }
685
686 unsigned char _PADpoll(int port, unsigned char value) {
687         if (reqPos == 0) {
688                 //mem the request number
689                 req = value;
690                 //copy the default value of request response in buffer instead of the keystate
691                 initBufForRequest(port, value);
692         }
693
694         //if no new request the pad return 0xff, for signaling connected
695         if (reqPos >= respSize) return 0xff;
696
697         switch(reqPos) {
698                 case 2:
699                         reqIndex2Treatment(port, value);
700                 break;
701                 case 3:
702                         switch(req) {
703                                 case CMD_SET_MODE_AND_LOCK :
704                                         //change mode on pad
705                                 break;
706                                 case CMD_READ_DATA_AND_VIBRATE:
707                                 //mem the vibration value for Large motor;
708                                 pad[port].Vib[1] = value;
709                                 //vibration
710                                 vibrate(port);
711                                 break;
712                         }
713                 break;
714         }
715         return buf[reqPos++];
716 }
717
718 unsigned char _PADpollMultitap(int port, unsigned char value) {
719         if (reqPos >= respSize)
720                 return 0xff;
721
722         return bufMulti[reqPos++];
723 }
724
725 // refresh the button state on port 1.
726 // int pad is not needed.
727 unsigned char CALLBACK PAD1__startPoll(int pad) {
728         reqPos = 0;
729         // first call the pad provide if a multitap is connected between the psx and himself
730         if (multitap1 == -1) {
731                 PadDataS padd;
732                 padd.requestPadIndex = 0;
733                 PAD1_readPort1(&padd);
734                 multitap1 = padd.portMultitap;
735         }
736         // just one pad is on port 1 : NO MULTITAP
737         if (multitap1 == 0) {
738                 PadDataS padd;
739                 padd.requestPadIndex = 0;
740                 PAD1_readPort1(&padd);
741                 _PADstartPoll(&padd);
742         } else {
743                 // a multitap is plugged : refresh all pad.
744                 int i;
745                 PadDataS padd[4];
746                 for(i = 0; i < 4; i++) {
747                         padd[i].requestPadIndex = i;
748                         PAD1_readPort1(&padd[i]);
749                 }
750                 _PADstartPollMultitap(padd);
751         }
752         //printf("\npad 1 : ");
753         return 0x00;
754 }
755
756 unsigned char CALLBACK PAD1__poll(unsigned char value) {
757         char tmp;
758         if (multitap1 == 1) {
759                 tmp = _PADpollMultitap(0, value);
760         } else {
761                 tmp = _PADpoll(0, value);
762         }
763         //printf("%2x:%2x, ",value,tmp);
764         return tmp;
765
766 }
767
768 long CALLBACK PAD1__configure(void) { return 0; }
769 void CALLBACK PAD1__about(void) {}
770 long CALLBACK PAD1__test(void) { return 0; }
771 long CALLBACK PAD1__query(void) { return 3; }
772 long CALLBACK PAD1__keypressed() { return 0; }
773
774 #define LoadPad1Sym1(dest, name) \
775         LoadSym(PAD1_##dest, PAD##dest, name, TRUE);
776
777 #define LoadPad1SymN(dest, name) \
778         LoadSym(PAD1_##dest, PAD##dest, name, FALSE);
779
780 #define LoadPad1Sym0(dest, name) \
781         LoadSym(PAD1_##dest, PAD##dest, name, FALSE); \
782         if (PAD1_##dest == NULL) PAD1_##dest = (PAD##dest) PAD1__##dest;
783
784 static int LoadPAD1plugin(const char *PAD1dll) {
785         void *drv;
786
787         hPAD1Driver = SysLoadLibrary(PAD1dll);
788         if (hPAD1Driver == NULL) {
789                 PAD1_configure = NULL;
790                 SysMessage (_("Could not load Controller 1 plugin %s!"), PAD1dll); return -1;
791         }
792         drv = hPAD1Driver;
793         LoadPad1Sym1(init, "PADinit");
794         LoadPad1Sym1(shutdown, "PADshutdown");
795         LoadPad1Sym1(open, "PADopen");
796         LoadPad1Sym1(close, "PADclose");
797         LoadPad1Sym0(query, "PADquery");
798         LoadPad1Sym1(readPort1, "PADreadPort1");
799         LoadPad1Sym0(configure, "PADconfigure");
800         LoadPad1Sym0(test, "PADtest");
801         LoadPad1Sym0(about, "PADabout");
802         LoadPad1Sym0(keypressed, "PADkeypressed");
803         LoadPad1Sym0(startPoll, "PADstartPoll");
804         LoadPad1Sym0(poll, "PADpoll");
805         LoadPad1SymN(setSensitive, "PADsetSensitive");
806
807         return 0;
808 }
809
810 unsigned char CALLBACK PAD2__startPoll(int pad) {
811         int pad_index;
812
813         reqPos = 0;
814         if (multitap1 == 0 && (multitap2 == 0 || multitap2 == 2)) {
815                 pad_index = 1;
816         } else if(multitap1 == 1 && (multitap2 == 0 || multitap2 == 2)) {
817                 pad_index = 4;
818         } else {
819                 pad_index = 0;
820         }
821
822         //first call the pad provide if a multitap is connected between the psx and himself
823         if (multitap2 == -1) {
824                 PadDataS padd;
825                 padd.requestPadIndex = pad_index;
826                 PAD2_readPort2(&padd);
827                 multitap2 = padd.portMultitap;
828         }
829
830         // just one pad is on port 1 : NO MULTITAP
831         if (multitap2 == 0) {
832                 PadDataS padd;
833                 padd.requestPadIndex = pad_index;
834                 PAD2_readPort2(&padd);
835                 _PADstartPoll(&padd);
836         } else {
837                 // a multitap is plugged : refresh all pad.
838                 int i;
839                 PadDataS padd[4];
840                 for(i = 0; i < 4; i++) {
841                         padd[i].requestPadIndex = i+pad_index;
842                         PAD2_readPort2(&padd[i]);
843                 }
844                 _PADstartPollMultitap(padd);
845         }
846         //printf("\npad 2 : ");
847         return 0x00;
848 }
849
850 unsigned char CALLBACK PAD2__poll(unsigned char value) {
851         char tmp;
852         if (multitap2 == 2) {
853                 tmp = _PADpollMultitap(1, value);
854         } else {
855                 tmp = _PADpoll(1, value);
856         }
857         //printf("%2x:%2x, ",value,tmp);
858         return tmp;
859 }
860
861 long CALLBACK PAD2__configure(void) { return 0; }
862 void CALLBACK PAD2__about(void) {}
863 long CALLBACK PAD2__test(void) { return 0; }
864 long CALLBACK PAD2__query(void) { return PSE_PAD_USE_PORT1 | PSE_PAD_USE_PORT2; }
865 long CALLBACK PAD2__keypressed() { return 0; }
866
867 #define LoadPad2Sym1(dest, name) \
868         LoadSym(PAD2_##dest, PAD##dest, name, TRUE);
869
870 #define LoadPad2Sym0(dest, name) \
871         LoadSym(PAD2_##dest, PAD##dest, name, FALSE); \
872         if (PAD2_##dest == NULL) PAD2_##dest = (PAD##dest) PAD2__##dest;
873
874 #define LoadPad2SymN(dest, name) \
875         LoadSym(PAD2_##dest, PAD##dest, name, FALSE);
876
877 static int LoadPAD2plugin(const char *PAD2dll) {
878         void *drv;
879
880         hPAD2Driver = SysLoadLibrary(PAD2dll);
881         if (hPAD2Driver == NULL) {
882                 PAD2_configure = NULL;
883                 SysMessage (_("Could not load Controller 2 plugin %s!"), PAD2dll); return -1;
884         }
885         drv = hPAD2Driver;
886         LoadPad2Sym1(init, "PADinit");
887         LoadPad2Sym1(shutdown, "PADshutdown");
888         LoadPad2Sym1(open, "PADopen");
889         LoadPad2Sym1(close, "PADclose");
890         LoadPad2Sym0(query, "PADquery");
891         LoadPad2Sym1(readPort2, "PADreadPort2");
892         LoadPad2Sym0(configure, "PADconfigure");
893         LoadPad2Sym0(test, "PADtest");
894         LoadPad2Sym0(about, "PADabout");
895         LoadPad2Sym0(keypressed, "PADkeypressed");
896         LoadPad2Sym0(startPoll, "PADstartPoll");
897         LoadPad2Sym0(poll, "PADpoll");
898         LoadPad2SymN(setSensitive, "PADsetSensitive");
899
900         return 0;
901 }
902
903 void *hNETDriver = NULL;
904
905 void CALLBACK NET__setInfo(netInfo *info) {}
906 void CALLBACK NET__keypressed(int key) {}
907 long CALLBACK NET__configure(void) { return 0; }
908 long CALLBACK NET__test(void) { return 0; }
909 void CALLBACK NET__about(void) {}
910
911 #define LoadNetSym1(dest, name) \
912         LoadSym(NET_##dest, NET##dest, name, TRUE);
913
914 #define LoadNetSymN(dest, name) \
915         LoadSym(NET_##dest, NET##dest, name, FALSE);
916
917 #define LoadNetSym0(dest, name) \
918         LoadSym(NET_##dest, NET##dest, name, FALSE); \
919         if (NET_##dest == NULL) NET_##dest = (NET##dest) NET__##dest;
920
921 static int LoadNETplugin(const char *NETdll) {
922         void *drv;
923
924         hNETDriver = SysLoadLibrary(NETdll);
925         if (hNETDriver == NULL) {
926                 SysMessage (_("Could not load NetPlay plugin %s!"), NETdll); return -1;
927         }
928         drv = hNETDriver;
929         LoadNetSym1(init, "NETinit");
930         LoadNetSym1(shutdown, "NETshutdown");
931         LoadNetSym1(open, "NETopen");
932         LoadNetSym1(close, "NETclose");
933         LoadNetSymN(sendData, "NETsendData");
934         LoadNetSymN(recvData, "NETrecvData");
935         LoadNetSym1(sendPadData, "NETsendPadData");
936         LoadNetSym1(recvPadData, "NETrecvPadData");
937         LoadNetSym1(queryPlayer, "NETqueryPlayer");
938         LoadNetSym1(pause, "NETpause");
939         LoadNetSym1(resume, "NETresume");
940         LoadNetSym0(setInfo, "NETsetInfo");
941         LoadNetSym0(keypressed, "NETkeypressed");
942         LoadNetSym0(configure, "NETconfigure");
943         LoadNetSym0(test, "NETtest");
944         LoadNetSym0(about, "NETabout");
945
946         return 0;
947 }
948
949 #ifdef ENABLE_SIO1API
950
951 void *hSIO1Driver = NULL;
952
953 long CALLBACK SIO1__init(void) { return 0; }
954 long CALLBACK SIO1__shutdown(void) { return 0; }
955 long CALLBACK SIO1__open(void) { return 0; }
956 long CALLBACK SIO1__close(void) { return 0; }
957 long CALLBACK SIO1__configure(void) { return 0; }
958 long CALLBACK SIO1__test(void) { return 0; }
959 void CALLBACK SIO1__about(void) {}
960 void CALLBACK SIO1__pause(void) {}
961 void CALLBACK SIO1__resume(void) {}
962 long CALLBACK SIO1__keypressed(int key) { return 0; }
963 void CALLBACK SIO1__writeData8(unsigned char val) {}
964 void CALLBACK SIO1__writeData16(unsigned short val) {}
965 void CALLBACK SIO1__writeData32(unsigned long val) {}
966 void CALLBACK SIO1__writeStat16(unsigned short val) {}
967 void CALLBACK SIO1__writeStat32(unsigned long val) {}
968 void CALLBACK SIO1__writeMode16(unsigned short val) {}
969 void CALLBACK SIO1__writeMode32(unsigned long val) {}
970 void CALLBACK SIO1__writeCtrl16(unsigned short val) {}
971 void CALLBACK SIO1__writeCtrl32(unsigned long val) {}
972 void CALLBACK SIO1__writeBaud16(unsigned short val) {}
973 void CALLBACK SIO1__writeBaud32(unsigned long val) {}
974 unsigned char CALLBACK SIO1__readData8(void) { return 0; }
975 unsigned short CALLBACK SIO1__readData16(void) { return 0; }
976 unsigned long CALLBACK SIO1__readData32(void) { return 0; }
977 unsigned short CALLBACK SIO1__readStat16(void) { return 0; }
978 unsigned long CALLBACK SIO1__readStat32(void) { return 0; }
979 unsigned short CALLBACK SIO1__readMode16(void) { return 0; }
980 unsigned long CALLBACK SIO1__readMode32(void) { return 0; }
981 unsigned short CALLBACK SIO1__readCtrl16(void) { return 0; }
982 unsigned long CALLBACK SIO1__readCtrl32(void) { return 0; }
983 unsigned short CALLBACK SIO1__readBaud16(void) { return 0; }
984 unsigned long CALLBACK SIO1__readBaud32(void) { return 0; }
985 void CALLBACK SIO1__registerCallback(void (CALLBACK *callback)(void)) {};
986
987 void CALLBACK SIO1irq(void) {
988     psxHu32ref(0x1070) |= SWAPu32(0x100);
989 }
990
991 #define LoadSio1Sym1(dest, name) \
992     LoadSym(SIO1_##dest, SIO1##dest, name, TRUE);
993
994 #define LoadSio1SymN(dest, name) \
995     LoadSym(SIO1_##dest, SIO1##dest, name, FALSE);
996
997 #define LoadSio1Sym0(dest, name) \
998     LoadSym(SIO1_##dest, SIO1##dest, name, FALSE); \
999     if (SIO1_##dest == NULL) SIO1_##dest = (SIO1##dest) SIO1__##dest;
1000
1001 static int LoadSIO1plugin(const char *SIO1dll) {
1002     void *drv;
1003
1004     hSIO1Driver = SysLoadLibrary(SIO1dll);
1005     if (hSIO1Driver == NULL) {
1006         SysMessage (_("Could not load SIO1 plugin %s!"), SIO1dll); return -1;
1007     }
1008     drv = hSIO1Driver;
1009
1010     LoadSio1Sym0(init, "SIO1init");
1011     LoadSio1Sym0(shutdown, "SIO1shutdown");
1012     LoadSio1Sym0(open, "SIO1open");
1013     LoadSio1Sym0(close, "SIO1close");
1014     LoadSio1Sym0(pause, "SIO1pause");
1015     LoadSio1Sym0(resume, "SIO1resume");
1016     LoadSio1Sym0(keypressed, "SIO1keypressed");
1017     LoadSio1Sym0(configure, "SIO1configure");
1018     LoadSio1Sym0(test, "SIO1test");
1019     LoadSio1Sym0(about, "SIO1about");
1020     LoadSio1Sym0(writeData8, "SIO1writeData8");
1021     LoadSio1Sym0(writeData16, "SIO1writeData16");
1022     LoadSio1Sym0(writeData32, "SIO1writeData32");
1023     LoadSio1Sym0(writeStat16, "SIO1writeStat16");
1024     LoadSio1Sym0(writeStat32, "SIO1writeStat32");
1025     LoadSio1Sym0(writeMode16, "SIO1writeMode16");
1026     LoadSio1Sym0(writeMode32, "SIO1writeMode32");
1027     LoadSio1Sym0(writeCtrl16, "SIO1writeCtrl16");
1028     LoadSio1Sym0(writeCtrl32, "SIO1writeCtrl32");
1029     LoadSio1Sym0(writeBaud16, "SIO1writeBaud16");
1030     LoadSio1Sym0(writeBaud32, "SIO1writeBaud32");
1031     LoadSio1Sym0(readData16, "SIO1readData16");
1032     LoadSio1Sym0(readData32, "SIO1readData32");
1033     LoadSio1Sym0(readStat16, "SIO1readStat16");
1034     LoadSio1Sym0(readStat32, "SIO1readStat32");
1035     LoadSio1Sym0(readMode16, "SIO1readMode16");
1036     LoadSio1Sym0(readMode32, "SIO1readMode32");
1037     LoadSio1Sym0(readCtrl16, "SIO1readCtrl16");
1038     LoadSio1Sym0(readCtrl32, "SIO1readCtrl32");
1039     LoadSio1Sym0(readBaud16, "SIO1readBaud16");
1040     LoadSio1Sym0(readBaud32, "SIO1readBaud32");
1041     LoadSio1Sym0(registerCallback, "SIO1registerCallback");
1042
1043     return 0;
1044 }
1045
1046 #endif
1047
1048 void CALLBACK clearDynarec(void) {
1049         psxCpu->Reset();
1050 }
1051
1052 int LoadPlugins() {
1053         int ret;
1054         char Plugin[MAXPATHLEN];
1055
1056         ReleasePlugins();
1057         SysLibError();
1058
1059         if (UsingIso()) {
1060                 LoadCDRplugin(NULL);
1061         } else {
1062                 sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Cdr);
1063                 if (LoadCDRplugin(Plugin) == -1) return -1;
1064         }
1065
1066         sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Gpu);
1067         if (LoadGPUplugin(Plugin) == -1) return -1;
1068
1069         sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Spu);
1070         if (LoadSPUplugin(Plugin) == -1) return -1;
1071
1072         sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Pad1);
1073         if (LoadPAD1plugin(Plugin) == -1) return -1;
1074
1075         sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Pad2);
1076         if (LoadPAD2plugin(Plugin) == -1) return -1;
1077
1078         if (strcmp("Disabled", Config.Net) == 0 || strcmp("", Config.Net) == 0)
1079                 Config.UseNet = FALSE;
1080         else {
1081                 Config.UseNet = TRUE;
1082                 sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Net);
1083                 if (LoadNETplugin(Plugin) == -1) Config.UseNet = FALSE;
1084         }
1085
1086 #ifdef ENABLE_SIO1API
1087         sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Sio1);
1088         if (LoadSIO1plugin(Plugin) == -1) return -1;
1089 #endif
1090
1091         ret = CDR_init();
1092         if (ret < 0) { SysMessage (_("Error initializing CD-ROM plugin: %d"), ret); return -1; }
1093         ret = GPU_init();
1094         if (ret < 0) { SysMessage (_("Error initializing GPU plugin: %d"), ret); return -1; }
1095         ret = SPU_init();
1096         if (ret < 0) { SysMessage (_("Error initializing SPU plugin: %d"), ret); return -1; }
1097         ret = PAD1_init(1);
1098         if (ret < 0) { SysMessage (_("Error initializing Controller 1 plugin: %d"), ret); return -1; }
1099         ret = PAD2_init(2);
1100         if (ret < 0) { SysMessage (_("Error initializing Controller 2 plugin: %d"), ret); return -1; }
1101
1102         if (Config.UseNet) {
1103                 ret = NET_init();
1104                 if (ret < 0) { SysMessage (_("Error initializing NetPlay plugin: %d"), ret); return -1; }
1105         }
1106
1107 #ifdef ENABLE_SIO1API
1108         ret = SIO1_init();
1109         if (ret < 0) { SysMessage (_("Error initializing SIO1 plugin: %d"), ret); return -1; }
1110 #endif
1111
1112         SysPrintf(_("Plugins loaded.\n"));
1113         return 0;
1114 }
1115
1116 void ReleasePlugins() {
1117         if (Config.UseNet) {
1118                 int ret = NET_close();
1119                 if (ret < 0) Config.UseNet = FALSE;
1120         }
1121         NetOpened = FALSE;
1122
1123         if (hCDRDriver != NULL || cdrIsoActive()) CDR_shutdown();
1124         if (hGPUDriver != NULL) GPU_shutdown();
1125         if (hSPUDriver != NULL) SPU_shutdown();
1126         if (hPAD1Driver != NULL) PAD1_shutdown();
1127         if (hPAD2Driver != NULL) PAD2_shutdown();
1128
1129         if (Config.UseNet && hNETDriver != NULL) NET_shutdown();
1130
1131         if (hCDRDriver != NULL) SysCloseLibrary(hCDRDriver); hCDRDriver = NULL;
1132         if (hGPUDriver != NULL) SysCloseLibrary(hGPUDriver); hGPUDriver = NULL;
1133         if (hSPUDriver != NULL) SysCloseLibrary(hSPUDriver); hSPUDriver = NULL;
1134         if (hPAD1Driver != NULL) SysCloseLibrary(hPAD1Driver); hPAD1Driver = NULL;
1135         if (hPAD2Driver != NULL) SysCloseLibrary(hPAD2Driver); hPAD2Driver = NULL;
1136
1137         if (Config.UseNet && hNETDriver != NULL) {
1138                 SysCloseLibrary(hNETDriver); hNETDriver = NULL;
1139         }
1140
1141 #ifdef ENABLE_SIO1API
1142         if (hSIO1Driver != NULL) {
1143                 SIO1_shutdown();
1144                 SysCloseLibrary(hSIO1Driver);
1145                 hSIO1Driver = NULL;
1146         }
1147 #endif
1148 }
1149
1150 // for CD swap
1151 int ReloadCdromPlugin()
1152 {
1153         if (hCDRDriver != NULL || cdrIsoActive()) CDR_shutdown();
1154         if (hCDRDriver != NULL) SysCloseLibrary(hCDRDriver); hCDRDriver = NULL;
1155
1156         if (UsingIso()) {
1157                 LoadCDRplugin(NULL);
1158         } else {
1159                 char Plugin[MAXPATHLEN];
1160                 sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Cdr);
1161                 if (LoadCDRplugin(Plugin) == -1) return -1;
1162         }
1163
1164         return CDR_init();
1165 }
1166
1167 void SetIsoFile(const char *filename) {
1168         if (filename == NULL) {
1169                 IsoFile[0] = '\0';
1170                 return;
1171         }
1172         strncpy(IsoFile, filename, MAXPATHLEN);
1173 }
1174
1175 const char *GetIsoFile(void) {
1176         return IsoFile;
1177 }
1178
1179 boolean UsingIso(void) {
1180         return (IsoFile[0] != '\0');
1181 }
1182
1183 void SetCdOpenCaseTime(s64 time) {
1184         cdOpenCaseTime = time;
1185 }