1
2
3 /* Pcsx - Pc Psx Emulator
4 * Copyright (C) 1999-2002 Pcsx Team
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <dlfcn.h>
25 #include <X11/keysym.h>
26 #include <signal.h>
27
28 #include "Linux.h"
29
30 #include "../libpcsxcore/plugins.h"
31 #include "../libpcsxcore/spu.h"
32 #include "../libpcsxcore/cdriso.h"
33
34 #include "nopic.h"
35
36 #define MAX_SLOTS 9 /* ADB TODO Same as GtkGui.c */
37
38 void OnFile_Exit();
39
40 extern void LidInterrupt();
41
42 unsigned long gpuDisp;
43
44 int StatesC = 0;
45 unsigned char loadedOld = FALSE;
46 int speed = 100;
47 extern int UseGui;
48
gpuShowPic()49 void gpuShowPic() {
50 gchar *state_filename;
51 gzFile f;
52 unsigned char *pMem;
53
54 pMem = (unsigned char *) malloc(128*96*3);
55 if (pMem == NULL) return;
56
57 state_filename = get_state_filename (StatesC);
58
59 GPU_freeze(2, (GPUFreeze_t *)&StatesC);
60
61 f = gzopen(state_filename, "rb");
62 if (f != NULL) {
63 gzseek(f, 32, SEEK_SET); // skip header
64 gzseek(f, sizeof(u32), SEEK_CUR);
65 gzseek(f, sizeof(boolean), SEEK_CUR);
66 gzread(f, pMem, 128*96*3);
67 gzclose(f);
68 } else {
69 memcpy(pMem, NoPic_Image.pixel_data, 128*96*3);
70 DrawNumBorPic(pMem, StatesC+1);
71 }
72 GPU_showScreenPic(pMem);
73
74 free(pMem);
75 g_free (state_filename);
76
77 vblank_count_hideafter = 2*50; // show pic for about 2 seconds
78 }
79
KeyStateSave(int i)80 void KeyStateSave(int i) {
81 gchar *state_filename;
82 gchar *oldname, *newname;
83 int j;
84
85 state_filename = get_state_filename (i);
86 if (i < OLD_SLOT && !loadedOld) {
87 newname = get_state_filename (LAST_OLD_SLOT);
88 for (j = LAST_OLD_SLOT - 1; j >= OLD_SLOT; --j) {
89 oldname = get_state_filename (j);
90 rename(oldname, newname);
91 g_free (newname);
92 newname = oldname;
93 }
94 rename(state_filename, newname);
95 g_free (newname);
96 }
97 state_save (state_filename);
98 loadedOld = FALSE;
99
100 g_free (state_filename);
101 }
102
KeyStateLoad(int i)103 void KeyStateLoad(int i) {
104 gchar *state_filename;
105
106 loadedOld = (i >= OLD_SLOT && i <= LAST_OLD_SLOT);
107
108 state_filename = get_state_filename (i);
109 state_load (state_filename);
110
111 g_free (state_filename);
112
113 // HACKHACK: prevent crash when using recompiler due to execution not
114 // returned from compiled code. This WILL cause memory leak, however a
115 // large amount of refactor is needed for a proper fix.
116 if (Config.Cpu == CPU_DYNAREC) psxCpu->Execute();
117 }
118
119 // todo: make toggle config param
120 static s16 modctrl = 0, modalt = 0, toggle = 0, pressed = 0;
121 s32 lastpressed = 0;
122 time_t tslastpressed = 0;
123
124 /* Handle keyboard keystrokes */
PADhandleKey(int key)125 void PADhandleKey(int key) {
126 char Text[MAXPATHLEN];
127 gchar *state_filename;
128 time_t now;
129 int slot;
130
131 short rel = 0; //released key flag
132
133 // Allow rewind key to repeat
134 if (key == 0 || (key == lastpressed && key != XK_BackSpace))
135 return;
136
137 if ((key >> 30) & 1) //specific to dfinput (padJoy)
138 rel = 1;
139 //printf("Key %x\n", key);
140
141 if (rel) {
142 switch (key & ~0x40000000) {
143 case XK_Alt_L:
144 case XK_Alt_R:
145 modalt=0;
146 break;
147 case XK_Control_L:
148 case XK_Control_R:
149 modctrl=0;
150 break;
151 case XK_section:
152 if (!toggle && pressed) GPU_keypressed( XK_section );
153 pressed = 0;
154 break;
155 }
156 lastpressed = 0;
157 return;
158 }
159
160 lastpressed = key;
161 switch (key) {
162 case XK_Alt_L:
163 case XK_Alt_R:
164 modalt=1;
165 break;
166 case XK_Control_L:
167 case XK_Control_R:
168 modctrl=1;
169 break;
170
171 case XK_0:
172 if (modalt && modctrl)
173 return;
174 if (modalt) KeyStateLoad(10);
175 break;
176
177 case XK_1: case XK_2: case XK_3: case XK_4: case XK_5:
178 case XK_6: case XK_7: case XK_8: case XK_9:
179 slot = key - XK_1;
180 if (modalt && modctrl)
181 return;
182 if (modalt) KeyStateLoad(slot);
183 else if (modctrl) KeyStateSave(slot);
184 //else KeyStateLoad(OLD_SLOT + slot);
185 break;
186
187 case XK_F1:
188 GPU_freeze(2, (GPUFreeze_t *)&StatesC);
189 KeyStateSave(StatesC);
190 gpuShowPic();
191 break;
192 case XK_F2:
193 if (StatesC < (MAX_SLOTS - 1)) StatesC++;
194 else StatesC = 0;
195 GPU_freeze(2, (GPUFreeze_t *)&StatesC);
196 gpuShowPic();
197 break;
198 case XK_F3:
199 KeyStateLoad(StatesC);
200 gpuShowPic();
201 break;
202 case XK_F4:
203 gpuShowPic();
204 break;
205 case XK_section:
206 if (pressed) break;
207 GPU_keypressed( XK_section );
208 pressed = 1;
209 break;
210 case XK_F5:
211 Config.SioIrq ^= 0x1;
212 if (Config.SioIrq)
213 sprintf(Text, _("SIO IRQ Always Enabled"));
214 else sprintf(Text, _("SIO IRQ Not Always Enabled"));
215 GPU_displayText(Text);
216 break;
217 case XK_F6:
218 Config.Mdec ^= 0x1;
219 if (Config.Mdec)
220 sprintf(Text, _("Black & White Mdecs Only Enabled"));
221 else sprintf(Text, _("Black & White Mdecs Only Disabled"));
222 GPU_displayText(Text);
223 break;
224 case XK_F7:
225 Config.Xa ^= 0x1;
226 if (Config.Xa == 0)
227 sprintf (Text, _("XA Enabled"));
228 else sprintf (Text, _("XA Disabled"));
229 GPU_displayText(Text);
230 break;
231 case XK_F8:
232 GPU_makeSnapshot();
233 break;
234 case XK_F9:
235 SetCdOpenCaseTime(-1);
236
237 LidInterrupt();
238 break;
239 case XK_F10:
240 SetCdOpenCaseTime(0);
241
242 LidInterrupt();
243 break;
244 case XK_F12:
245 psxReset();
246 break;
247 case XK_BackSpace:
248 now = clock();
249 //printf("Rewind %u %u %u\n", tslastpressed, now, rewind_counter);
250 rewind_counter = 0;
251 if ((((now - tslastpressed) * 1000) / CLOCKS_PER_SEC) <= 130) break;
252 tslastpressed = now;
253 RewindState();
254 break;
255 case XK_bracketleft:
256 if (speed == Config.AltSpeed1) {
257 speed = 100;
258 } else {
259 speed = Config.AltSpeed1;
260 }
261 GPU_setSpeed(speed / 100.0);
262 break;
263 case XK_bracketright:
264 if (speed == Config.AltSpeed2) {
265 speed = 100;
266 } else {
267 speed = Config.AltSpeed2;
268 }
269 GPU_setSpeed(speed / 100.0);
270 break;
271 case XK_Escape:
272 // TODO
273 // the architecture is too broken to actually restart the GUI
274 // because SysUpdate is called from deep within the actual
275 // execution of the emulation code
276 // Fixing this would probably require a complete reworking of
277 // all functions, so that they return 0 or 1 for success
278 // that way, execution wouldn't continue
279 if (CdromId[0] != '\0') {
280 loadedOld = TRUE;
281 KeyStateSave(10);
282 }
283 ClosePlugins();
284 UpdateMenuSlots();
285 if (!UseGui) OnFile_Exit();
286 StartGui();
287 break;
288 case XK_Return: //0xff0d
289 if (modalt) //alt-return
290 //I just made this up: a special sym for fullscreen because the current interface can't handle key mods
291 //though it can be used in the future as a convention...eg bit 29 for alt, bit 28 for cntl, etc.
292 GPU_keypressed( (1<<29) | 0xFF0D );
293 break;
294 default:
295 GPU_keypressed(key);
296 #ifdef ENABLE_SIO1API
297 SIO1_keypressed(key);
298 #endif
299 if (Config.UseNet) NET_keypressed(key);
300 }
301 }
302
303 void OnFile_Exit();
304
SignalExit(int sig)305 void SignalExit(int sig) {
306 ClosePlugins();
307 OnFile_Exit();
308 }
309
310 #define PARSEPATH(dst, src) \
311 ptr = src + strlen(src); \
312 while (*ptr != '\\' && ptr != src) ptr--; \
313 if (ptr != src) { \
314 strcpy(dst, ptr+1); \
315 }
316
_OpenPlugins()317 int _OpenPlugins() {
318 int ret;
319
320 signal(SIGINT, SignalExit);
321 signal(SIGPIPE, SignalExit);
322
323 GPU_clearDynarec(clearDynarec);
324
325 ret = CDR_open();
326 if (ret < 0) { SysMessage(_("Error opening CD-ROM plugin!")); return -1; }
327 ret = SPU_open();
328 if (ret < 0) { SysMessage(_("Error opening SPU plugin!")); return -1; }
329 SPU_registerCallback(SPUirq);
330 ret = GPU_open(&gpuDisp, "PCSXR", NULL);
331 if (ret < 0) { SysMessage(_("Error opening GPU plugin!")); return -1; }
332 ret = PAD1_open(&gpuDisp);
333 ret |= PAD1_init(1); // Allow setting to change during run
334 if (ret < 0) { SysMessage(_("Error opening Controller 1 plugin!")); return -1; }
335 PAD1_registerVibration(GPU_visualVibration);
336 PAD1_registerCursor(GPU_cursor);
337 ret = PAD2_open(&gpuDisp);
338 ret |= PAD2_init(2); // Allow setting to change during run
339 if (ret < 0) { SysMessage(_("Error opening Controller 2 plugin!")); return -1; }
340 PAD2_registerVibration(GPU_visualVibration);
341 PAD2_registerCursor(GPU_cursor);
342 #ifdef ENABLE_SIO1API
343 ret = SIO1_open(&gpuDisp);
344 if (ret < 0) { SysMessage(_("Error opening SIO1 plugin!")); return -1; }
345 SIO1_registerCallback(SIO1irq);
346 #endif
347
348 if (Config.UseNet && !NetOpened) {
349 netInfo info;
350 char path[MAXPATHLEN];
351 char dotdir[MAXPATHLEN];
352
353 strncpy(dotdir, getenv("HOME"), MAXPATHLEN-100);
354 strcat(dotdir, "/.pcsxr/plugins/");
355
356 strcpy(info.EmuName, "PCSXR " PACKAGE_VERSION);
357 strncpy(info.CdromID, CdromId, 9);
358 strncpy(info.CdromLabel, CdromLabel, 9);
359 info.psxMem = psxM;
360 info.GPU_showScreenPic = GPU_showScreenPic;
361 info.GPU_displayText = GPU_displayText;
362 info.GPU_showScreenPic = GPU_showScreenPic;
363 info.PAD_setSensitive = PAD1_setSensitive;
364 sprintf(path, "%s%s", Config.BiosDir, Config.Bios);
365 strcpy(info.BIOSpath, path);
366 strcpy(info.MCD1path, Config.Mcd1);
367 strcpy(info.MCD2path, Config.Mcd2);
368 sprintf(path, "%s%s", dotdir, Config.Gpu);
369 strcpy(info.GPUpath, path);
370 sprintf(path, "%s%s", dotdir, Config.Spu);
371 strcpy(info.SPUpath, path);
372 sprintf(path, "%s%s", dotdir, Config.Cdr);
373 strcpy(info.CDRpath, path);
374 NET_setInfo(&info);
375
376 ret = NET_open(&gpuDisp);
377 if (ret < 0) {
378 if (ret == -2) {
379 // -2 is returned when something in the info
380 // changed and needs to be synced
381 char *ptr;
382
383 PARSEPATH(Config.Bios, info.BIOSpath);
384 PARSEPATH(Config.Gpu, info.GPUpath);
385 PARSEPATH(Config.Spu, info.SPUpath);
386 PARSEPATH(Config.Cdr, info.CDRpath);
387
388 strcpy(Config.Mcd1, info.MCD1path);
389 strcpy(Config.Mcd2, info.MCD2path);
390 return -2;
391 } else {
392 Config.UseNet = FALSE;
393 }
394 } else {
395 if (NET_queryPlayer() == 1) {
396 if (SendPcsxInfo() == -1) Config.UseNet = FALSE;
397 } else {
398 if (RecvPcsxInfo() == -1) Config.UseNet = FALSE;
399 }
400 }
401 NetOpened = TRUE;
402 } else if (Config.UseNet) {
403 NET_resume();
404 }
405
406 return 0;
407 }
408
OpenPlugins()409 int OpenPlugins() {
410 int ret;
411
412 while ((ret = _OpenPlugins()) == -2) {
413 ReleasePlugins();
414 LoadMcds(Config.Mcd1, Config.Mcd2);
415 if (LoadPlugins() == -1) return -1;
416 }
417 return ret;
418 }
419
ClosePlugins()420 void ClosePlugins() {
421 int ret;
422
423 signal(SIGINT, SIG_DFL);
424 signal(SIGPIPE, SIG_DFL);
425 ret = CDR_close();
426 if (ret < 0) { SysMessage(_("Error closing CD-ROM plugin!")); return; }
427 ret = SPU_close();
428 if (ret < 0) { SysMessage(_("Error closing SPU plugin!")); return; }
429 ret = PAD1_close();
430 if (ret < 0) { SysMessage(_("Error closing Controller 1 Plugin!")); return; }
431 ret = PAD2_close();
432 if (ret < 0) { SysMessage(_("Error closing Controller 2 plugin!")); return; }
433 ret = GPU_close();
434 if (ret < 0) { SysMessage(_("Error closing GPU plugin!")); return; }
435 #ifdef ENABLE_SIO1API
436 ret = SIO1_close();
437 if (ret < 0) { SysMessage(_("Error closing SIO1 plugin!")); return; }
438 #endif
439
440 if (Config.UseNet) {
441 NET_pause();
442 }
443 }
444
445