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