Adding Guncon support for mouse based lightguns
[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
511
512
513 //NO MULTITAP
514
515 void initBufForRequest(int padIndex, char value){
516         switch (value){
517                 //Pad keystate already in buffer
518                 //case CMD_READ_DATA_AND_VIBRATE :
519                 //      break;
520                 case CMD_CONFIG_MODE :
521                         if (pad[padIndex].configMode == 1) {
522                                 memcpy(buf, resp43, 8);
523                                 break;
524                         }
525                         //else, not in config mode, pad keystate return (already in the buffer)
526                         break;
527                 case CMD_SET_MODE_AND_LOCK :
528                         memcpy(buf, resp44, 8);
529                         break;
530                 case CMD_QUERY_MODEL_AND_MODE :
531                         memcpy(buf, resp45, 8);
532                         break;
533                 case CMD_QUERY_ACT :
534                         memcpy(buf, resp46_00, 8);
535                         break;
536                 case CMD_QUERY_COMB :
537                         memcpy(buf, resp47, 8);
538                         break;
539                 case CMD_QUERY_MODE :
540                         memcpy(buf, resp4C_00, 8);
541                         break;
542                 case CMD_VIBRATION_TOGGLE :
543                         memcpy(buf, resp4D, 8);
544                         break;
545                 case REQ40 :
546                         memcpy(buf, resp40, 8);
547                         break;
548                 case REQ41 :
549                         memcpy(buf, resp41, 8);
550                         break;
551                 case REQ49 :
552                         memcpy(buf, resp49, 8);
553                         break;
554                 case REQ4A :
555                         memcpy(buf, resp4A, 8);
556                         break;
557                 case REQ4B :
558                         memcpy(buf, resp4B, 8);
559                         break;
560                 case REQ4E :
561                         memcpy(buf, resp4E, 8);
562                         break;
563                 case REQ4F :
564                         memcpy(buf, resp4F, 8);
565                         break;
566         }
567 }
568
569
570
571
572 void reqIndex2Treatment(int padIndex, char value){
573         switch (req){
574                 case CMD_CONFIG_MODE :
575                         //0x43
576                         if (value == 0) {
577                                 pad[padIndex].configMode = 0;
578                         } else {
579                                 pad[padIndex].configMode = 1;
580                         }
581                         break;
582                 case CMD_SET_MODE_AND_LOCK :
583                         //0x44 store the led state for change mode if the next value = 0x02
584                         //0x01 analog ON
585                         //0x00 analog OFF
586                         ledStateReq44[padIndex] = value;
587                         break;
588                 case CMD_QUERY_ACT :
589                         //0x46
590                         if (value == 1) {
591                                 memcpy(buf, resp46_01, 8);
592                         }
593                         break;
594                 case CMD_QUERY_MODE :
595                         if (value == 1) {
596                                 memcpy(buf, resp4C_01, 8);
597                         }
598                         break;
599                 case CMD_VIBRATION_TOGGLE :
600                         //0x4D
601                         memcpy(buf, resp4D, 8);
602                         break;
603                 case CMD_READ_DATA_AND_VIBRATE:
604                         //mem the vibration value for small motor;
605                         pad[padIndex].Vib[0] = value;
606                         break;
607         }
608 }
609         
610 void vibrate(int padIndex){
611         if (pad[padIndex].Vib[0] != pad[padIndex].VibF[0] || pad[padIndex].Vib[1] != pad[padIndex].VibF[1]) {
612                 //value is different update Value and call libretro for vibration
613                 pad[padIndex].VibF[0] = pad[padIndex].Vib[0];
614                 pad[padIndex].VibF[1] = pad[padIndex].Vib[1];
615                 plat_trigger_vibrate(padIndex, pad[padIndex].VibF[0], pad[padIndex].VibF[1]);
616                 //printf("vibration pad %i", padIndex);
617         }
618 }
619
620
621
622
623 //Build response for 0x42 request Pad in port
624 void _PADstartPoll(PadDataS *pad) {
625     switch (pad->controllerType) {
626         case PSE_PAD_TYPE_MOUSE:
627                         stdpar[0] = 0x12;
628             stdpar[2] = pad->buttonStatus & 0xff;
629             stdpar[3] = pad->buttonStatus >> 8;
630             stdpar[4] = pad->moveX;
631             stdpar[5] = pad->moveY;
632             memcpy(buf, stdpar, 6);
633             respSize = 6;
634             break;
635         case PSE_PAD_TYPE_NEGCON: // npc101/npc104(slph00001/slph00069)
636             stdpar[0] = 0x23;
637             stdpar[2] = pad->buttonStatus & 0xff;
638             stdpar[3] = pad->buttonStatus >> 8;
639             stdpar[4] = pad->rightJoyX;
640             stdpar[5] = pad->rightJoyY;
641             stdpar[6] = pad->leftJoyX;
642             stdpar[7] = pad->leftJoyY;
643             memcpy(buf, stdpar, 8);
644             respSize = 8;
645             break;
646         case PSE_PAD_TYPE_GUNCON: // GUNCON - gun controller SLPH-00034 from Namco
647             stdpar[0] = 0x63;
648             stdpar[1] = 0x5a;
649             stdpar[2] = pad->buttonStatus & 0xff;
650             stdpar[3] = pad->buttonStatus >> 8;
651                     
652             //This code assumes an X resolution of 256 and a Y resolution of 240
653             int xres = 256;
654             int yres = 240;
655             
656             //The code wants an input range for x and y of 0-1023 we passed in -32767 -> 32767 
657             int absX = (pad->absoluteX / 64) + 512;
658             int absY = (pad->absoluteY / 64) + 512;
659                        
660             //Keep within limits
661             if (absX > 1023) absX = 1023;
662             if (absX < 0) absX = 0;
663             if (absY > 1023) absY = 1023;
664             if (absY < 0) absY = 0;
665                     
666             stdpar[4] = 0x5a - (xres - 256) / 3 + (((xres - 256) / 3 + 356) * absX >> 10);      
667             stdpar[5] = (0x5a - (xres - 256) / 3 + (((xres - 256) / 3 + 356) * absX >> 10)) >> 8;
668             stdpar[6] = 0x20 + (yres * absY >> 10);
669             stdpar[7] = (0x20 + (yres * absY >> 10)) >> 8;
670                     
671             //Offscreen - Point at the side of the screen so PSX thinks you are pointing offscreen
672             //Required as a mouse can't be offscreen
673             //Coordinates X=0001h, Y=000Ah indicates "no light"
674             //This will mean you cannot shoot the very each of the screen
675             //ToDo read offscreen range from settings if useful to change
676             int OffscreenRange = 2;
677             if (absX < (OffscreenRange) || absX > (1023 - OffscreenRange) || absY < (OffscreenRange) || absY > (1023 - OffscreenRange))
678             {
679                 stdpar[4] = 0x01;
680                 stdpar[5] = 0x00;
681                 stdpar[6] = 0x0A;
682                 stdpar[7] = 0x00;           
683             }
684                     
685             memcpy(buf, stdpar, 8);
686             respSize = 8;
687             break;
688         case PSE_PAD_TYPE_ANALOGPAD: // scph1150
689             stdpar[0] = 0x73;
690             stdpar[2] = pad->buttonStatus & 0xff;
691             stdpar[3] = pad->buttonStatus >> 8;
692             stdpar[4] = pad->rightJoyX;
693             stdpar[5] = pad->rightJoyY;
694             stdpar[6] = pad->leftJoyX;
695             stdpar[7] = pad->leftJoyY;
696             memcpy(buf, stdpar, 8);
697             respSize = 8;
698             break;
699         case PSE_PAD_TYPE_ANALOGJOY: // scph1110
700             stdpar[0] = 0x53;
701             stdpar[2] = pad->buttonStatus & 0xff;
702             stdpar[3] = pad->buttonStatus >> 8;
703             stdpar[4] = pad->rightJoyX;
704             stdpar[5] = pad->rightJoyY;
705             stdpar[6] = pad->leftJoyX;
706             stdpar[7] = pad->leftJoyY;
707             memcpy(buf, stdpar, 8);
708             respSize = 8;
709             break;
710         case PSE_PAD_TYPE_STANDARD:
711         default:
712                 stdpar[0] = 0x41;
713             stdpar[2] = pad->buttonStatus & 0xff;
714             stdpar[3] = pad->buttonStatus >> 8;
715             //avoid analog value in multitap mode if change pad type in game.
716             stdpar[4] = 0xff;
717             stdpar[5] = 0xff;
718             stdpar[6] = 0xff;
719             stdpar[7] = 0xff;
720                 memcpy(buf, stdpar, 8);
721                 respSize = 8;
722     }
723 }
724
725
726 //Build response for 0x42 request Multitap in port
727 //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)
728 void _PADstartPollMultitap(PadDataS* padd) {
729     int i, offset;
730     for(i = 0; i < 4; i++) {
731         offset = 2 + (i * 8);
732         _PADstartPoll(&padd[i]);
733         memcpy(multitappar+offset, stdpar, 8);
734     }
735     memcpy(bufMulti, multitappar, 34);
736     respSize = 34;
737 }
738
739
740 unsigned char _PADpoll(int port, unsigned char value) {
741         if (reqPos == 0) {
742                 //mem the request number
743                 req = value;
744                 //copy the default value of request response in buffer instead of the keystate
745                 initBufForRequest(port, value);
746         }
747         
748         //if no new request the pad return 0xff, for signaling connected
749         if (reqPos >= respSize) return 0xff;
750         
751         switch(reqPos){
752                 case 2:
753                         reqIndex2Treatment(port, value);
754                 break;
755                 case 3:
756                         switch(req) {
757                                 case CMD_SET_MODE_AND_LOCK :
758                                         //change mode on pad
759                                 break;
760                                 case CMD_READ_DATA_AND_VIBRATE:
761                                 //mem the vibration value for Large motor;
762                                 pad[port].Vib[1] = value;
763                                 //vibration
764                                 vibrate(port);
765                                 break;
766                         }
767                 break;
768         }
769         return buf[reqPos++];
770 }
771
772
773 unsigned char _PADpollMultitap(int port, unsigned char value) {
774         if (reqPos >= respSize) return 0xff;
775         return bufMulti[reqPos++];
776 }
777
778
779 // refresh the button state on port 1.
780 // int pad is not needed.
781 unsigned char CALLBACK PAD1__startPoll(int pad) {
782         reqPos = 0;
783         // first call the pad provide if a multitap is connected between the psx and himself
784         if (multitap1 == -1) {
785                 PadDataS padd;
786                 padd.requestPadIndex = 0;
787                 PAD1_readPort1(&padd);
788                 multitap1 = padd.portMultitap;
789         }
790         // just one pad is on port 1 : NO MULTITAP
791         if (multitap1 == 0) {
792                 PadDataS padd;
793                 padd.requestPadIndex = 0;
794                 PAD1_readPort1(&padd);
795                 _PADstartPoll(&padd);
796         } else {
797                 // a multitap is plugged : refresh all pad.
798                 int i;
799                 PadDataS padd[4];
800                 for(i = 0; i < 4; i++) {
801                         padd[i].requestPadIndex = i;
802                         PAD1_readPort1(&padd[i]);
803                 }
804                 _PADstartPollMultitap(padd);
805         }
806         //printf("\npad 1 : ");
807         return 0x00;
808 }
809
810 unsigned char CALLBACK PAD1__poll(unsigned char value) {
811         char tmp;
812         if (multitap1 == 1) {
813                 tmp = _PADpollMultitap(0, value);
814         } else {
815                 tmp = _PADpoll(0, value);
816         }
817         //printf("%2x:%2x, ",value,tmp);
818         return tmp;
819         
820 }
821
822
823 long CALLBACK PAD1__configure(void) { return 0; }
824 void CALLBACK PAD1__about(void) {}
825 long CALLBACK PAD1__test(void) { return 0; }
826 long CALLBACK PAD1__query(void) { return 3; }
827 long CALLBACK PAD1__keypressed() { return 0; }
828
829 #define LoadPad1Sym1(dest, name) \
830         LoadSym(PAD1_##dest, PAD##dest, name, TRUE);
831
832 #define LoadPad1SymN(dest, name) \
833         LoadSym(PAD1_##dest, PAD##dest, name, FALSE);
834
835 #define LoadPad1Sym0(dest, name) \
836         LoadSym(PAD1_##dest, PAD##dest, name, FALSE); \
837         if (PAD1_##dest == NULL) PAD1_##dest = (PAD##dest) PAD1__##dest;
838
839 static int LoadPAD1plugin(const char *PAD1dll) {
840         void *drv;
841
842         hPAD1Driver = SysLoadLibrary(PAD1dll);
843         if (hPAD1Driver == NULL) {
844                 PAD1_configure = NULL;
845                 SysMessage (_("Could not load Controller 1 plugin %s!"), PAD1dll); return -1;
846         }
847         drv = hPAD1Driver;
848         LoadPad1Sym1(init, "PADinit");
849         LoadPad1Sym1(shutdown, "PADshutdown");
850         LoadPad1Sym1(open, "PADopen");
851         LoadPad1Sym1(close, "PADclose");
852         LoadPad1Sym0(query, "PADquery");
853         LoadPad1Sym1(readPort1, "PADreadPort1");
854         LoadPad1Sym0(configure, "PADconfigure");
855         LoadPad1Sym0(test, "PADtest");
856         LoadPad1Sym0(about, "PADabout");
857         LoadPad1Sym0(keypressed, "PADkeypressed");
858         LoadPad1Sym0(startPoll, "PADstartPoll");
859         LoadPad1Sym0(poll, "PADpoll");
860         LoadPad1SymN(setSensitive, "PADsetSensitive");
861
862         return 0;
863 }
864
865 unsigned char CALLBACK PAD2__startPoll(int pad) {
866         int pad_index;
867
868         reqPos = 0;
869         if (multitap1 == 0 && (multitap2 == 0 || multitap2 == 2)) {
870                 pad_index = 1;
871         } else if(multitap1 == 1 && (multitap2 == 0 || multitap2 == 2)) {
872                 pad_index = 4;
873         } else {
874                 pad_index = 0;
875         }
876
877         //first call the pad provide if a multitap is connected between the psx and himself
878         if (multitap2 == -1) {
879                 PadDataS padd;
880                 padd.requestPadIndex = pad_index;
881                 PAD2_readPort2(&padd);
882                 multitap2 = padd.portMultitap;
883         }
884         
885         // just one pad is on port 1 : NO MULTITAP
886         if (multitap2 == 0) {
887                 PadDataS padd;
888                 padd.requestPadIndex = pad_index;
889                 PAD2_readPort2(&padd);
890                 _PADstartPoll(&padd);
891         } else {
892                 // a multitap is plugged : refresh all pad.
893                 int i;
894                 PadDataS padd[4];
895                 for(i = 0; i < 4; i++) {
896                         padd[i].requestPadIndex = i+pad_index;
897                         PAD2_readPort2(&padd[i]);
898                 }
899                 _PADstartPollMultitap(padd);
900         }
901         //printf("\npad 2 : ");
902         return 0x00;
903 }
904
905 unsigned char CALLBACK PAD2__poll(unsigned char value) {
906         char tmp;
907         if (multitap2 == 2) {
908                 tmp = _PADpollMultitap(1, value);
909         } else {
910                 tmp = _PADpoll(1, value);
911         }
912         //printf("%2x:%2x, ",value,tmp);
913         return tmp;
914 }
915
916 long CALLBACK PAD2__configure(void) { return 0; }
917 void CALLBACK PAD2__about(void) {}
918 long CALLBACK PAD2__test(void) { return 0; }
919 long CALLBACK PAD2__query(void) { return PSE_PAD_USE_PORT1 | PSE_PAD_USE_PORT2; }
920 long CALLBACK PAD2__keypressed() { return 0; }
921
922 #define LoadPad2Sym1(dest, name) \
923         LoadSym(PAD2_##dest, PAD##dest, name, TRUE);
924
925 #define LoadPad2Sym0(dest, name) \
926         LoadSym(PAD2_##dest, PAD##dest, name, FALSE); \
927         if (PAD2_##dest == NULL) PAD2_##dest = (PAD##dest) PAD2__##dest;
928
929 #define LoadPad2SymN(dest, name) \
930         LoadSym(PAD2_##dest, PAD##dest, name, FALSE);
931
932 static int LoadPAD2plugin(const char *PAD2dll) {
933         void *drv;
934
935         hPAD2Driver = SysLoadLibrary(PAD2dll);
936         if (hPAD2Driver == NULL) {
937                 PAD2_configure = NULL;
938                 SysMessage (_("Could not load Controller 2 plugin %s!"), PAD2dll); return -1;
939         }
940         drv = hPAD2Driver;
941         LoadPad2Sym1(init, "PADinit");
942         LoadPad2Sym1(shutdown, "PADshutdown");
943         LoadPad2Sym1(open, "PADopen");
944         LoadPad2Sym1(close, "PADclose");
945         LoadPad2Sym0(query, "PADquery");
946         LoadPad2Sym1(readPort2, "PADreadPort2");
947         LoadPad2Sym0(configure, "PADconfigure");
948         LoadPad2Sym0(test, "PADtest");
949         LoadPad2Sym0(about, "PADabout");
950         LoadPad2Sym0(keypressed, "PADkeypressed");
951         LoadPad2Sym0(startPoll, "PADstartPoll");
952         LoadPad2Sym0(poll, "PADpoll");
953         LoadPad2SymN(setSensitive, "PADsetSensitive");
954
955         return 0;
956 }
957
958 void *hNETDriver = NULL;
959
960 void CALLBACK NET__setInfo(netInfo *info) {}
961 void CALLBACK NET__keypressed(int key) {}
962 long CALLBACK NET__configure(void) { return 0; }
963 long CALLBACK NET__test(void) { return 0; }
964 void CALLBACK NET__about(void) {}
965
966 #define LoadNetSym1(dest, name) \
967         LoadSym(NET_##dest, NET##dest, name, TRUE);
968
969 #define LoadNetSymN(dest, name) \
970         LoadSym(NET_##dest, NET##dest, name, FALSE);
971
972 #define LoadNetSym0(dest, name) \
973         LoadSym(NET_##dest, NET##dest, name, FALSE); \
974         if (NET_##dest == NULL) NET_##dest = (NET##dest) NET__##dest;
975
976 static int LoadNETplugin(const char *NETdll) {
977         void *drv;
978
979         hNETDriver = SysLoadLibrary(NETdll);
980         if (hNETDriver == NULL) {
981                 SysMessage (_("Could not load NetPlay plugin %s!"), NETdll); return -1;
982         }
983         drv = hNETDriver;
984         LoadNetSym1(init, "NETinit");
985         LoadNetSym1(shutdown, "NETshutdown");
986         LoadNetSym1(open, "NETopen");
987         LoadNetSym1(close, "NETclose");
988         LoadNetSymN(sendData, "NETsendData");
989         LoadNetSymN(recvData, "NETrecvData");
990         LoadNetSym1(sendPadData, "NETsendPadData");
991         LoadNetSym1(recvPadData, "NETrecvPadData");
992         LoadNetSym1(queryPlayer, "NETqueryPlayer");
993         LoadNetSym1(pause, "NETpause");
994         LoadNetSym1(resume, "NETresume");
995         LoadNetSym0(setInfo, "NETsetInfo");
996         LoadNetSym0(keypressed, "NETkeypressed");
997         LoadNetSym0(configure, "NETconfigure");
998         LoadNetSym0(test, "NETtest");
999         LoadNetSym0(about, "NETabout");
1000
1001         return 0;
1002 }
1003
1004 #ifdef ENABLE_SIO1API
1005
1006 void *hSIO1Driver = NULL;
1007
1008 long CALLBACK SIO1__init(void) { return 0; }
1009 long CALLBACK SIO1__shutdown(void) { return 0; }
1010 long CALLBACK SIO1__open(void) { return 0; }
1011 long CALLBACK SIO1__close(void) { return 0; }
1012 long CALLBACK SIO1__configure(void) { return 0; }
1013 long CALLBACK SIO1__test(void) { return 0; }
1014 void CALLBACK SIO1__about(void) {}
1015 void CALLBACK SIO1__pause(void) {}
1016 void CALLBACK SIO1__resume(void) {}
1017 long CALLBACK SIO1__keypressed(int key) { return 0; }
1018 void CALLBACK SIO1__writeData8(unsigned char val) {}
1019 void CALLBACK SIO1__writeData16(unsigned short val) {}
1020 void CALLBACK SIO1__writeData32(unsigned long val) {}
1021 void CALLBACK SIO1__writeStat16(unsigned short val) {}
1022 void CALLBACK SIO1__writeStat32(unsigned long val) {}
1023 void CALLBACK SIO1__writeMode16(unsigned short val) {}
1024 void CALLBACK SIO1__writeMode32(unsigned long val) {}
1025 void CALLBACK SIO1__writeCtrl16(unsigned short val) {}
1026 void CALLBACK SIO1__writeCtrl32(unsigned long val) {}
1027 void CALLBACK SIO1__writeBaud16(unsigned short val) {}
1028 void CALLBACK SIO1__writeBaud32(unsigned long val) {}
1029 unsigned char CALLBACK SIO1__readData8(void) { return 0; }
1030 unsigned short CALLBACK SIO1__readData16(void) { return 0; }
1031 unsigned long CALLBACK SIO1__readData32(void) { return 0; }
1032 unsigned short CALLBACK SIO1__readStat16(void) { return 0; }
1033 unsigned long CALLBACK SIO1__readStat32(void) { return 0; }
1034 unsigned short CALLBACK SIO1__readMode16(void) { return 0; }
1035 unsigned long CALLBACK SIO1__readMode32(void) { return 0; }
1036 unsigned short CALLBACK SIO1__readCtrl16(void) { return 0; }
1037 unsigned long CALLBACK SIO1__readCtrl32(void) { return 0; }
1038 unsigned short CALLBACK SIO1__readBaud16(void) { return 0; }
1039 unsigned long CALLBACK SIO1__readBaud32(void) { return 0; }
1040 void CALLBACK SIO1__registerCallback(void (CALLBACK *callback)(void)) {};
1041
1042 void CALLBACK SIO1irq(void) {
1043     psxHu32ref(0x1070) |= SWAPu32(0x100);
1044 }
1045
1046 #define LoadSio1Sym1(dest, name) \
1047     LoadSym(SIO1_##dest, SIO1##dest, name, TRUE);
1048
1049 #define LoadSio1SymN(dest, name) \
1050     LoadSym(SIO1_##dest, SIO1##dest, name, FALSE);
1051
1052 #define LoadSio1Sym0(dest, name) \
1053     LoadSym(SIO1_##dest, SIO1##dest, name, FALSE); \
1054     if (SIO1_##dest == NULL) SIO1_##dest = (SIO1##dest) SIO1__##dest;
1055
1056 static int LoadSIO1plugin(const char *SIO1dll) {
1057     void *drv;
1058
1059     hSIO1Driver = SysLoadLibrary(SIO1dll);
1060     if (hSIO1Driver == NULL) {
1061         SysMessage (_("Could not load SIO1 plugin %s!"), SIO1dll); return -1;
1062     }
1063     drv = hSIO1Driver;
1064
1065     LoadSio1Sym0(init, "SIO1init");
1066     LoadSio1Sym0(shutdown, "SIO1shutdown");
1067     LoadSio1Sym0(open, "SIO1open");
1068     LoadSio1Sym0(close, "SIO1close");
1069     LoadSio1Sym0(pause, "SIO1pause");
1070     LoadSio1Sym0(resume, "SIO1resume");
1071     LoadSio1Sym0(keypressed, "SIO1keypressed");
1072     LoadSio1Sym0(configure, "SIO1configure");
1073     LoadSio1Sym0(test, "SIO1test");
1074     LoadSio1Sym0(about, "SIO1about");
1075     LoadSio1Sym0(writeData8, "SIO1writeData8");
1076     LoadSio1Sym0(writeData16, "SIO1writeData16");
1077     LoadSio1Sym0(writeData32, "SIO1writeData32");
1078     LoadSio1Sym0(writeStat16, "SIO1writeStat16");
1079     LoadSio1Sym0(writeStat32, "SIO1writeStat32");
1080     LoadSio1Sym0(writeMode16, "SIO1writeMode16");
1081     LoadSio1Sym0(writeMode32, "SIO1writeMode32");
1082     LoadSio1Sym0(writeCtrl16, "SIO1writeCtrl16");
1083     LoadSio1Sym0(writeCtrl32, "SIO1writeCtrl32");
1084     LoadSio1Sym0(writeBaud16, "SIO1writeBaud16");
1085     LoadSio1Sym0(writeBaud32, "SIO1writeBaud32");
1086     LoadSio1Sym0(readData16, "SIO1readData16");
1087     LoadSio1Sym0(readData32, "SIO1readData32");
1088     LoadSio1Sym0(readStat16, "SIO1readStat16");
1089     LoadSio1Sym0(readStat32, "SIO1readStat32");
1090     LoadSio1Sym0(readMode16, "SIO1readMode16");
1091     LoadSio1Sym0(readMode32, "SIO1readMode32");
1092     LoadSio1Sym0(readCtrl16, "SIO1readCtrl16");
1093     LoadSio1Sym0(readCtrl32, "SIO1readCtrl32");
1094     LoadSio1Sym0(readBaud16, "SIO1readBaud16");
1095     LoadSio1Sym0(readBaud32, "SIO1readBaud32");
1096     LoadSio1Sym0(registerCallback, "SIO1registerCallback");
1097
1098     return 0;
1099 }
1100
1101 #endif
1102
1103 void CALLBACK clearDynarec(void) {
1104         psxCpu->Reset();
1105 }
1106
1107 int LoadPlugins() {
1108         int ret;
1109         char Plugin[MAXPATHLEN * 2];
1110
1111         ReleasePlugins();
1112         SysLibError();
1113
1114         if (UsingIso()) {
1115                 LoadCDRplugin(NULL);
1116         } else {
1117                 sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Cdr);
1118                 if (LoadCDRplugin(Plugin) == -1) return -1;
1119         }
1120
1121         sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Gpu);
1122         if (LoadGPUplugin(Plugin) == -1) return -1;
1123
1124         sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Spu);
1125         if (LoadSPUplugin(Plugin) == -1) return -1;
1126
1127         sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Pad1);
1128         if (LoadPAD1plugin(Plugin) == -1) return -1;
1129
1130         sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Pad2);
1131         if (LoadPAD2plugin(Plugin) == -1) return -1;
1132
1133         if (strcmp("Disabled", Config.Net) == 0 || strcmp("", Config.Net) == 0)
1134                 Config.UseNet = FALSE;
1135         else {
1136                 Config.UseNet = TRUE;
1137                 sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Net);
1138                 if (LoadNETplugin(Plugin) == -1) Config.UseNet = FALSE;
1139         }
1140
1141 #ifdef ENABLE_SIO1API
1142         sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Sio1);
1143         if (LoadSIO1plugin(Plugin) == -1) return -1;
1144 #endif
1145
1146         ret = CDR_init();
1147         if (ret < 0) { SysMessage (_("Error initializing CD-ROM plugin: %d"), ret); return -1; }
1148         ret = GPU_init();
1149         if (ret < 0) { SysMessage (_("Error initializing GPU plugin: %d"), ret); return -1; }
1150         ret = SPU_init();
1151         if (ret < 0) { SysMessage (_("Error initializing SPU plugin: %d"), ret); return -1; }
1152         ret = PAD1_init(1);
1153         if (ret < 0) { SysMessage (_("Error initializing Controller 1 plugin: %d"), ret); return -1; }
1154         ret = PAD2_init(2);
1155         if (ret < 0) { SysMessage (_("Error initializing Controller 2 plugin: %d"), ret); return -1; }
1156
1157         if (Config.UseNet) {
1158                 ret = NET_init();
1159                 if (ret < 0) { SysMessage (_("Error initializing NetPlay plugin: %d"), ret); return -1; }
1160         }
1161
1162 #ifdef ENABLE_SIO1API
1163         ret = SIO1_init();
1164         if (ret < 0) { SysMessage (_("Error initializing SIO1 plugin: %d"), ret); return -1; }
1165 #endif
1166
1167         SysPrintf(_("Plugins loaded.\n"));
1168         return 0;
1169 }
1170
1171 void ReleasePlugins() {
1172         if (Config.UseNet) {
1173                 int ret = NET_close();
1174                 if (ret < 0) Config.UseNet = FALSE;
1175         }
1176         NetOpened = FALSE;
1177
1178         if (hCDRDriver != NULL || cdrIsoActive()) CDR_shutdown();
1179         if (hGPUDriver != NULL) GPU_shutdown();
1180         if (hSPUDriver != NULL) SPU_shutdown();
1181         if (hPAD1Driver != NULL) PAD1_shutdown();
1182         if (hPAD2Driver != NULL) PAD2_shutdown();
1183
1184         if (Config.UseNet && hNETDriver != NULL) NET_shutdown(); 
1185
1186         if (hCDRDriver != NULL) { SysCloseLibrary(hCDRDriver); hCDRDriver = NULL; }
1187         if (hGPUDriver != NULL) { SysCloseLibrary(hGPUDriver); hGPUDriver = NULL; }
1188         if (hSPUDriver != NULL) { SysCloseLibrary(hSPUDriver); hSPUDriver = NULL; }
1189         if (hPAD1Driver != NULL) { SysCloseLibrary(hPAD1Driver); hPAD1Driver = NULL; }
1190         if (hPAD2Driver != NULL) { SysCloseLibrary(hPAD2Driver); hPAD2Driver = NULL; }
1191
1192         if (Config.UseNet && hNETDriver != NULL) {
1193                 SysCloseLibrary(hNETDriver); hNETDriver = NULL;
1194         }
1195
1196 #ifdef ENABLE_SIO1API
1197         if (hSIO1Driver != NULL) {
1198                 SIO1_shutdown();
1199                 SysCloseLibrary(hSIO1Driver);
1200                 hSIO1Driver = NULL;
1201         }
1202 #endif
1203 }
1204
1205 // for CD swap
1206 int ReloadCdromPlugin()
1207 {
1208         if (hCDRDriver != NULL || cdrIsoActive()) CDR_shutdown();
1209         if (hCDRDriver != NULL) { SysCloseLibrary(hCDRDriver); hCDRDriver = NULL; }
1210
1211         if (UsingIso()) {
1212                 LoadCDRplugin(NULL);
1213         } else {
1214                 char Plugin[MAXPATHLEN * 2];
1215                 sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Cdr);
1216                 if (LoadCDRplugin(Plugin) == -1) return -1;
1217         }
1218
1219         return CDR_init();
1220 }
1221
1222 void SetIsoFile(const char *filename) {
1223         if (filename == NULL) {
1224                 IsoFile[0] = '\0';
1225                 return;
1226         }
1227         strncpy(IsoFile, filename, MAXPATHLEN - 1);
1228 }
1229
1230 const char *GetIsoFile(void) {
1231         return IsoFile;
1232 }
1233
1234 boolean UsingIso(void) {
1235         return (IsoFile[0] != '\0');
1236 }
1237
1238 void SetCdOpenCaseTime(s64 time) {
1239         cdOpenCaseTime = time;
1240 }