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