drc: don't remove unused i/o reads because of FIFOs
[pcsx_rearmed.git] / gui / Plugin.c
1 /*  Pcsx - Pc Psx Emulator
2  *  Copyright (C) 1999-2002  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 Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <dlfcn.h>
23 #include <X11/keysym.h>
24 #include <signal.h>
25
26 #include "Linux.h"
27
28 #include "../libpcsxcore/plugins.h"
29 #include "../libpcsxcore/spu.h"
30 #include "../libpcsxcore/cdriso.h"
31
32 #include "nopic.h"
33
34 #define MAX_SLOTS 5     /* ADB TODO Same as Gtk2Gui.c */
35
36 void OnFile_Exit();
37
38 unsigned long gpuDisp;
39
40 int StatesC = 0;
41 extern int UseGui;
42 int ShowPic = 0;
43
44 void gpuShowPic() {
45         gchar *state_filename;
46         gzFile f;
47
48         if (!ShowPic) {
49                 unsigned char *pMem;
50
51                 pMem = (unsigned char *) malloc(128*96*3);
52                 if (pMem == NULL) return;
53
54                 state_filename = get_state_filename (StatesC);
55
56                 GPU_freeze(2, (GPUFreeze_t *)&StatesC);
57
58                 f = gzopen(state_filename, "rb");
59                 if (f != NULL) {
60                         gzseek(f, 32, SEEK_SET); // skip header
61                         gzread(f, pMem, 128*96*3);
62                         gzclose(f);
63                 } else {
64                         memcpy(pMem, NoPic_Image.pixel_data, 128*96*3);
65                         DrawNumBorPic(pMem, StatesC+1);
66                 }
67                 GPU_showScreenPic(pMem);
68
69                 free(pMem);
70                 ShowPic = 1;
71                 g_free (state_filename);
72         } else {
73                 GPU_showScreenPic(NULL);
74                 ShowPic = 0;
75         }
76 }
77
78 void KeyStateSave(int i) {
79         gchar *state_filename;
80
81         state_filename = get_state_filename (i);
82         state_save (state_filename);
83
84         g_free (state_filename);
85 }
86
87 void KeyStateLoad(int i) {
88         gchar *state_filename;
89
90         state_filename = get_state_filename (i);
91         state_load (state_filename);
92
93         g_free (state_filename);
94
95         // HACKHACK: prevent crash when using recompiler due to execution not
96         // returned from compiled code. This WILL cause memory leak, however a
97         // large amount of refactor is needed for a proper fix.
98         if (Config.Cpu == CPU_DYNAREC) psxCpu->Execute();
99 }
100
101 static short modctrl = 0, modalt = 0;
102
103 /* Handle keyboard keystrokes */
104 void PADhandleKey(int key) {
105         char Text[MAXPATHLEN];
106         gchar *state_filename;
107
108         short rel = 0;  //released key flag
109
110         if (key == 0)
111                 return;
112
113         if ((key >> 30) & 1)    //specific to dfinput (padJoy)
114                 rel = 1;
115
116         if (rel) {
117                 switch (key & ~0x40000000) {
118                 case XK_Alt_L:
119                 case XK_Alt_R:
120                         modalt=0;
121                         break;
122                 case XK_Control_L:
123                 case XK_Control_R:
124                         modctrl=0;
125                         break;
126                 }
127                 return;
128         }
129
130         switch (key) {
131                 case XK_Alt_L:
132                 case XK_Alt_R:
133                         modalt=1;
134                         break;
135                 case XK_Control_L:
136                 case XK_Control_R:
137                         modctrl=1;
138                         break;
139
140                 case XK_0:
141                         if (modalt && modctrl)
142                                 return;
143                         if (modalt) KeyStateLoad(10);
144                         break;
145
146                 case XK_1:
147                         if (modalt && modctrl)
148                                 return;
149                         if (modalt) KeyStateLoad(0);
150                         if (modctrl) KeyStateSave(0);
151                         break;
152                 case XK_2:
153                         if (modalt && modctrl)
154                                 return;
155                         if (modalt) KeyStateLoad(1);
156                         if (modctrl) KeyStateSave(1);
157                         break;
158                 case XK_3:
159                         if (modalt && modctrl)
160                                 return;
161                         if (modalt) KeyStateLoad(2);
162                         if (modctrl) KeyStateSave(2);
163                         break;
164                 case XK_4:
165                         if (modalt && modctrl)
166                                 return;
167                         if (modalt) KeyStateLoad(3);
168                         if (modctrl) KeyStateSave(3);
169                         break;
170                 case XK_5:
171                         if (modalt && modctrl)
172                                 return;
173                         if (modalt) KeyStateLoad(4);
174                         if (modctrl) KeyStateSave(4);
175                         break;
176
177                 case XK_F1:
178                         GPU_freeze(2, (GPUFreeze_t *)&StatesC);
179                         state_filename = get_state_filename (StatesC);
180                         state_save (state_filename);
181
182                         g_free (state_filename);
183
184                         if (ShowPic) { ShowPic = 0; gpuShowPic(); }
185
186                         break;
187                 case XK_F2:
188                         if (StatesC < (MAX_SLOTS - 1)) StatesC++;
189                         else StatesC = 0;
190                         GPU_freeze(2, (GPUFreeze_t *)&StatesC);
191                         if (ShowPic) { ShowPic = 0; gpuShowPic(); }
192                         break;
193                 case XK_F3:
194                         state_filename = get_state_filename (StatesC);
195                         state_load (state_filename);
196
197                         g_free (state_filename);
198
199                         // HACKHACK: prevent crash when using recompiler due to execution not
200                         // returned from compiled code. This WILL cause memory leak, however a
201                         // large amount of refactor is needed for a proper fix.
202                         if (Config.Cpu == CPU_DYNAREC) psxCpu->Execute();
203
204                         break;
205                 case XK_F4:
206                         gpuShowPic();
207                         break;
208                 case XK_F5:
209                         Config.Sio ^= 0x1;
210                         if (Config.Sio)
211                                 sprintf(Text, _("SIO IRQ Always Enabled"));
212                         else sprintf(Text, _("SIO IRQ Not Always Enabled"));
213                         GPU_displayText(Text);
214                         break;
215                 case XK_F6:
216                         Config.Mdec ^= 0x1;
217                         if (Config.Mdec)
218                                 sprintf(Text, _("Black & White Mdecs Only Enabled"));
219                         else sprintf(Text, _("Black & White Mdecs Only Disabled"));
220                         GPU_displayText(Text);
221                         break;
222                 case XK_F7:
223                         Config.Xa ^= 0x1;
224                         if (Config.Xa == 0)
225                                 sprintf (Text, _("XA Enabled"));
226                         else sprintf (Text, _("XA Disabled"));
227                         GPU_displayText(Text);
228                         break;
229                 case XK_F8:
230                         GPU_makeSnapshot();
231                         break;
232                 case XK_F9:
233                         SetCdOpenCaseTime(-1);
234                         break;
235                 case XK_F10:
236                         SetCdOpenCaseTime(0);
237                         break;
238                 case XK_Escape:
239                         // TODO
240                         // the architecture is too broken to actually restart the GUI
241                         // because SysUpdate is called from deep within the actual
242                         // execution of the emulation code
243                         // Fixing this would probably require a complete reworking of
244                         // all functions, so that they return 0 or 1 for success
245                         // that way, execution wouldn't continue
246                         if (CdromId[0] != '\0')
247                                 KeyStateSave(10);
248                         ClosePlugins();
249                         UpdateMenuSlots();
250                         if (!UseGui) OnFile_Exit();
251                         StartGui();
252                         break;
253                 case XK_Return:         //0xff0d
254                         if (modalt)     //alt-return
255                                 //I just made this up: a special sym for fullscreen because the current interface can't handle key mods
256                                 //though it can be used in the future as a convention...eg bit 29 for alt, bit 28 for cntl, etc.
257                                 GPU_keypressed( (1<<29) | 0xFF0D );
258                         break;
259                 default:
260                         GPU_keypressed(key);
261                         if (Config.UseNet) NET_keypressed(key);
262         }       
263 }
264
265 void OnFile_Exit();
266
267 void SignalExit(int sig) {
268         ClosePlugins();
269         OnFile_Exit();
270 }
271
272 #define PARSEPATH(dst, src) \
273         ptr = src + strlen(src); \
274         while (*ptr != '\\' && ptr != src) ptr--; \
275         if (ptr != src) { \
276                 strcpy(dst, ptr+1); \
277         }
278
279 int _OpenPlugins() {
280         int ret;
281
282         signal(SIGINT, SignalExit);
283         signal(SIGPIPE, SignalExit);
284
285         GPU_clearDynarec(clearDynarec);
286
287         ret = CDR_open();
288         if (ret < 0) { SysMessage(_("Error opening CD-ROM plugin!")); return -1; }
289         ret = SPU_open();
290         if (ret < 0) { SysMessage(_("Error opening SPU plugin!")); return -1; }
291         SPU_registerCallback(SPUirq);
292         ret = GPU_open(&gpuDisp, "PCSX", NULL);
293         if (ret < 0) { SysMessage(_("Error opening GPU plugin!")); return -1; }
294         ret = PAD1_open(&gpuDisp);
295         if (ret < 0) { SysMessage(_("Error opening Controller 1 plugin!")); return -1; }
296         ret = PAD2_open(&gpuDisp);
297         if (ret < 0) { SysMessage(_("Error opening Controller 2 plugin!")); return -1; }
298
299         if (Config.UseNet && !NetOpened) {
300                 netInfo info;
301                 char path[MAXPATHLEN];
302                 char dotdir[MAXPATHLEN];
303
304                 strncpy(dotdir, getenv("HOME"), MAXPATHLEN-100);
305                 strcat(dotdir, "/.pcsx/plugins/");
306
307                 strcpy(info.EmuName, "PCSX " PACKAGE_VERSION);
308                 strncpy(info.CdromID, CdromId, 9);
309                 strncpy(info.CdromLabel, CdromLabel, 9);
310                 info.psxMem = psxM;
311                 info.GPU_showScreenPic = GPU_showScreenPic;
312                 info.GPU_displayText = GPU_displayText;
313                 info.GPU_showScreenPic = GPU_showScreenPic;
314                 info.PAD_setSensitive = PAD1_setSensitive;
315                 sprintf(path, "%s%s", Config.BiosDir, Config.Bios);
316                 strcpy(info.BIOSpath, path);
317                 strcpy(info.MCD1path, Config.Mcd1);
318                 strcpy(info.MCD2path, Config.Mcd2);
319                 sprintf(path, "%s%s", dotdir, Config.Gpu);
320                 strcpy(info.GPUpath, path);
321                 sprintf(path, "%s%s", dotdir, Config.Spu);
322                 strcpy(info.SPUpath, path);
323                 sprintf(path, "%s%s", dotdir, Config.Cdr);
324                 strcpy(info.CDRpath, path);
325                 NET_setInfo(&info);
326
327                 ret = NET_open(&gpuDisp);
328                 if (ret < 0) {
329                         if (ret == -2) {
330                                 // -2 is returned when something in the info
331                                 // changed and needs to be synced
332                                 char *ptr;
333
334                                 PARSEPATH(Config.Bios, info.BIOSpath);
335                                 PARSEPATH(Config.Gpu,  info.GPUpath);
336                                 PARSEPATH(Config.Spu,  info.SPUpath);
337                                 PARSEPATH(Config.Cdr,  info.CDRpath);
338
339                                 strcpy(Config.Mcd1, info.MCD1path);
340                                 strcpy(Config.Mcd2, info.MCD2path);
341                                 return -2;
342                         } else {
343                                 Config.UseNet = FALSE;
344                         }
345                 } else {
346                         if (NET_queryPlayer() == 1) {
347                                 if (SendPcsxInfo() == -1) Config.UseNet = FALSE;
348                         } else {
349                                 if (RecvPcsxInfo() == -1) Config.UseNet = FALSE;
350                         }
351                 }
352                 NetOpened = TRUE;
353         } else if (Config.UseNet) {
354                 NET_resume();
355         }
356
357         return 0;
358 }
359
360 int OpenPlugins() {
361         int ret;
362
363         while ((ret = _OpenPlugins()) == -2) {
364                 ReleasePlugins();
365                 LoadMcds(Config.Mcd1, Config.Mcd2);
366                 if (LoadPlugins() == -1) return -1;
367         }
368         return ret;
369 }
370
371 void ClosePlugins() {
372         int ret;
373
374         signal(SIGINT, SIG_DFL);
375         signal(SIGPIPE, SIG_DFL);
376         ret = CDR_close();
377         if (ret < 0) { SysMessage(_("Error closing CD-ROM plugin!")); return; }
378         ret = SPU_close();
379         if (ret < 0) { SysMessage(_("Error closing SPU plugin!")); return; }
380         ret = PAD1_close();
381         if (ret < 0) { SysMessage(_("Error closing Controller 1 Plugin!")); return; }
382         ret = PAD2_close();
383         if (ret < 0) { SysMessage(_("Error closing Controller 2 plugin!")); return; }
384         ret = GPU_close();
385         if (ret < 0) { SysMessage(_("Error closing GPU plugin!")); return; }
386
387         if (Config.UseNet) {
388                 NET_pause();
389         }
390 }