1 /*
2 
3   unix.c
4 
5   This file contains system specific information
6   (e.g. displaying routines, joystick access,
7         window controls etc ...)
8 
9 */
10 
11 #ifdef UNIX
12 
13 #ifdef GLIDE
14 #ifdef FRAMEBUFFER
15 #error: Do not try to make GLIDE & FRAMEBUFFER !!!
16 #endif
17 #if !defined JOYSTICK && !defined BSD_JOYSTICK
18 #error: Do not try to make GLIDE w/o JOYSTICK/BSD_JOYSTICK !!!
19 #endif
20 #endif
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 
27 #include "globals.h"
28 #include "sys.h"
29 #include "gameboy.h"
30 #include "z80.h"
31 #include "arplay.h"
32 #include "settings.h"
33 
34 /* unix signal processing */
35 #define __USE_POSIX
36 #include <signal.h>
37 #include <sys/time.h>
38 #include <sys/types.h>
39 
40 #ifndef GLIDE
41 /* X specific */
42 #include <X11/Xlib.h>
43 #include <X11/Xutil.h>
44 #include <X11/keysym.h>
45 
46 #ifdef MIT_SHM
47 #include <X11/extensions/XShm.h>
48 #include <sys/shm.h>
49 #include <sys/ipc.h>
50 #endif
51 
52 #ifdef WITH_XVIDEO
53 #include <X11/extensions/Xvlib.h>
54 #endif
55 
56 #endif
57 
58 #ifdef JOYSTICK
59 /* linux joystick device */
60 #include <linux/joystick.h>
61 #include <fcntl.h>
62 #include <sys/ioctl.h>
63 #endif
64 #ifdef BSD_JOYSTICK
65 /* BSD joystick device */
66 #include <sys/joystick.h>
67 #include <fcntl.h>
68 #include <sys/ioctl.h>
69 #endif
70 
71 #ifdef FRAMEBUFFER
72 /* framebuffer device */
73 #include <fcntl.h>
74 #include <linux/fb.h>
75 #include <sys/ioctl.h>
76 #include <sys/mman.h>
77 #include <termios.h>
78 #include <linux/vt.h>
79 
80 char *fbdevname="/dev/fb0";
81 struct fb_fix_screeninfo fb_finfo;
82 struct fb_var_screeninfo fb_vinfo,fb_vinfo_orig;
83 struct termios termsave;
84 struct vt_mode vt_modesave;
85 
86 int fbdev,tty,fbgb_linesize,ttystate;
87 int usingfb;
88 char *fbmem,*fbgb;
89 #endif
90 
91 #ifdef GLIDE
92 #include <glide.h>
93 #include <sst1vid.h>
94 #include <termios.h>
95 
96 struct termios termsave;
97 #endif
98 
99 #ifdef DIALOGLINK
100 #include <sys/socket.h>
101 #include <netinet/in.h>
102 #include <netdb.h>
103 
104 char *sock_tcpsignature="cingb___init___socket";
105 int dialoglink,dlglink_status,sock_d,sock_nd,sock_desc;
106 
107 int dlglink_init(void);
108 #endif
109 
110 /* experimental ***************************************/
111 #ifdef SOUND
112 #include "sound.h"
113 #endif
114 
115 #include "joypad.h"
116 
117 #ifndef GLIDE
118 char *gbwintitle="cingb";
119 
120 Display *display;
121 Visual *visual;
122 Window gbwin;
123 Colormap colormap;
124 int screen;
125 XColor *colors;
126 static XImage *gameboyscreen;
127 GC gbgc;
128 static size_t lcdbuffersize=0;
129 
130 #ifdef MIT_SHM
131 /* XShm */
132 static Status use_xshm;
133 static XShmSegmentInfo shminfo;
134 #endif
135 
136 #ifdef WITH_XVIDEO
137 static int use_xvideo=0;
138 static unsigned int xv_port=0, xv_format;
139 static XvImage *xv_gameboyscreen;
140 static int win_width=GB_LCDXSCREENSIZE;
141 static int win_height=GB_LCDYSCREENSIZE;
142 #endif
143 #endif
144 
145 int joypaddev,usejoypad,usekeys,timerset,
146   resolution,doublesize,dsupdatenow,usingsound,bitmapbits;
147 volatile int refreshtimer;
148 struct itimerval itv;
149 int REDSHL,GREENSHL,BLUESHL;
150 int REDOFS,GREENOFS,BLUEOFS;
151 
152 #ifdef JOYSTICK
153 struct JS_DATA_TYPE js;
154 #endif
155 #ifdef BSD_JOYSTICK
156 struct joystick js;
157 #endif
158 
159 uchar GB_STD8BITPAL[]=
160 {
161   215,
162   172,
163   86,
164   0
165 };
166 
167 unsigned long int GB_STDPAL[4];
168 
169 
timerhandler(int signr)170 void timerhandler(int signr)
171 {
172 #ifdef _LINUX
173   signal(SIGALRM, timerhandler);
174 #endif
175   refreshtimer++;
176 }
177 
178 #ifdef FRAMEBUFFER
179 
FB_ClearScreen(void)180 void FB_ClearScreen(void)
181 {
182   memset(fbmem,0,fb_vinfo.xres*fb_vinfo.yres*resolution/8);
183 }
184 
tty_switchhandler(int signal)185 void tty_switchhandler(int signal)
186 {
187   switch (signal) {
188   case SIGUSR1:
189     ttystate=0;
190     ioctl(tty, VT_RELDISP, 1);
191     break;
192   case SIGUSR2:
193     ttystate=1;
194     ioctl(tty, VT_RELDISP, VT_ACKACQ);
195     FB_ClearScreen();
196     break;
197   }
198 }
199 
InitFB(void)200 int InitFB(void)
201 {
202   struct termios term;
203   struct vt_mode vtm;
204   struct sigaction old,now;
205 
206   fbdev=open(fbdevname,O_RDWR,0);
207   if (!fbdev) {
208     fprintf(stderr,"Could not open %s or an X connection.\n",fbdevname);
209     return 1;
210   }
211   if (ioctl(fbdev,FBIOGET_FSCREENINFO,&fb_finfo)<0) {
212     fprintf(stderr,"Error: FBIOGET_FSCREENINFO\n");
213     return 1;
214   }
215   if (ioctl(fbdev,FBIOGET_VSCREENINFO,&fb_vinfo)<0) {
216     fprintf(stderr,"Error: FBIOGET_VSCREENINFO\n");
217     return 1;
218   }
219   bitmapbits=resolution=fb_vinfo.bits_per_pixel;
220 
221   if (resolution<16) {
222     fprintf(stderr,"Sorry: I don't support %d bits resolution, yet.\n",
223 	    resolution);
224     return 1;
225   }
226   memcpy(&fb_vinfo_orig,&fb_vinfo,sizeof(fb_vinfo_orig));
227 
228   fbmem=mmap(NULL,fb_finfo.smem_len,PROT_WRITE,
229 	     MAP_SHARED,fbdev,0);
230 
231   if (fbmem==MAP_FAILED) {
232     fprintf(stderr,"Error: mmap failed.\n");
233     return 1;
234   }
235 
236   if (!smallview) {
237     fbgb=fbmem+(fb_vinfo.xres-GB_LCDXSCREENSIZE*2)*resolution/16+
238       (fb_vinfo.yres-GB_LCDYSCREENSIZE*2)/2*fb_finfo.line_length;
239     fbgb_linesize=GB_LCDXSCREENSIZE*2*resolution/8;
240   } else {
241     fbgb=fbmem+(fb_vinfo.xres-GB_LCDXSCREENSIZE)*resolution/16+
242       (fb_vinfo.yres-GB_LCDYSCREENSIZE)/2*fb_finfo.line_length;
243     fbgb_linesize=GB_LCDXSCREENSIZE*resolution/8;
244   }
245 
246 
247   if (fb_vinfo.xoffset!=0 || fb_vinfo.yoffset!=0) {
248     fb_vinfo.xoffset=0;
249     fb_vinfo.yoffset=0;
250     if (ioctl(fbdev,FBIOPAN_DISPLAY,&fb_vinfo)<0) {
251       fprintf(OUTSTREAM,"Error: FBIOPAN_DISPLAY\n");
252       return 1;
253     }
254   }
255 
256   usingfb=1;
257   FB_ClearScreen();
258 
259   logfile=fopen("cingb.log","w");
260   if (logfile==NULL) {
261     fprintf(stdout,"Could not open logfile (using stdout).\n");
262     logfile=stdout;
263   }
264 
265 #ifdef DEBUG
266   printf("FB_TYPE  : %d\n",fb_finfo.type);
267   printf("FB_VISUAL: %d\n",fb_finfo.visual);
268   printf("Resolution: %dx%dx%d\n",fb_vinfo.xres,fb_vinfo.yres,
269 	 fb_vinfo.bits_per_pixel);
270   printf("Pixel format: red  : %d-%d\n",fb_vinfo.red.offset,
271 	 fb_vinfo.red.offset+fb_vinfo.red.length-1);
272   printf("              green: %d-%d\n",fb_vinfo.green.offset,
273 	 fb_vinfo.green.offset+fb_vinfo.green.length-1);
274   printf("              blue : %d-%d\n",fb_vinfo.blue.offset,
275 	 fb_vinfo.blue.offset+fb_vinfo.blue.length-1);
276 #endif
277   REDOFS  =fb_vinfo.red.offset;
278   GREENOFS=fb_vinfo.green.offset;
279   BLUEOFS =fb_vinfo.blue.offset;
280 
281   REDSHL  =fb_vinfo.red.length-5;
282   GREENSHL=fb_vinfo.green.length-5;
283   BLUESHL =fb_vinfo.blue.length-5;
284 
285   /* init terminal settings */
286   fprintf(OUTSTREAM,"Setting up terminal ... ");
287   tcgetattr(0,&termsave);
288   memcpy(&term,&termsave,sizeof(struct termios));
289   cfmakeraw(&term);
290   term.c_iflag|=BRKINT;
291   term.c_lflag|=ISIG;
292   tcsetattr(0,TCSANOW,&term);
293   out_ok;
294 
295   /* tty init */
296   fprintf(OUTSTREAM,"Setting up tty device ... ");
297   if ((tty=open("/dev/tty",O_RDWR))<0) {
298     fprintf(OUTSTREAM,"Error opening tty device.\n");
299     return 1;
300   }
301   if (ioctl(tty,VT_GETMODE,&vt_modesave)<0) {
302     fprintf(OUTSTREAM,"Error writing to tty device.\n");
303     return 1;
304   }
305   memcpy(&vtm,&vt_modesave,sizeof(struct vt_mode));
306   now.sa_handler  = tty_switchhandler;
307   now.sa_flags    = 0;
308   now.sa_restorer = NULL;
309   sigemptyset(&now.sa_mask);
310   sigaction(SIGUSR1,&now,&old);
311   sigaction(SIGUSR2,&now,&old);
312 
313   vtm.mode   = VT_PROCESS;
314   vtm.waitv  = 0;
315   vtm.relsig = SIGUSR1;
316   vtm.acqsig = SIGUSR2;
317 
318   if (ioctl(tty,VT_SETMODE,&vtm)<0) {
319     fprintf(OUTSTREAM,"Error writing to tty device.\n");
320     return 1;
321   }
322   ttystate=1;
323   out_ok;
324 
325   return 0;
326 }
327 
DoneFB(void)328 void DoneFB(void)
329 {
330   /* clean up */
331 
332   ioctl(tty,VT_SETMODE,&vt_modesave);
333   close(tty);
334 
335   tcsetattr(0,TCSANOW,&termsave);
336   FB_ClearScreen();
337 
338   if (ioctl(fbdev,FBIOPUT_VSCREENINFO,&fb_vinfo_orig)<0) {
339     fprintf(stderr,"Error: FBIOPUT_VSCREENINFO. (restoring state)\n");
340   }
341 
342   if (munmap(fbmem,fb_finfo.smem_len)) {
343     fprintf(stderr,"Error: munmap failed.\n");
344   }
345   close(fbdev);
346 #ifdef VERBOSE
347   fprintf(OUTSTREAM,"Framebuffer device closed.\n");
348 #endif
349   fclose(logfile);
350   logfile=stdout;
351 }
352 #endif
353 
allocate_lcdbuffer(void)354 void allocate_lcdbuffer(void) {
355 	lcdbuffersize=doublesize ?
356 		GB_XBUFFERSIZE*GB_LCDYSCREENSIZE*(bitmapbits/2) :
357 		GB_XBUFFERSIZE*GB_LCDYSCREENSIZE*(bitmapbits/8);
358 	fprintf(OUTSTREAM,"Allocating lcd buffer (%lu bytes%s)... ",
359 		(size_t)lcdbuffersize, doublesize ? "; double-size" : "");
360 	lcdbuffer=malloc(lcdbuffersize);
361 	if (lcdbuffer==NULL) out_failed; else out_ok;
362 }
363 
364 #ifdef GLIDE
365 
366 /* **************************************** */
initGlide(void)367 int initGlide(void)
368 {
369   GrHwConfiguration hwconfig;
370   struct termios term;
371 
372   /* init terminal settings */
373   fprintf(OUTSTREAM,"Setting up terminal ... ");
374   tcgetattr(0,&termsave);
375   memcpy(&term,&termsave,sizeof(struct termios));
376   cfmakeraw(&term);
377   term.c_iflag|=BRKINT;
378   term.c_lflag|=ISIG;
379   tcsetattr(0,TCSANOW,&term);
380   out_ok;
381 
382   fprintf(OUTSTREAM,"Initializing glide ... ");
383   grGlideInit();
384   fprintf(OUTSTREAM,"ok\nSearching glide hardware ...\n");
385   if (grSstQueryHardware(&hwconfig)==FXTRUE) {
386     grSstSelect(0);
387     if (grSstWinOpen(0,GR_RESOLUTION_640x480,GR_REFRESH_NONE,
388 		     GR_COLORFORMAT_ARGB,GR_ORIGIN_UPPER_LEFT,2,1)!=FXTRUE) {
389       fprintf(OUTSTREAM,
390 	      "*** Error: Failed to set the standard 640x480 mode.\n");
391       return 1;
392     }
393   } else {
394     fprintf(OUTSTREAM,"*** Error: glide hardware not found.\n");
395     return 1;
396   }
397 
398   grColorCombine( GR_COMBINE_FUNCTION_LOCAL,
399 		  GR_COMBINE_FACTOR_NONE,
400 		  GR_COMBINE_LOCAL_CONSTANT,
401 		  GR_COMBINE_OTHER_NONE,
402 		  FXFALSE );
403 
404   grBufferClear(0,0,0);
405   grBufferSwap(0);
406   grBufferClear(0,0,0);
407   grDisableAllEffects();
408 
409   /* fixed sst1 format (there aren't others defined) */
410 
411   bitmapbits=resolution=16;
412   REDSHL=BLUESHL=0;
413   GREENSHL=1;
414   REDOFS=11;
415   GREENOFS=5;
416   BLUEOFS=0;
417 
418   out_ok;
419 
420   allocate_lcdbuffer();
421 
422   return 0;
423 }
doneGlide(void)424 void doneGlide(void)
425 {
426   grGlideShutdown();
427   tcsetattr(0,TCSANOW,&termsave);
428 }
429 
430 #else
InitXConnection(void)431 int InitXConnection(void)
432 {
433   XVisualInfo visualinfo;
434   XVisualInfo *retvinfo;
435   char *displayname=NULL;
436   int i,v;
437 #ifdef MIT_SHM
438   int major,minor;
439   Bool shared;
440 #endif
441 #ifdef WITH_XVIDEO
442   unsigned int xv_ver, xv_rel, xv_reqbase, xv_eventbase, xv_errbase,
443   	adaptorcount;
444   XvAdaptorInfo *adaptorinfo = NULL;
445 #endif
446 
447   display=XOpenDisplay(displayname);
448 
449   if (display==NULL)
450     {
451 #if defined(FRAMEBUFFER) && !defined(DEBUG)
452       return InitFB();
453 #else
454       fprintf(stderr,"Cannot connect to X-Server.\n");
455       return 1;
456 #endif
457     }
458 
459 #ifdef WITH_XVIDEO
460 
461 	if (check_xvideo) {
462 		fprintf(OUTSTREAM, "Checking for XVideo extension ... ");
463 		use_xvideo=(XvQueryExtension(display, &xv_ver, &xv_rel,
464 		&xv_reqbase, &xv_eventbase, &xv_errbase)==Success);
465 		if (!use_xvideo) out_failed;
466 		else {
467 			out_ok;
468 			fprintf(OUTSTREAM, "Fetching XVideo adapters ... ");
469 			if (XvQueryAdaptors(display,DefaultRootWindow(display),
470 				&adaptorcount,&adaptorinfo)!=Success){
471 
472 				use_xvideo=0;
473 				out_failed;
474 			} else out_ok;
475 		}
476 	} else {
477 		use_xvideo=0;
478 	}
479 
480 	if (use_xvideo) {
481 		int i;
482 		int inuse=0;
483 
484 		xv_port=0;
485 		fprintf(OUTSTREAM, "Opening XVideo port (adapters: %d) ... ",
486 			adaptorcount);
487 
488 		for (i=0; i<adaptorcount && xv_port==0; i++) {
489 			if ((adaptorinfo[i].type&XvInputMask) &&
490 				(adaptorinfo[i].type&XvImageMask)) {
491 
492 				XvPortID id;
493 
494 				for (id=adaptorinfo[i].base_id;
495 					id<adaptorinfo[i].base_id+
496 					adaptorinfo[i].num_ports; id++)
497 
498 					if (XvGrabPort(display, id,
499 						CurrentTime)==Success) {
500 
501 						xv_port = id;
502 						break;
503 					} inuse=1;
504 			}
505 		}
506 
507 		if (xv_port==0) {
508 			if (inuse) fprintf(OUTSTREAM, "all ports in use ");
509 			out_failed;
510 			use_xvideo=0;
511 		} else {
512 			int i;
513 			int formats=0;
514 			XvImageFormatValues *fo;
515 
516 			fo = XvListImageFormats(display, xv_port, (int*)&formats);
517 
518 			xv_format=0;
519 			for(i=0; i<formats; i++){
520 				fprintf(OUTSTREAM, "Available XVideo image format: 0x%x (%4.4s) %s\n", fo[i].id,(char*)&fo[i].id, (fo[i].format == XvPacked) ? "packed" : "planar");
521 				if (xv_format==0 &&
522 				(fo[i].id==0x59565955|| fo[i].id==0x55595659)) {
523 					xv_format = fo[i].id;
524 					fprintf(OUTSTREAM, "y:%d, u:%d, v:%d (bits/pixel:%d)\n",
525 					  fo[i].y_sample_bits,
526 					  fo[i].u_sample_bits,
527 					  fo[i].v_sample_bits, fo[i].bits_per_pixel);
528 				}
529 			}
530 			fprintf(OUTSTREAM, "Selecting XVideo output format ... ");
531 			if (xv_format==0) {
532 				XvUngrabPort(display, xv_port, CurrentTime);
533 				use_xvideo=0;
534 				out_failed;
535 			} else out_ok;
536 		}
537 	}
538 #endif
539 
540 #ifdef MIT_SHM
541   use_xshm=XShmQueryVersion (display, &major, &minor, &shared) && shared;
542 #endif
543 
544 
545 #ifdef FRAMEBUFFER
546   usingfb=0;
547 #endif
548 
549   if (!smallview) doublesize=1;
550 
551   screen=DefaultScreen(display);
552   visual=DefaultVisual(display, screen);
553   visualinfo.visualid=visual->visualid;
554   retvinfo=XGetVisualInfo(display, VisualIDMask, &visualinfo, &i);
555   if (retvinfo==NULL) {
556 	  fprintf(stderr, "Error getting VisualInfo for visual id %u.\n",
557 			  (unsigned int)visual->visualid);
558 	  exit(-1);
559   }
560   memcpy(&visualinfo, retvinfo, sizeof(XVisualInfo));
561   XFree(retvinfo);
562 
563   bitmapbits=BitmapUnit(display);
564 
565 	if (use_xvideo) {
566 		bitmapbits=32;
567 		fprintf(OUTSTREAM,"Screen bitmap bits is %i, resolution is %i bits (YUV).\n", bitmapbits, resolution);
568 	} else {
569 		resolution = visualinfo.depth;
570 		fprintf(OUTSTREAM,"Screen  bitmap bits is %i, resolution is %i bits.\n", bitmapbits, resolution);
571 	}
572 
573   if (bitmapbits==8) {
574     /* create a palette with 6 shades for every color
575        this will be slower (multiplication) but it
576        looks far better than 4 shades.                 */
577 
578       colormap=XCreateColormap(display, RootWindow(display,screen),
579 			       visual,AllocAll);
580       colors=(XColor *)calloc(256,sizeof(XColor));
581       for (i=0;i<256;i++)
582 	{
583 	  colors[i].pixel=i;
584 	  colors[i].flags=DoRed|DoGreen|DoBlue;
585 
586 	  if (i<216)
587 	    {
588 	      v=(i / 36) % 6;
589 	      colors[i].red=v*13107;
590 	      v=(i / 6) % 6;
591 	      colors[i].green=v*13107;
592 	      v=i % 6;
593 	      colors[i].blue=v*13107;
594 	    }
595 	}
596       XStoreColors(display,colormap,colors,256);
597   } else {
598     REDOFS=BLUEOFS=GREENOFS=0;
599     REDSHL=BLUESHL=GREENSHL=0;
600     for (i=visualinfo.red_mask;!(i&1);i>>=1,REDOFS++);
601     for (;i&1;i>>=1,REDSHL++);
602     for (i=visualinfo.green_mask;!(i&1);i>>=1,GREENOFS++);
603     for (;i&1;i>>=1,GREENSHL++);
604     for (i=visualinfo.blue_mask;!(i&1);i>>=1,BLUEOFS++);
605     for (;i&1;i>>=1,BLUESHL++);
606     REDSHL-=5;GREENSHL-=5;BLUESHL-=5;
607   }
608   return 0;
609 }
610 #endif
611 
612 /* signal hookfunc */
DoBreak(int signum)613 void DoBreak(int signum)
614 {
615   if (!ABORT_EMULATION) {
616     ABORT_EMULATION=1;
617     savestate();
618     tidyup();
619     exit(0);
620   }
621 }
622 
623 #ifdef MIT_SHM
xerrorhandler(Display * display,XErrorEvent * event)624 int xerrorhandler (Display *display, XErrorEvent *event) {
625     use_xshm=0;
626     return 0;
627 }
628 #endif
629 
630 
631 #ifndef GLIDE
InitXRessources(void)632 int InitXRessources(void)
633 {
634   XSetWindowAttributes gbwinattr;
635   XTextProperty prop_gbwintitle;
636   XGCValues values;
637 #ifdef MIT_SHM
638   XErrorHandler old_handler;
639 #endif
640 
641 
642   fprintf(OUTSTREAM,"Window initialization ... ");
643 
644   gbwinattr.event_mask=StructureNotifyMask|ExposureMask|KeyPressMask|
645   	KeyReleaseMask;
646   gbwinattr.colormap=colormap;
647   gbwinattr.border_pixel=0;
648 
649   gbwin=XCreateWindow(display,
650 		      RootWindow(display,screen),
651 		      100,50,
652 		      smallview ? GB_LCDXSCREENSIZE : GB_LCDXSCREENSIZE*2,
653 		      smallview ? GB_LCDYSCREENSIZE : GB_LCDYSCREENSIZE*2,
654 		      0,resolution,
655 		      InputOutput,
656 			    visual,
657 		      CWEventMask|
658 		      CWColormap|
659 		      CWBorderPixel,
660 		      &gbwinattr);
661 
662   if (!gbwin) {
663     out_failed;
664     return 1;
665   } else out_ok;
666 
667   values.background=0;
668   gbgc=XCreateGC(display,gbwin,GCBackground,&values);
669 
670   XStringListToTextProperty(&gbwintitle,1,&prop_gbwintitle);
671   XSetWMName(display,gbwin,&prop_gbwintitle);
672   /*XSelectInput(display,gbwin,ExposureMask|KeyPressMask|KeyReleaseMask);*/
673   XMapRaised(display,gbwin);
674   XFlush(display);
675 
676   dsupdatenow=0;
677 
678 
679   fprintf(OUTSTREAM,"Display initialized.\nCreating display image buffer ... ");
680 
681 #ifdef MIT_SHM
682  tryagain:
683   if (use_xshm) {
684 
685 #ifdef WITH_XVIDEO
686 	if (use_xvideo) {
687 		fprintf(OUTSTREAM,"(xv+shared) ");
688 		xv_gameboyscreen=(XvImage *)XvShmCreateImage(display,
689 			xv_port, xv_format, lcdbuffer,
690 			GB_XBUFFERSIZE*2, GB_LCDYSCREENSIZE, &shminfo);
691 		if (xv_gameboyscreen==NULL) {
692 			fprintf(OUTSTREAM,"screen allocation failed for XVideo"
693 				" trying X11\n Creating image buffer ... ");
694 			use_xvideo=0;
695 			goto tryagain;
696 		}
697 	}
698 	else
699 #endif
700 	{
701 	    fprintf(OUTSTREAM,"(shared) ");
702 		gameboyscreen=XShmCreateImage(display,visual,resolution,
703 			ZPixmap,NULL,&shminfo,
704 			smallview ? GB_XBUFFERSIZE : GB_XBUFFERSIZE*2,
705 			smallview ? GB_LCDYSCREENSIZE : GB_LCDYSCREENSIZE*2);
706 	}
707 
708     if (gameboyscreen==NULL) {
709       use_xshm=0;
710       out_failed;
711       fprintf(OUTSTREAM,"Trying normal mode ...\n");
712       goto tryagain;
713     }
714 
715     shminfo.shmid=shmget(IPC_PRIVATE,gameboyscreen->bytes_per_line*
716 			 gameboyscreen->height,
717 			 IPC_CREAT|0777);
718 
719     if (shminfo.shmid<0) {
720       out_failed;
721       fprintf(OUTSTREAM,"Trying normal mode ...\n");
722       XDestroyImage(gameboyscreen);
723       use_xshm=0;
724       goto tryagain;
725     }
726 
727     lcdbuffer=shminfo.shmaddr=gameboyscreen->data=shmat(shminfo.shmid,0,0);
728 
729     if (!lcdbuffer) {
730       out_failed;
731       fprintf(OUTSTREAM,"Trying normal mode ...\n");
732       XDestroyImage(gameboyscreen);
733       shmctl(shminfo.shmid,IPC_RMID,0);
734       use_xshm=0;
735       goto tryagain;
736     }
737 
738     shminfo.readOnly=False;
739     old_handler=XSetErrorHandler(xerrorhandler);
740     XShmAttach(display,&shminfo);
741     XSync(display,False);
742     XShmPutImage(display,gbwin,gbgc,gameboyscreen,8,0,0,0,
743 		 1,1,0);
744     XSync(display,False);
745     XSetErrorHandler (old_handler);
746 
747     if (!use_xshm) {
748       out_failed;
749       fprintf(OUTSTREAM,"Trying normal mode ...\n");
750       XDestroyImage(gameboyscreen);
751       shmdt(shminfo.shmaddr);
752       shmctl(shminfo.shmid,IPC_RMID,0);
753       goto tryagain;
754     } else fprintf(OUTSTREAM,"shared OK\n");
755   } else {
756 
757 #endif
758 
759 	allocate_lcdbuffer();
760 	gameboyscreen=NULL;
761 
762 #ifdef WITH_XVIDEO
763 	xv_gameboyscreen=NULL;
764 	if (use_xvideo) {
765 		fprintf(OUTSTREAM,"(xv) ");
766 		xv_gameboyscreen=(XvImage *)XvCreateImage(display,
767 			xv_port, xv_format, lcdbuffer,
768 			GB_XBUFFERSIZE*2, GB_LCDYSCREENSIZE);
769 
770 		if (xv_gameboyscreen==NULL) {
771 			fprintf(OUTSTREAM,"screen allocation failed for XVideo"
772 				" trying X11\n Creating image buffer ... ");
773 			use_xvideo=0;
774 			free(lcdbuffer);
775 			goto tryagain;
776 		}
777 
778 	} else
779 #endif
780 	{
781 		fprintf(OUTSTREAM,"(x11) ");
782 		gameboyscreen=XCreateImage(display,visual,resolution,ZPixmap,
783 			0, lcdbuffer,
784 			smallview ? GB_XBUFFERSIZE : GB_XBUFFERSIZE*2,
785 			smallview ? GB_LCDYSCREENSIZE : GB_LCDYSCREENSIZE*2,
786 			bitmapbits,0);
787 	}
788 
789 #ifdef MIT_SHM
790   }
791 #endif
792 
793 
794   fprintf(OUTSTREAM,"Preparing image ... ");
795   if (!use_xvideo) {
796 	  fprintf(OUTSTREAM,"X11 ... ");
797 	  if (gameboyscreen) out_ok; else {
798 		  out_failed;
799 		  return 1;
800 	  }
801   } else {
802 	  fprintf(OUTSTREAM,"XVideo (using %d bytes) ... ",
803 	  	xv_gameboyscreen->data_size);
804 	  if (!xv_gameboyscreen) {
805 		  out_failed;
806 		  return 1;
807 	  }
808 
809 	  if (xv_gameboyscreen->data_size>lcdbuffersize) {
810 		  out_failed;
811 		  return 1;
812 	  }
813 
814 	  doublesize=0;
815 	  smallview=1;
816 	  out_ok;
817   }
818 
819 #ifndef DEBUG
820   XAutoRepeatOff(display);
821 #endif
822   return 0;
823 }
824 #endif
825 
initsys(void)826 int initsys(void)
827 {
828   int retval;
829 #ifdef JOYSTICK
830   int status;
831   struct JS_DATA_SAVE_TYPE_32 jsd;
832 #endif
833 
834   doublesize=0;
835 #if defined(GLIDE) && !defined(DEBUG)
836   retval=initGlide();
837 #else
838   if ((retval=InitXConnection())!=0) return 1;
839   if (!retval
840 #ifdef FRAMEBUFFER
841       && !usingfb
842 #endif
843                ) retval=InitXRessources();
844 #endif
845 
846 #ifdef MIT_SHM
847   if (use_xshm)
848 #endif
849      fprintf(OUTSTREAM,"Buffer allocation ... ");
850 
851   if (lcdbuffer==NULL) {
852     out_failed;
853     retval=1;
854   } else out_ok;
855 
856   /* B/W palette initialisation */
857   GB_STDPAL[0]=color_translate(0x7FFF);
858   GB_STDPAL[1]=color_translate(0x56B5);
859   GB_STDPAL[2]=color_translate(0x2D6B);
860   GB_STDPAL[3]=color_translate(0x0000);
861 
862   usejoypad=0;
863 #if defined JOYSTICK || defined BSD_JOYSTICK
864   fprintf(OUTSTREAM,"Opening joypad device ... ");
865   joypaddev=open(joy_device,O_RDONLY);
866   if (joypaddev<0) {
867     out_failed;
868   } else {
869     out_ok;
870 #ifdef JOYSTICK
871     fprintf(OUTSTREAM,"Reading joystick info ... ");
872     status=ioctl(joypaddev,JS_GET_ALL,&jsd);
873     if (status<0) {
874       out_failed;
875       close(joypaddev);
876     } else {
877       out_ok;
878       usejoypad=1;
879     }
880 #endif
881 #ifdef BSD_JOYSTICK
882       usejoypad=1;
883 #endif
884   }
885 #endif
886 
887 #ifdef GLIDE
888   if (!usejoypad) {
889     doneGlide();
890     return 1;
891   }
892 #endif
893 
894   signal(SIGHUP,DoBreak);signal(SIGINT,DoBreak);
895   signal(SIGQUIT,DoBreak);signal(SIGTERM,DoBreak);
896   signal(SIGPIPE,DoBreak);
897 
898 #ifdef __SVR4
899   sigset(SIGALRM,timerhandler);
900 #else
901   signal(SIGALRM,timerhandler);
902 #endif
903 
904 
905   itv.it_value.tv_usec=20000;
906   itv.it_value.tv_sec=0;
907   itv.it_interval.tv_usec=20000;
908   itv.it_interval.tv_sec=0;
909   timerset=setitimer(ITIMER_REAL,&itv,NULL);
910   refreshtimer=0;
911   if (timerset<0) {
912     fprintf(OUTSTREAM,"setitimer() failed./n");
913     fprintf(OUTSTREAM,"no real-time emulation will be available.\n");
914   }
915 
916 
917 #ifdef SOUND
918   if (producesound) {
919     fprintf(OUTSTREAM,"Initialize sound emulation ... \n");
920     usingsound=initsound();
921     fprintf(OUTSTREAM,"Sound %s\n",usingsound ? "OK" : "FAILED");
922   }
923 #endif
924 
925 #ifdef DIALOGLINK
926   if (dialoglink)
927     dlglink_status=dlglink_init();
928 #endif
929 
930   return retval;
931 }
932 
933 #ifndef GLIDE
DoneXConnection(void)934 void DoneXConnection(void)
935 {
936 #ifndef DEBUG
937   XAutoRepeatOn(display);
938 #endif
939 
940 #ifdef WITH_XVIDEO
941 	fprintf(OUTSTREAM, "Freeing XVideo ressources ... ");
942 	if (use_xvideo && xv_port) {
943 		XvUngrabPort(display, xv_port, CurrentTime);
944 	}
945 #endif
946 
947 #ifdef VERBOSE
948   fprintf(OUTSTREAM,"Destroying window and freeing memory ... ");
949 #endif
950 
951 #ifdef MIT_SHM
952   if (use_xshm) {
953     XShmDetach(display,&shminfo);
954   }
955 #endif
956 
957 #ifdef WITH_XVIDEO
958 	if (!use_xvideo)
959 #endif
960 	  XDestroyImage(gameboyscreen);
961 
962 #ifdef MIT_SHM
963   if (use_xshm) {
964     shmdt(shminfo.shmaddr);
965     shmctl(shminfo.shmid,IPC_RMID,0);
966   }
967 #endif
968 
969   XUnmapWindow(display,gbwin);
970   XDestroyWindow(display,gbwin);
971   XFreeGC(display,gbgc);
972   if (bitmapbits==8) {
973     XFreeColormap(display,colormap);
974     free(colors);
975   }
976 #ifdef VERBOSE
977   out_ok;
978 #endif
979 
980 #ifdef VERBOSE
981   fprintf(OUTSTREAM,"Shutting down X-connection ... ");fflush(stdout);
982 #endif
983   XCloseDisplay(display);
984 #ifdef VERBOSE
985   out_ok;
986 #endif
987 }
988 #endif
989 
donesys(void)990 void donesys(void)
991 {
992 #ifdef DIALOGLINK
993   switch (dlglink_status) {
994   case 1:
995     close(sock_nd);
996     close(sock_d);
997     break;
998   case 2:
999     close(sock_d);
1000     break;
1001   }
1002 #endif
1003 
1004 #ifdef SOUND
1005   if (producesound) {
1006     fprintf(OUTSTREAM,"Closing sound.\n");
1007     donesound();
1008   }
1009 #endif
1010 
1011 
1012 #if defined JOYSTICK || defined BSD_JOYSTICK
1013 #ifdef VERBOSE
1014   fprintf(OUTSTREAM,"Closing joypad device ... ");
1015 #endif
1016   if (joypaddev>0) close(joypaddev);
1017   out_ok;
1018 #endif
1019 
1020 
1021 #ifdef GLIDE
1022     doneGlide();
1023 #else
1024 #ifdef FRAMEBUFFER
1025   if (!usingfb)
1026 #endif
1027     DoneXConnection();
1028 #ifdef FRAMEBUFFER
1029   else DoneFB();
1030 #endif
1031 #endif
1032 }
1033 
color_translate(unsigned short int gbcol)1034 unsigned int color_translate(unsigned short int gbcol)
1035 {
1036 	/* hope, it works now for every type of visual */
1037 
1038 	if (!use_xvideo) {
1039 
1040 		if (bitmapbits>8)
1041 			return (((gbcol&0x1F)<<REDSHL)<<REDOFS)|
1042 				((((gbcol>>5)&0x1F)<<GREENSHL)<<GREENOFS)|
1043 				((((gbcol>>10)&0x1F)<<BLUESHL)<<BLUEOFS);
1044 		else
1045 			return ((gbcol&0x1F)/6)*36+(((gbcol>>5)&0x1F)/6)*6+
1046 				((gbcol>>10)&0x1F)/6;
1047 	} else {
1048 		int r;
1049 		int g;
1050 		int b;
1051 
1052 		int y, u, v;
1053 
1054 		r=(gbcol&0x1F)<<3;
1055 		g=((gbcol>>5)&0x1F)<<3;
1056 		b=((gbcol>>10)&0x1F)<<3;
1057 
1058 		y = (((66*r+129*g+25*b)>>8)+16)&0xff;
1059 		u = (((-38*r-74*g+112*b)>>8)+128);
1060 		v = (((112*r-94*g-18*b)>>8)+128);
1061 
1062 		/*fprintf(stderr, "r: %d, g: %d, b: %d\n", r, g, b);
1063 		fprintf(stderr, "y: %d, u: %d, v: %d\n", y, u, v);*/
1064 
1065 		return (y<<24)|(y<<8)|u|(v<<16);
1066 
1067 		/* return (v<<24)|(y<<16)|(u<<8)|y; */
1068 
1069 	}
1070 }
1071 
drawscreen(void)1072 void drawscreen(void)
1073 {
1074 #ifndef GLIDE
1075 #ifdef FRAMEBUFFER
1076   int y;
1077   char *lcdpos,*buffer;
1078   register int x,v;
1079   char *buffer2;
1080 #endif
1081 
1082   if (doublesize
1083 #ifdef MIT_SHM
1084       && !use_xshm
1085 #endif
1086     ) {
1087     if (dsupdatenow++==0) return;
1088     if (dsupdatenow>2) dsupdatenow=0;
1089   }
1090 
1091   if (smallview) {
1092 #ifdef FRAMEBUFFER
1093     if (usingfb) {
1094       if (ttystate) {
1095 	for (y=0,buffer=fbgb,lcdpos=lcdbuffer+resolution;
1096 	     y<GB_LCDYSCREENSIZE;y++,buffer+=fb_finfo.line_length,
1097 	       lcdpos+=GB_XBUFFERSIZE*resolution/8) {
1098 	  memcpy(buffer,lcdpos,fbgb_linesize);
1099 	}
1100       }
1101     } else
1102 #endif
1103 
1104 #ifdef MIT_SHM
1105       if (use_xshm) {
1106 #ifdef WITH_XVIDEO
1107 	      if (use_xvideo)
1108 		      XvShmPutImage(display, xv_port, gbwin, gbgc,
1109 		      	xv_gameboyscreen, 16, 0,
1110 			GB_LCDXSCREENSIZE*2, GB_LCDYSCREENSIZE,
1111 			0,0,
1112 			win_width, win_height,
1113 			False);
1114 	      else
1115 #endif
1116 		      XShmPutImage(display,gbwin,gbgc,gameboyscreen,8,0,0,0,
1117 				      GB_LCDXSCREENSIZE,GB_LCDYSCREENSIZE,0);
1118       } else
1119 #endif
1120 
1121 #ifdef WITH_XVIDEO
1122       if (use_xvideo) {
1123 	      XvPutImage(display, xv_port, gbwin, gbgc,
1124 			      xv_gameboyscreen, 16, 0,
1125 			      GB_LCDXSCREENSIZE*2, GB_LCDYSCREENSIZE,
1126 			      0,0,
1127 				win_width, win_height);
1128       } else
1129 #endif
1130 	XPutImage(display,gbwin,gbgc,gameboyscreen,8,0,0,0,
1131 		  GB_LCDXSCREENSIZE,GB_LCDYSCREENSIZE);
1132   } else {
1133 #ifdef FRAMEBUFFER
1134     if (usingfb) {
1135       if (ttystate) {
1136 	for (y=0,buffer=fbgb,buffer2=fbgb+fb_finfo.line_length,
1137 	       lcdpos=lcdbuffer+resolution;
1138 	     y<GB_LCDYSCREENSIZE;y++,buffer+=fb_finfo.line_length<<1,
1139 	       buffer2+=fb_finfo.line_length<<1,
1140 	       lcdpos+=GB_XBUFFERSIZE*resolution/8) {
1141 	  switch (resolution) {
1142 	  case 8:
1143 	    for (x=0;x<GB_LCDXSCREENSIZE;x++) {
1144 	      v=((unsigned char *)lcdpos)[x];v|=v<<8;
1145 	      ((unsigned short int *)buffer)[x]=v;
1146 	      ((unsigned short int *)buffer2)[x]=v;
1147 	    }
1148 	    break;
1149 	  case 16:
1150 	    for (x=0;x<GB_LCDXSCREENSIZE;x++) {
1151 	      v=((unsigned short int *)lcdpos)[x];v|=v<<16;
1152 	      ((unsigned int *)buffer)[x]=v;
1153 	      ((unsigned int *)buffer2)[x]=v;
1154 	    }
1155 	    break;
1156 	  case 32:
1157 	    for (x=0;x<(GB_LCDXSCREENSIZE<<1);x+=2) {
1158 	      v=((unsigned int *)lcdpos)[x>>1];
1159 	      ((unsigned int *)buffer)[x]=v;
1160 	      ((unsigned int *)buffer)[x+1]=v;
1161 	      ((unsigned int *)buffer2)[x]=v;
1162 	      ((unsigned int *)buffer2)[x+1]=v;
1163 	    }
1164 	    break;
1165 	  }
1166 	}
1167       }
1168     } else
1169 #endif
1170 
1171 #ifdef MIT_SHM
1172       if (use_xshm) {
1173 	      XShmPutImage(display,gbwin,gbgc,gameboyscreen,16,0,0,0,
1174 			      GB_LCDXSCREENSIZE*2,GB_LCDYSCREENSIZE*2,
1175 			      0);
1176       } else
1177 #endif
1178 	      XPutImage(display,gbwin,gbgc,gameboyscreen,16,0,0,0,
1179 			      GB_LCDXSCREENSIZE*2,GB_LCDYSCREENSIZE*2);
1180   }
1181 
1182 #ifdef FRAMEBUFFER
1183   if (!usingfb)
1184 #endif
1185     /*    XFlush(display);*/
1186 #else
1187   /* Glide version of drawscreen *********************************** */
1188 
1189   GrLfbInfo_t info;
1190   unsigned short int *buffer,*buffer2,*lcdpos;
1191   register int x,y;
1192   register unsigned int v;
1193 
1194   if (!grLfbLock(GR_LFB_WRITE_ONLY,GR_BUFFER_BACKBUFFER,
1195 		 GR_LFBWRITEMODE_565,GR_ORIGIN_UPPER_LEFT,
1196 		 FXFALSE,&info)) {
1197     grGlideShutdown();
1198     printf("Lock failed.\n");
1199     ABORT_EMULATION=1;
1200     return;
1201   }
1202   buffer=info.lfbPtr+((240-GB_LCDYSCREENSIZE)*info.strideInBytes)+
1203     320-(GB_LCDXSCREENSIZE>>1);
1204   buffer2=buffer+(info.strideInBytes>>1);
1205 
1206   for (y=0,lcdpos=(unsigned short int *)(lcdbuffer+resolution);
1207        y<GB_LCDYSCREENSIZE;y++,
1208 	 buffer+=info.strideInBytes,buffer2+=info.strideInBytes,
1209 	 lcdpos+=GB_XBUFFERSIZE) {
1210     for (x=0;x<GB_LCDXSCREENSIZE;x++) {
1211       v=lcdpos[x];v|=v<<16;
1212       ((unsigned int *)buffer)[x]=v;
1213       ((unsigned int *)buffer2)[x]=v;
1214     }
1215   }
1216 
1217   grLfbUnlock(GR_LFB_WRITE_ONLY,GR_BUFFER_BACKBUFFER);
1218   grBufferSwap(1);
1219 #endif
1220 
1221   if (usingsound) return;
1222 
1223   if (timerset>=0) {
1224       while (refreshtimer<1); /* sync loop */
1225   } else {
1226       while (refreshtimer<3); /* sync loop */
1227   }
1228   refreshtimer=0;
1229 }
1230 
joypad(void)1231 void joypad(void)
1232 {
1233 #if defined JOYSTICK || defined BSD_JOYSTICK
1234   int status;
1235 #endif
1236 #if defined(FRAMEBUFFER) || defined (GLIDE)
1237   int retval;
1238   fd_set rfds;
1239   struct timeval tv;
1240 #endif
1241 #ifndef GLIDE
1242   XEvent E;
1243 
1244 #ifdef FRAMEBUFFER
1245   if (!usingfb) {
1246 #endif
1247   while (XCheckWindowEvent(display,gbwin,KeyPressMask,&E)) {
1248     usekeys=1;
1249     switch(XLookupKeysym((XKeyEvent *)&E,0)) {
1250     case GBPAD_up:
1251       newjoypadstate&=0xBF;
1252       break;
1253     case GBPAD_down:
1254       newjoypadstate&=0x7F;
1255       break;
1256     case GBPAD_left:
1257       newjoypadstate&=0xDF;
1258       break;
1259     case GBPAD_right:
1260       newjoypadstate&=0xEF;
1261       break;
1262     case GBPAD_a:
1263       newjoypadstate&=0xFE;
1264       break;
1265     case GBPAD_b:
1266       newjoypadstate&=0xFD;
1267       break;
1268     case GBPAD_start:
1269       newjoypadstate&=0xF7;
1270       break;
1271     case GBPAD_select:
1272       newjoypadstate&=0xFB;
1273       break;
1274     case XK_Escape:
1275     case XK_q:
1276       usekeys=0;
1277       DoBreak(0);
1278       break;
1279     case XK_Return:
1280       ar_enabled=ar_enabled ? 0 : 1;
1281       break;
1282 #ifdef DEBUG
1283     case XK_b:
1284       breakpoint=-1;
1285       skipover=0;
1286       usekeys=0;
1287       break;
1288     case XK_t:
1289       db_trace=db_trace ? 0 : 1;
1290       usekeys=0;
1291       break;
1292 #endif
1293     }
1294   }
1295 
1296   while (XCheckWindowEvent(display,gbwin,KeyReleaseMask,&E)) {
1297     switch(XLookupKeysym((XKeyEvent *)&E,0)) {
1298     case GBPAD_up:
1299       newjoypadstate|=0x40;
1300       break;
1301     case GBPAD_down:
1302       newjoypadstate|=0x80;
1303       break;
1304     case GBPAD_left:
1305       newjoypadstate|=0x20;
1306       break;
1307     case GBPAD_right:
1308       newjoypadstate|=0x10;
1309       break;
1310     case GBPAD_a:
1311       newjoypadstate|=0x01;
1312       break;
1313     case GBPAD_b:
1314       newjoypadstate|=0x02;
1315       break;
1316     case GBPAD_start:
1317       newjoypadstate|=0x08;
1318       break;
1319     case GBPAD_select:
1320       newjoypadstate|=0x04;
1321       break;
1322     }
1323     if (newjoypadstate==0xFF) usekeys=0;
1324   }
1325 
1326   while (XCheckWindowEvent(display, gbwin, StructureNotifyMask, &E)) {
1327 	  if (E.type==ConfigureNotify) {
1328 		  win_width=E.xconfigure.width;
1329 		  win_height=E.xconfigure.height;
1330 	  }
1331   }
1332 #ifdef FRAMEBUFFER
1333   }
1334 #endif
1335 #endif
1336 
1337 #if defined(FRAMEBUFFER) || defined(GLIDE)
1338 #ifdef FRAMEBUFFER
1339   if (usingfb) {
1340 #endif
1341     FD_ZERO(&rfds);
1342     FD_SET(0,&rfds);
1343     tv.tv_sec=0;tv.tv_usec=0;
1344     retval=select(1,&rfds,NULL,NULL,&tv);
1345 
1346     if (retval) {
1347       read(0,&retval,1);
1348       /*
1349       printf("Pressed: %i\n",retval&0xFF);
1350       */
1351 
1352       switch (retval&0xFF) {
1353       case 27:
1354 	FD_ZERO(&rfds);
1355 	FD_SET(0,&rfds);
1356 	tv.tv_sec=0;tv.tv_usec=0;
1357 	retval=select(1,&rfds,NULL,NULL,&tv);
1358 	if (retval) {
1359 	  read(0,&retval,1);
1360 	  read(0,&retval,1);
1361 	  switch (retval&0xFF) {
1362 	    /*  case 65:printf("up\n");break;
1363 	  case 66:printf("down\n");break;
1364 	  case 67:printf("right\n");break;
1365 	  case 68:printf("left\n");break;*/
1366 	  }
1367 	} else DoBreak(0);
1368 	break;
1369       case 113:
1370 	DoBreak(0);
1371 	break;
1372       case 13:
1373 	ar_enabled=ar_enabled ? 0 : 1;
1374 	break;
1375       }
1376     }
1377 #ifdef FRAMEBUFFER
1378   }
1379 #endif
1380 #endif
1381 
1382 
1383 #if defined JOYSTICK || defined BSD_JOYSTICK
1384   if (usejoypad && (!usekeys)) {
1385 #ifdef JOYSTICK
1386     status=read(joypaddev,&js,JS_RETURN);
1387     if (status==JS_RETURN) {
1388       newjoypadstate=
1389 	(js.x<joy_left   ? 0 : 0x20)|
1390 	(js.x>joy_right  ? 0 : 0x10)|
1391 	(js.y<joy_top    ? 0 : 0x40)|
1392 	(js.y>joy_bottom ? 0 : 0x80)|
1393 	(js.buttons & joy_buttonA      ? 0 : 0x01)|
1394 	(js.buttons & joy_buttonB      ? 0 : 0x02)|
1395 	(js.buttons & joy_buttonSTART  ? 0 : 0x08)|
1396 	(js.buttons & joy_buttonSELECT ? 0 : 0x04);
1397     }
1398 #else
1399     status=read(joypaddev,&js,sizeof(struct joystick));
1400     if (status==sizeof(struct joystick)) {
1401       int buttons;
1402 
1403       buttons=(js.b1&0xFF)|((js.b2&0xFF)<<8);
1404 
1405       newjoypadstate=
1406 	(js.x<joy_left   ? 0 : 0x20)|
1407 	(js.x>joy_right  ? 0 : 0x10)|
1408 	(js.y<joy_top    ? 0 : 0x40)|
1409 	(js.y>joy_bottom ? 0 : 0x80)|
1410 	(buttons & joy_buttonA      ? 0 : 0x01)|
1411 	(buttons & joy_buttonB      ? 0 : 0x02)|
1412 	(buttons & joy_buttonSTART  ? 0 : 0x08)|
1413 	(buttons & joy_buttonSELECT ? 0 : 0x04);
1414     }
1415 #endif
1416   }
1417 #endif
1418 }
1419 
1420 #ifndef GLIDE
vramdump(tilescreen,dataofs)1421 void vramdump(tilescreen,dataofs)
1422 int tilescreen;
1423 int dataofs;
1424 {
1425   char *dumpwintitle="VRAM dump";
1426   Window dumpwin;
1427   XSetWindowAttributes gbwinattr;
1428   XTextProperty prop_wintitle;
1429   XEvent E;
1430   int x,y,xx,yy;
1431   GC gc;
1432   XGCValues gcval;
1433   uchar *tileofs,*tile,*tdofs;
1434   uchar scan1,scan2;
1435 
1436 #ifdef FRAMEBUFFER
1437   if (usingfb) return;
1438 #endif
1439 
1440   gbwinattr.event_mask=ExposureMask|KeyPressMask;
1441   gbwinattr.colormap=colormap;
1442   gbwinattr.border_pixel=0;
1443   dumpwin=XCreateWindow(display,
1444 		      RootWindow(display,screen),
1445 		      300,50,256,256,
1446 		      0,resolution,
1447 		      InputOutput,
1448 			    visual,
1449 		      CWEventMask|
1450 		      CWColormap|
1451 		      CWBorderPixel,
1452 		      &gbwinattr);
1453 
1454   if (!dumpwin) return;
1455 
1456   XStringListToTextProperty(&dumpwintitle,1,&prop_wintitle);
1457   XSetWMName(display,dumpwin,&prop_wintitle);
1458   XSelectInput(display,dumpwin,ExposureMask|KeyPressMask);
1459   XMapRaised(display,dumpwin);
1460   XWindowEvent(display,dumpwin,ExposureMask,&E);
1461 
1462   gcval.background=0;
1463   gc=XCreateGC(display,dumpwin,GCBackground,&gcval);
1464 
1465   tileofs=vram[0]+0x1800+(tilescreen ? 0x400 : 0);
1466   tdofs=vram[0]+(dataofs ? 0x0000 : 0x1000);
1467   for (y=0;y<32;y++)
1468     for (x=0;x<32;x++) {
1469       tile=tdofs+(dataofs ? (int)tileofs[y*32+x]*16 :
1470 	(int)((signed char)tileofs[y*32+x])*16);
1471       for (yy=0;yy<8;yy++) {
1472 	scan1=(tile+yy*2)[0];
1473 	scan2=(tile+yy*2)[1];
1474 	for (xx=0;xx<8;xx++) {
1475 	  gcval.foreground=GB_STDPAL[3-(
1476 		(BGP>>
1477 		((3-(((scan1>>(7-xx))&1)|(((scan2>>(7-xx))&1)<<1)))*2))&3)
1478 	  ];
1479 	  XChangeGC(display,gc,GCForeground,&gcval);
1480 	  XDrawLine(display,dumpwin,gc,x*8+xx,y*8+yy,
1481 		    x*8+xx,y*8+yy);
1482 	}
1483       }
1484     }
1485 
1486   XFreeGC(display,gc);
1487   while (1) {
1488     XNextEvent(display,&E);
1489     if (E.type==KeyPress) break;
1490   }
1491   fprintf(OUTSTREAM,"exited.\n");
1492   XDestroyWindow(display,dumpwin);
1493 }
1494 #endif
1495 
1496 #ifdef DIALOGLINK
1497 
dlglink_getbyte(void)1498 int dlglink_getbyte(void)
1499 {
1500   int c=0;
1501   fd_set fds;
1502   struct timeval tv;
1503 
1504   FD_ZERO(&fds);
1505   FD_SET(sock_desc,&fds);
1506   tv.tv_sec=0;tv.tv_usec=0;
1507 
1508   c=select(16,&fds,NULL,NULL,&tv);
1509 
1510   if (c<=0) return -1;
1511 
1512   if (recv(sock_desc,&c,1,0)<=0) return -1;
1513 
1514   return c;
1515 }
1516 
dlglink_sndbyte(int c)1517 void dlglink_sndbyte(int c)
1518 {
1519   while (send(sock_desc,&c,1,0)<=0);
1520 }
1521 
dlglink_getstr(char * buf,int size)1522 void dlglink_getstr(char *buf,int size)
1523 {
1524   int n,ch;
1525 
1526   for (n=0;n<size;n++) {
1527     while ((ch=dlglink_getbyte())<0);
1528     buf[n]=ch;
1529   }
1530 }
1531 
dlglink_sndstr(char * buf,int size)1532 void dlglink_sndstr(char *buf,int size)
1533 {
1534   int n;
1535 
1536   for (n=0;n<size;n++) dlglink_sndbyte(buf[n]);
1537 }
1538 
1539 #define TCPPORT 9121
dlglink_init(void)1540 int dlglink_init(void)
1541 {
1542   struct sockaddr_in sock_name;
1543   int n;
1544   socklen_t sock_len;
1545   struct hostent *sock_hp;
1546   char buffer[64];
1547 
1548   if ((sock_d=socket(AF_INET,SOCK_STREAM,0))<0) {
1549     fprintf(OUTSTREAM,"Error: socket initialization failed.\n");
1550     fprintf(OUTSTREAM,"No dialog link supported.\n");
1551     exit(1);
1552   }
1553 
1554   sock_len=sizeof(struct sockaddr_in);
1555 
1556   if (strlen(servername)==0) {
1557     /* server side init */
1558 
1559     memset(&sock_name,0,sizeof(struct sockaddr_in));
1560 
1561     sock_name.sin_family=AF_INET;
1562     sock_name.sin_port=htons(TCPPORT);
1563     n=INADDR_ANY;
1564     memcpy(&sock_name.sin_addr,&n,sizeof(n));
1565 
1566     if (bind(sock_d,(struct sockaddr *)&sock_name,sock_len)<0) {
1567       fprintf(OUTSTREAM,"Error: bind to port %i failed.\n",TCPPORT);
1568       close(sock_d);
1569       exit(1);
1570     }
1571 
1572     if (listen(sock_d,1)<0) {
1573       fprintf(OUTSTREAM,"Error: listen on port %i failed.\n",TCPPORT);
1574       close(sock_d);
1575       exit(1);
1576     }
1577 
1578     fprintf(OUTSTREAM,"Waiting for the other side ... ");
1579     if ((sock_nd=accept(sock_d,(struct sockaddr *)&sock_name,&sock_len))<0) {
1580       out_failed;
1581       close(sock_d);
1582       exit(1);
1583     } else out_ok;
1584 
1585 
1586     sock_desc=sock_nd;
1587 
1588     dlglink_sndstr(sock_tcpsignature,strlen(sock_tcpsignature)+1);
1589     dlglink_getstr(buffer,strlen(sock_tcpsignature)+1);
1590 
1591     if (strcmp(buffer,sock_tcpsignature)) {
1592       fprintf(OUTSTREAM,"Not a cingb-socket ?\nReceived: %s\n",buffer);
1593       close(sock_d);
1594       exit(1);
1595     }
1596 
1597     fprintf(OUTSTREAM,"Connection established.\n");
1598 
1599     return 1;
1600 
1601   } else {
1602     /* client side init */
1603 
1604     if ((sock_hp=gethostbyname(servername))==NULL) {
1605       fprintf(OUTSTREAM,"Error: unknown host %s.\n",servername);
1606       fprintf(OUTSTREAM,"Closing emulation.\n");
1607       close(sock_d);
1608       exit(1);
1609     }
1610 
1611     memset(&sock_name,0,sizeof(struct sockaddr_in));
1612 
1613     sock_name.sin_family=AF_INET;
1614     sock_name.sin_port=htons(TCPPORT);
1615     memcpy(&sock_name.sin_addr,sock_hp->h_addr_list[0],sock_hp->h_length);
1616 
1617     fprintf(OUTSTREAM,"Trying to connect to server ... ");
1618     if (connect(sock_d,(struct sockaddr *)&sock_name,sock_len)<0) {
1619       out_failed;
1620       close(sock_d);
1621       exit(1);
1622     } else out_ok;
1623 
1624     sock_desc=sock_d;
1625 
1626     dlglink_getstr(buffer,strlen(sock_tcpsignature)+1);
1627 
1628     if (strcmp(buffer,sock_tcpsignature)) {
1629       fprintf(OUTSTREAM,"Not a cingb-socket ?\nReceived: %s\n",buffer);
1630       close(sock_d);
1631       exit(1);
1632     }
1633     dlglink_sndstr(sock_tcpsignature,strlen(sock_tcpsignature)+1);
1634 
1635     fprintf(OUTSTREAM,"Connection established.\n");
1636 
1637     return 2;
1638   }
1639 }
1640 #endif /* DIALOGLINK */
1641 
1642 #endif /* UNIX */
1643