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