/** VGB: portable GameBoy emulator ***************************/ /** **/ /** Unix.c **/ /** **/ /** This file contains Unix/X-dependent subroutines and **/ /** drivers. **/ /** **/ /** Copyright (C) Marat Fayzullin 1994,1995,1996 **/ /** Elan Feingold 1995 **/ /** You are not allowed to distribute this software **/ /** commercially. Please, notify me, if you make any **/ /** changes to this file. **/ /*************************************************************/ #define USE_XPAL /* We are using XPal[] to determine colors */ /** Standard Unix/X #includes ********************************/ #include #include #include #include #include #include #include #include #include "GB.h" /** MIT Shared Memory Extension for X ************************/ #ifdef MITSHM #include #include #include XShmSegmentInfo SHMInfo; int UseSHM=1; #endif /** Various X-related variables ******************************/ Display *Dsp; Window Wnd; Colormap DefaultCMap; XImage *Img; GC DefaultGC; unsigned long White,Black; /** Various variables and short functions ********************/ #define WIDTH 176 /* Width (>=176, must be divisible by 8) */ #define HEIGHT 144 /* Height (>=144) */ char *Title = "Virtual GameBoy Unix/X 0.7"; int SaveCPU = 1; byte *XBuf,*ZBuf,XPal[12]; char *ColorNames[12] = { "white","#989898","#585858","black", "white","#989898","#585858","black", "white","#989898","#585858","black" }; void OnBreak(int Arg) { CPURunning=0; } /** InitMachine **********************************************/ /** Allocate resources needed by Unix/X-dependent code. **/ /*************************************************************/ int InitMachine() { Screen *Scr; XEvent E; XGCValues values; XColor Color,C; int J; if(Verbose) printf("Initializing Unix/X drivers:\n Opening display..."); Dsp=XOpenDisplay(NULL); if(!Dsp) { if(Verbose) printf("FAILED\n");return(0); } Scr=DefaultScreenOfDisplay(Dsp); White=WhitePixelOfScreen(Scr); Black=BlackPixelOfScreen(Scr); DefaultGC=DefaultGCOfScreen(Scr); DefaultCMap=DefaultColormapOfScreen(Scr); if(Verbose) printf("OK\n Opening window..."); Wnd= XCreateSimpleWindow (Dsp,RootWindowOfScreen(Scr),0,0,160,144,0,White,Black); if(!Wnd) { if(Verbose) printf("FAILED\n");return(0); } { XSizeHints Hints; XWMHints WMHints; Hints.flags=PSize|PMinSize|PMaxSize; Hints.min_width=Hints.max_width=Hints.base_width=160; Hints.min_height=Hints.max_height=Hints.base_height=144; WMHints.input=True;WMHints.flags=InputHint; XSetWMHints(Dsp,Wnd,&WMHints); XSetWMNormalHints(Dsp,Wnd,&Hints); XStoreName(Dsp,Wnd,Title); } XSelectInput (Dsp,Wnd,FocusChangeMask|ExposureMask|KeyPressMask|KeyReleaseMask); XMapRaised(Dsp,Wnd); XClearWindow(Dsp,Wnd); XAutoRepeatOff(Dsp); XWindowEvent(Dsp,Wnd,ExposureMask,&E); if(Verbose) printf("OK\n Allocating Z-buffer..."); if(!(ZBuf=malloc(2*WIDTH*HEIGHT/8))) return(0); #ifdef MITSHM if(UseSHM) { if(Verbose) printf("OK\n Using shared memory:\n Creating image..."); Img= XShmCreateImage (Dsp,DefaultVisualOfScreen(Scr),8,ZPixmap,NULL,&SHMInfo,WIDTH,HEIGHT); if(!Img) { if(Verbose) printf("FAILED\n");return(0); } if(Verbose) printf("OK\n Getting SHM info..."); SHMInfo.shmid= shmget(IPC_PRIVATE,Img->bytes_per_line*Img->height,IPC_CREAT|0777); if(SHMInfo.shmid<0) { if(Verbose) printf("FAILED\n");return(0); } if(Verbose) printf("OK\n Allocating SHM..."); XBuf=(byte *)(Img->data=SHMInfo.shmaddr=shmat(SHMInfo.shmid,0,0)); if(!XBuf) { if(Verbose) printf("FAILED\n");return(0); } SHMInfo.readOnly=False; if(Verbose) printf("OK\n Attaching SHM..."); if(!XShmAttach(Dsp,&SHMInfo)) { if(Verbose) printf("FAILED\n");return(0); } } else #endif { if(Verbose) printf("OK\n Allocating screen buffer..."); XBuf=(byte *)malloc(sizeof(byte)*HEIGHT*WIDTH); if(!XBuf) { if(Verbose) printf("FAILED\n");return(0); } if(Verbose) printf("OK\n Creating image..."); Img= XCreateImage (Dsp,DefaultVisualOfScreen(Scr),8,ZPixmap,0,XBuf,WIDTH,HEIGHT,8,0); if(!Img) { if(Verbose) printf("FAILED\n");return(0); } } if(Verbose) puts("OK"); for(J=0;J<12;J++) XPal[J]=XAllocNamedColor(Dsp,DefaultCMap,ColorNames[J],&Color,&C)? Color.pixel : J&2? White:Black; signal(SIGHUP,OnBreak);signal(SIGINT,OnBreak); signal(SIGQUIT,OnBreak);signal(SIGTERM,OnBreak); return(1); } /** TrashMachine *********************************************/ /** Deallocate all resources taken by InitMachine(). **/ /*************************************************************/ void TrashMachine() { if(Verbose) printf("Shutting down...\n"); if(Dsp&&Wnd) { #ifdef MITSHM if(UseSHM) { XShmDetach(Dsp,&SHMInfo); if(SHMInfo.shmaddr) shmdt(SHMInfo.shmaddr); if(SHMInfo.shmid>=0) shmctl(SHMInfo.shmid,IPC_RMID,0); } else #endif MITSHM if(Img) XDestroyImage(Img); } if(ZBuf) free(ZBuf); if(Dsp) { XAutoRepeatOn(Dsp);XCloseDisplay(Dsp); } } /** PutImage *************************************************/ /** Put an image on the screen. **/ /*************************************************************/ void PutImage() { #ifdef MITSHM if(UseSHM) XShmPutImage(Dsp,Wnd,DefaultGC,Img,(WIDTH-160)/2,0,0,0,160,144,False); else #endif XPutImage(Dsp,Wnd,DefaultGC,Img,(WIDTH-160)/2,0,0,0,160,144); XFlush(Dsp); } /** Joystick *************************************************/ /** Return the current joystick state. **/ /*************************************************************/ byte Joystick(void) { static byte JoyState = 0xFF; XEvent E; word J; if(XCheckWindowEvent(Dsp,Wnd,KeyPressMask|KeyReleaseMask,&E)) { J=XLookupKeysym((XKeyEvent *)&E,0); if(E.type==KeyPress) switch(J) { case XK_F12: case XK_Escape: CPURunning=0;break; #ifdef DEBUG case XK_F1: Trace=!Trace;break; case XK_F2: puts("\033[H\033[2J*** REGISTERS: ***"); for(J=0xFF40;J<0xFF50;J++) printf("(%Xh) = %Xh\n",J,RAM[J]); printf("ISWITCH = %Xh\n",ISWITCH); break; case XK_F3: puts("\033[H\033[2J*** SPRITES: ***"); for(J=0xFE9C;J<0xFE9C+4*40;J+=4) printf ( "SPRITE %d: %d,%d Pat %d Attr %d\n", (J-0xFE9C)/4,RAM[J+1],RAM[J],RAM[J+2],RAM[J+3] ); break; #endif case XK_Return: JoyState&=0x7F;break; case XK_Tab: JoyState&=0xBF;break; case XK_Down: JoyState&=0xF7;break; case XK_Up: JoyState&=0xFB;break; case XK_Left: JoyState&=0xFD;break; case XK_Right: JoyState&=0xFE;break; case XK_z: case XK_x: case XK_c: case XK_v: case XK_b: case XK_n: case XK_m: case XK_Z: case XK_X: case XK_C: case XK_V: case XK_B: case XK_N: case XK_M: case XK_Alt_L: JoyState&=0xDF;break; case XK_a: case XK_s: case XK_d: case XK_f: case XK_g: case XK_h: case XK_j: case XK_A: case XK_S: case XK_D: case XK_F: case XK_G: case XK_H: case XK_J: case XK_space: JoyState&=0xEF;break; } else switch(J) { case XK_Return: JoyState|=0x80;break; case XK_Tab: JoyState|=0x40;break; case XK_Down: JoyState|=0x08;break; case XK_Up: JoyState|=0x04;break; case XK_Left: JoyState|=0x02;break; case XK_Right: JoyState|=0x01;break; case XK_z: case XK_x: case XK_c: case XK_v: case XK_b: case XK_n: case XK_m: case XK_Z: case XK_X: case XK_C: case XK_V: case XK_B: case XK_N: case XK_M: case XK_Alt_L: JoyState|=0x20;break; case XK_a: case XK_s: case XK_d: case XK_f: case XK_g: case XK_h: case XK_j: case XK_A: case XK_S: case XK_D: case XK_F: case XK_G: case XK_H: case XK_J: case XK_space: JoyState|=0x10;break; } } for(J=0;XCheckWindowEvent(Dsp,Wnd,FocusChangeMask,&E);) J=(E.type==FocusOut); if(SaveCPU&&J) { XAutoRepeatOn(Dsp); while(!XCheckWindowEvent(Dsp,Wnd,FocusChangeMask,&E)&&CPURunning) { if(XCheckWindowEvent(Dsp,Wnd,ExposureMask,&E)) PutImage(); XPeekEvent(Dsp,&E); } XAutoRepeatOff(Dsp); } return(JoyState); } /*** SIOSend ****************************************************/ /*** Send a byte onto the serial line. ***/ /****************************************************************/ byte SIOSend(register byte V) { return(0); } /*** SIOReceive *************************************************/ /*** Receive a byte from the serial line. Returns 1 on ***/ /*** success, 0 otherwise. ***/ /****************************************************************/ byte SIOReceive(register byte *V) { return(0); } /****************************************************************/ /*** Write value into sound chip register (Reg #0 at FF10h). ***/ /****************************************************************/ void Sound(byte R,byte V) { return; } /** Common.h ****************************************************/ /** Parts of the drivers common for Unix/X and MSDOS. **/ /****************************************************************/ #include "Common.h"