Commit | Line | Data |
---|---|---|
ef79bbde P |
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 | } |