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