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