/** ADAMEm: Coleco ADAM emulator ********************************************/ /** **/ /** X.c **/ /** **/ /** This file contains the X-Windows specific routines. It does not **/ /** include the sound emulation code **/ /** **/ /** Copyright (C) Marcel de Kogel 1996,1997,1998,1999 **/ /** You are not allowed to distribute this software commercially **/ /** Please, notify me, if you make any changes to this file **/ /****************************************************************************/ #include "Coleco.h" #include "X.h" #include "Bitmap.h" #include "Unix.h" #include #include #include #include #include #include #include #include /* Title for -help output */ char Title[]="ADAMEm Unix/X 1.0"; char szSnapshotFile[256]; /* Next snapshot file */ int videomode; /* 0=1x1 1=2x1 */ static int makesnap=0; /* 1 if snapshot should be written */ static int bpp; /* Bits per pixel of the display */ static Display *Dsp; /* Default display */ static Window Wnd; /* Our window */ static Colormap DefaultCMap; /* The display's default colours */ static XImage *Img; /* Our image */ static GC DefaultGC; /* The default graphics context */ static int White,Black; /* White and black colour values */ #ifdef MITSHM /* SHM extensions */ #include #include #include XShmSegmentInfo SHMInfo; int UseSHM=1; #endif /* These functions are used to put a pixel on the image buffer */ typedef void (*PutPixelProcFn) (int offset,int c) FASTCALL; static void PutPixel32_0 (int offset,int c) FASTCALL; static void PutPixel16_0 (int offset,int c) FASTCALL; static void PutPixel8_0 (int offset,int c) FASTCALL; static void PutPixel32_1 (int offset,int c) FASTCALL; static void PutPixel16_1 (int offset,int c) FASTCALL; static void PutPixel8_1 (int offset,int c) FASTCALL; static void PutPixel32_2 (int offset,int c) FASTCALL; static void PutPixel16_2 (int offset,int c) FASTCALL; static void PutPixel8_2 (int offset,int c) FASTCALL; static void (*PutPixelProc)(int offset,int c) FASTCALL; #define PutPixel(P,C) (*PutPixelProc)(P,C) static PutPixelProcFn PutPixelProcTable[][3]= { { PutPixel8_0, PutPixel16_0, PutPixel32_0 }, { PutPixel8_1, PutPixel16_1, PutPixel32_1 }, { PutPixel8_2, PutPixel16_2, PutPixel32_2 } }; /* Key mapping */ static int KEY_LEFT,KEY_RIGHT,KEY_UP,KEY_DOWN, KEY_BUTTONA,KEY_BUTTONB,KEY_BUTTONC,KEY_BUTTOND; static int PalBuf[16],Pal0; /* Palette buffer */ static int default_mouse_sens=200;/* Default mouse sensitivity */ static int keyboardmode; /* 0=joystick, 1=keyboard */ static word MouseJoyState[2]; /* Current mouse status */ static word JoystickJoyState[2]; /* Current joystick status */ static int OldTimer=0; /* Last value of timer */ static int NewTimer=0; /* New value of timer */ static int calloptions=0; /* If 1, OptionsDialogue() is called */ static int width,height; /* width & height of the window */ byte *DisplayBuf; /* Screen buffer */ char szJoystickFileName[256]; /* File holding joystick information */ char *szKeys="1511531521540201E31E107A"; /* Key scancodes */ int mouse_sens=200; /* Mouse sensitivity */ int keypadmode=0; /* 1 if keypad should be reversed */ int joystick=1; /* Joystick support */ int calibrate=0; /* Set to 1 to force joystick calibration */ int swapbuttons=0; /* 1=joystick, 2=keyboard, 4=mouse */ int expansionmode=0; /* Expansion module emulated */ int syncemu=1; /* 0 if emulation shouldn't be synced */ int SaveCPU=1; /* If 1, save CPU when focus is out */ static void PutImage (void) { #ifdef MITSHM if (UseSHM) XShmPutImage (Dsp,Wnd,DefaultGC,Img,0,0,0,0,width,height,False); else #endif XPutImage (Dsp,Wnd,DefaultGC,Img,0,0,0,0,width,height); XFlush (Dsp); } /****************************************************************************/ /** Keyboard routines **/ /****************************************************************************/ static int PausePressed=0; static byte keybstatus[NR_KEYS]; static byte keyboard_buffer[16]; static int keyboard_buffer_count=0; static void LocalAddToKeyboardBuffer (byte ch) { keyboard_buffer[keyboard_buffer_count]=ch; keyboard_buffer_count=(keyboard_buffer_count+1)&15; keyboard_buffer[keyboard_buffer_count]=0; } static int LocalGetKeyboardChar (void) { int retval; keyboard_buffer_count=(keyboard_buffer_count-1)&15; retval=keyboard_buffer[keyboard_buffer_count]; keyboard_buffer[keyboard_buffer_count]=0; return retval; } static const byte scan2ascii[NR_KEYS] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /* 00 */ 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, /* 10 */ 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, /* 20 */ 0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, /* 30 */ 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47, /* 40 */ 0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57, /* 50 */ 0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67, /* 60 */ 0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F, 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77, /* 70 */ 0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 80 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 90 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* A0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* B0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* C0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* D0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* E0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* F0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF00 */ 8, 9,0x00,0x00,0x00, 13,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF10 */ 0x00,0x00,0x00, 27,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF20 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF30 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF40 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 146, 163, 160, 161, 162, 150, 149, 147, /* FF50 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00, 148,0x00,0x00,0x00,0x00, /* FF60 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF70 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF80 */ 0x00,0x00,0x00,0x00,0x00, 13,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF90 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FFA0 */ 0x00,0x00, '*', '+',0x00, '-', '.', '/', '0', 170, 162, 169, 163, 128, 161, 171, /* FFB0 */ 160, 168,0x00,0x00,0x00,0x00, 129, 130, 131, 132, 133, 134, 144, 145,0x00,0x00, /* FFC0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FFD0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FFE0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FFF0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00, 151 }; static const byte scan2ascii_shift[NR_KEYS] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /* 00 */ 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, /* 10 */ 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, 0x20,0x21,0x22,0x23,0x24,0x25,0x26, 34, /* 20 */ 0x28,0x29,0x2A,0x2B, '<', '_', '>', '?', ')', '!', '@', '#', '$', '%', '^', '&', /* 30 */ '*', '(',0x3A, ':',0x3C, '+',0x3E,0x3F, 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 40 */ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 50 */ 'x', 'y', 'z', '{', '|', '}',0x5E,0x5F, '~', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 60 */ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 70 */ 'X', 'Y', 'Z',0x7B,0x7C,0x7D,0x7E,0x7F, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 80 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 90 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* A0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* B0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* C0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* D0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* E0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* F0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF00 */ 184, 185,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF10 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF20 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF30 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF40 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 154,0x00,0x00,0x00,0x00, 158, 157, 155, /* FF50 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00, 156,0x00,0x00,0x00,0x00, /* FF60 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF70 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF80 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF90 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FFA0 */ 0x00,0x00, '*', '+',0x00, '-', '.', '/', '0',0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FFB0 */ 0x00,0x00,0x00,0x00,0x00,0x00, 137, 138, 139, 140, 141, 142, 152, 153,0x00,0x00, /* FFC0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FFD0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FFE0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FFF0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00, 159 }; static const byte scan2ascii_ctrl[NR_KEYS] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 10 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 20 */ 0x00,0x00,0x00,0x00,0x00, 31,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00, 30,0x00, /* 30 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00, 1, 2, 3, 4, 5, 6, 7, /* 40 */ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, /* 50 */ 24, 25, 26, 27, 28, 29, 30, 31, 0x00, 1, 2, 3, 4, 5, 6, 7, /* 60 */ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, /* 70 */ 24, 25, 26,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 80 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 90 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* A0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* B0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* C0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* D0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* E0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* F0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF00 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF10 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF20 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF30 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF40 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00, 167, 164, 165, 166,0x00,0x00,0x00, /* FF50 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF60 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF70 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF80 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FF90 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FFA0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00, 166,0x00, 167,0x00, 165,0x00, /* FFB0 */ 164,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FFC0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FFD0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FFE0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* FFF0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; static inline int AltPressed (void) { return keybstatus[SCANCODE_LEFTALT] || keybstatus[SCANCODE_RIGHTALT]; } static inline int CtrlPressed (void) { return keybstatus[SCANCODE_LEFTCONTROL] || keybstatus[SCANCODE_RIGHTCONTROL]; } static void keyb_handler (int code,int newstatus) { if (code<0 || code>NR_KEYS) return; if (newstatus) newstatus=1; if (!newstatus) keybstatus[code]=0; else { if (!keybstatus[code]) { keybstatus[code]=1; if (CtrlPressed() && (code==SCANCODE_F11 || code==SCANCODE_F12)) { if (code==SCANCODE_F11) PausePressed=2; else PausePressed=1; } else PausePressed=0; switch (code) { case SCANCODE_INSERT: if (!keyboardmode || AltPressed()) joystick=1; break; case SCANCODE_HOME: if (!keyboardmode || AltPressed()) joystick=2; break; case SCANCODE_PAGEUP: if (!keyboardmode || AltPressed()) joystick=3; break; case SCANCODE_REMOVE: if (!keyboardmode || AltPressed()) swapbuttons^=1; break; case SCANCODE_END: if (!keyboardmode || AltPressed()) swapbuttons^=2; break; case SCANCODE_PAGEDOWN: if (!keyboardmode || AltPressed()) swapbuttons^=4; break; case SCANCODE_F1: if (!keyboardmode || AltPressed()) ToggleSoundChannel (0); break; case SCANCODE_F2: if (!keyboardmode || AltPressed()) ToggleSoundChannel (1); break; case SCANCODE_F3: if (!keyboardmode || AltPressed()) ToggleSoundChannel (2); break; case SCANCODE_F4: if (!keyboardmode || AltPressed()) ToggleSoundChannel (3); break; case SCANCODE_F5: if (!keyboardmode || AltPressed()) ToggleSound (); break; case SCANCODE_F8: if (!keyboardmode || AltPressed()) makesnap=1; break; case SCANCODE_F11: if (!PausePressed && !AltPressed()) DecreaseSoundVolume (); break; case SCANCODE_F12: if (!PausePressed && !AltPressed()) IncreaseSoundVolume (); break; case SCANCODE_F10: Z80_Running=0; break; case SCANCODE_F9: #ifdef DEBUG if (keybstatus[SCANCODE_LEFTSHIFT] || keybstatus[SCANCODE_RIGHTSHIFT]) { Trace=!Trace; break; } #endif if (EmuMode) if (CtrlPressed()) calloptions=1; else keyboardmode=(keyboardmode)? 0:1; break; } } if (keyboardmode && !AltPressed()) /* Modify keyboard buffer */ { /* Check for HOME+Cursor key and Cursor key combinations */ if (code==SCANCODE_KEYPAD5) { if (keybstatus[SCANCODE_CURSORLEFT] || keybstatus[SCANCODE_CURSORBLOCKLEFT]) { code=175; goto put_char_in_buf; } if (keybstatus[SCANCODE_CURSORRIGHT] || keybstatus[SCANCODE_CURSORBLOCKRIGHT]) { code=173; goto put_char_in_buf; } if (keybstatus[SCANCODE_CURSORUP] || keybstatus[SCANCODE_CURSORBLOCKUP]) { code=172; goto put_char_in_buf; } if (keybstatus[SCANCODE_CURSORDOWN] || keybstatus[SCANCODE_CURSORBLOCKDOWN]) { code=170; goto put_char_in_buf; } } if (keybstatus[SCANCODE_KEYPAD5]) { if (code==SCANCODE_CURSORLEFT) { code=175; goto put_char_in_buf; } if (code==SCANCODE_CURSORRIGHT) { code=173; goto put_char_in_buf; } if (code==SCANCODE_CURSORUP) { code=172; goto put_char_in_buf; } if (code==SCANCODE_CURSORDOWN) { code=170; goto put_char_in_buf; } } if (code==SCANCODE_CURSORUP || code==SCANCODE_CURSORBLOCKUP) { if (keybstatus[SCANCODE_CURSORRIGHT] || keybstatus[SCANCODE_CURSORBLOCKRIGHT]) { code=168; goto put_char_in_buf; } if (keybstatus[SCANCODE_CURSORLEFT] || keybstatus[SCANCODE_CURSORBLOCKLEFT]) { code=171; goto put_char_in_buf; } } if (code==SCANCODE_CURSORRIGHT || code==SCANCODE_CURSORBLOCKRIGHT) { if (keybstatus[SCANCODE_CURSORUP] || keybstatus[SCANCODE_CURSORBLOCKUP]) { code=168; goto put_char_in_buf; } if (keybstatus[SCANCODE_CURSORDOWN] || keybstatus[SCANCODE_CURSORBLOCKDOWN]) { code=169; goto put_char_in_buf; } } if (code==SCANCODE_CURSORDOWN || code==SCANCODE_CURSORBLOCKDOWN) { if (keybstatus[SCANCODE_CURSORRIGHT] || keybstatus[SCANCODE_CURSORBLOCKRIGHT]) { code=169; goto put_char_in_buf; } if (keybstatus[SCANCODE_CURSORLEFT] || keybstatus[SCANCODE_CURSORBLOCKLEFT]) { code=170; goto put_char_in_buf; } } if (code==SCANCODE_CURSORLEFT) { if (keybstatus[SCANCODE_CURSORUP] || keybstatus[SCANCODE_CURSORBLOCKUP]) { code=171; goto put_char_in_buf; } if (keybstatus[SCANCODE_CURSORDOWN] || keybstatus[SCANCODE_CURSORBLOCKDOWN]) { code=170; goto put_char_in_buf; } } if (keybstatus[SCANCODE_LEFTCONTROL] || keybstatus[SCANCODE_RIGHTCONTROL]) code=scan2ascii_ctrl[code]; else if (keybstatus[SCANCODE_LEFTSHIFT] || keybstatus[SCANCODE_RIGHTSHIFT]) code=scan2ascii_shift[code]; else code=scan2ascii[code]; put_char_in_buf: if (keybstatus[SCANCODE_CAPSLOCK]) { if (code>='a' && code<='z') code+='A'-'a'; else if (code>='A' && code<='Z') code+='a'-'A'; } if (code) LocalAddToKeyboardBuffer (code); } } } /* Look for keyboard events and pass them to the keyboard handler */ static void keyboard_update (void) { XEvent E; int i; while (XCheckWindowEvent(Dsp,Wnd,KeyPressMask|KeyReleaseMask,&E)) { i=XLookupKeysym ((XKeyEvent*)&E,0); if ((i&0xFFFFFF00)==0 || (i&0xFFFFFF00)==0xFF00) keyb_handler (i&511,E.type==KeyPress); } } /****************************************************************************/ /** Mouse routines **/ /****************************************************************************/ static int mouse_buttons=0; /* mouse buttons pressed */ static int mouse_xpos=500; /* horizontal position (0 - 1000) */ static int mouse_ypos=500; /* vertical position (0 - 1000) */ static int mouse_x=0; /* horizontal position (-500 - 500) */ static int mouse_y=0; /* vertical position (-500 - 500) */ static int got_mouse=0; /* 1 if mouse was properly initialised */ static void Mouse_SetJoyState () { if (mouse_buttons&1) MouseJoyState[0]&=0xBFFF; if (mouse_buttons&2) MouseJoyState[0]&=0xFFBF; if (mouse_buttons&4) MouseJoyState[1]&=0xBFFF; if (mouse_buttons&8) MouseJoyState[1]&=0xFFBF; SpinnerPosition[0]=(default_mouse_sens*mouse_x*(abs(mouse_x)+mouse_sens))/ (mouse_sens*mouse_sens); SpinnerPosition[1]=(default_mouse_sens*mouse_y*(abs(mouse_y)+mouse_sens))/ (mouse_sens*mouse_sens); } static void Mouse_GetPosition (void) { } static void Mouse_SetPosition (int x,int y) { } static void Mouse_SetHorizontalRange (int x,int y) { } static void Mouse_SetVerticalRange (int x,int y) { } static void Mouse_Check (void) { int tmp; if (!got_mouse) return; Mouse_GetPosition (); mouse_x=mouse_xpos-500; mouse_y=mouse_ypos-500; tmp=mouse_buttons; if (mouse_x || mouse_y) Mouse_SetPosition (500,500); switch (expansionmode) { case 4: /* emulate driving module */ if (mouse_buttons&7) MouseJoyState[0]&=0xFEFF; mouse_x/=4; mouse_y=0; mouse_buttons=0; break; case 5: /* emulate SA speed roller on both ports */ mouse_x/=4; mouse_y=mouse_x; mouse_buttons=0; break; case 6: /* emulate SA speed roller on port 1 */ mouse_x/=4; mouse_y=0; mouse_buttons=0; break; case 7: /* emulate SA speed roller on port 2 */ mouse_y=mouse_x/4; mouse_x=0; mouse_buttons=0; break; } if (swapbuttons&4) mouse_buttons=(mouse_buttons&(~3))| ((mouse_buttons&1)<<1)| ((mouse_buttons&2)>>1); Mouse_SetJoyState (); mouse_buttons=tmp; } static int Mouse_Detect (void) { if (Verbose) puts (" Detecting mouse... " "Sorry, mouse support is not implemented yet"); return 0; } static void Mouse_Init (void) { if (!got_mouse) Mouse_SetHorizontalRange (0,1000); Mouse_SetVerticalRange (0,1000); Mouse_SetPosition (500,500); return; } static void Mouse_Exit (void) { } /****************************************************************************/ /** Joystick routines **/ /****************************************************************************/ static int gotjoy=0; /* 1 if joystick was properly initialised */ static joypos_t joycentre; /* joystick centre position */ static joypos_t joymin; /* left-upper corner position */ static joypos_t joymax; /* right-lower corner position */ static joypos_t joy_lowmargin; /* start of 'dead' region */ static joypos_t joy_highmargin; /* end of 'dead' region */ static int Joy_Init (void) { if (!InitJoystick(1)) return 0; ReadJoystick (&joycentre); gotjoy=1; return 1; } static void CalibrateJoystick (void) { FILE *joyfile=NULL; if (!calibrate) joyfile=fopen(szJoystickFileName,"rb"); if (!joyfile) { fprintf (stderr,"Move joystick to top left and press enter\n"); fflush (stdin); fgetc (stdin); ReadJoystick (&joymin); fprintf (stderr,"Move joystick to bottom right and press enter\n"); fflush (stdin); fgetc (stdin); ReadJoystick (&joymax); joyfile=fopen(szJoystickFileName,"wb"); if (joyfile) { fwrite (&joymin,sizeof(joymin),1,joyfile); fwrite (&joymax,sizeof(joymax),1,joyfile); fclose (joyfile); } } else { fread (&joymin,sizeof(joymin),1,joyfile); fread (&joymax,sizeof(joymax),1,joyfile); fclose (joyfile); } joy_lowmargin.x=joycentre.x-(joycentre.x-joymin.x)/8; joy_lowmargin.y=joycentre.y-(joycentre.y-joymin.y)/8; joy_highmargin.x=joycentre.x+(joymax.x-joycentre.x)/8; joy_highmargin.y=joycentre.y+(joymax.y-joycentre.y)/8; /* prevent a divide by zero in JoySortOutAnalogue() */ if (joy_lowmargin.x-joymin.x==0) joy_lowmargin.x++; if (joymax.x-joy_highmargin.x==0) joy_highmargin.x--; if (joy_lowmargin.y-joymin.y==0) joy_lowmargin.y++; if (joymax.y-joy_highmargin.y==0) joy_highmargin.y--; } #define JOY_RANGE 128 static void JoySortOutAnalogue (joypos_t *jp) { if (jp->x < joymin.x) jp->x=-JOY_RANGE; else if (jp->x > joymax.x) jp->x=JOY_RANGE; else if ((jp->x > joy_lowmargin.x) && (jp->x < joy_highmargin.x)) jp->x=0; else if (jp->x < joy_lowmargin.x) jp->x=-JOY_RANGE+(jp->x-joymin.x)*JOY_RANGE/(joy_lowmargin.x-joymin.x); else jp->x=JOY_RANGE-(joymax.x-jp->x)*JOY_RANGE/(joymax.x-joy_highmargin.x); if (jp->y < joymin.y) jp->y=-JOY_RANGE; else if (jp->y > joymax.y) jp->y=JOY_RANGE; else if ((jp->y > joy_lowmargin.y) && (jp->y < joy_highmargin.y)) jp->y=0; else if (jp->y < joy_lowmargin.y) jp->y=-JOY_RANGE+(jp->y-joymin.y)*JOY_RANGE/(joy_lowmargin.y-joymin.y); else jp->y=JOY_RANGE-(joymax.y-jp->y)*JOY_RANGE/(joymax.y-joy_highmargin.y); } static void Joy_Check (void) { joypos_t jp; if (!gotjoy) return; ReadJoystick (&jp); switch (expansionmode) { case 0: case 5: case 6: case 7: if (jp.x<(joycentre.x*3/4)) JoystickJoyState[0]&=0xF7FF; else if (jp.x>(joycentre.x*5/4)) JoystickJoyState[0]&=0xFDFF; if (jp.y<(joycentre.y*3/4)) JoystickJoyState[0]&=0xFEFF; else if (jp.y>(joycentre.y*5/4)) JoystickJoyState[0]&=0xFBFF; if (jp.buttons&1) JoystickJoyState[0]&=(swapbuttons&1)? 0xFFBF:0xBFFF; if (jp.buttons&2) JoystickJoyState[0]&=(swapbuttons&1)? 0xBFFF:0xFFBF; if (jp.buttons&4) JoystickJoyState[0]=(JoyState[0]&0xFFF0)|12; if (jp.buttons&8) JoystickJoyState[0]=(JoyState[0]&0xFFF0)|13; break; case 2: JoySortOutAnalogue (&jp); mouse_x=jp.x; mouse_y=jp.y; mouse_buttons=0; if (jp.buttons&1) mouse_buttons|=(swapbuttons&1)? 2:1; if (jp.buttons&2) mouse_buttons|=(swapbuttons&1)? 1:2; if (jp.buttons&4) mouse_buttons|=4; if (jp.buttons&8) mouse_buttons|=8; Mouse_SetJoyState (); break; case 3: if (jp.y<(joycentre.y*3/4)) JoystickJoyState[0]&=0xFEFF; JoySortOutAnalogue (&jp); mouse_x=(jp.x/2); mouse_y=0; Mouse_SetJoyState (); if (jp.buttons&1) JoystickJoyState[1]&=(swapbuttons&1)? 0xFBFF:0xFEFF; if (jp.buttons&2) JoystickJoyState[1]&=(swapbuttons&1)? 0xFEFF:0xFBFF; if (jp.buttons&4) JoystickJoyState[1]&=0xF7FF; if (jp.buttons&8) JoystickJoyState[1]&=0xFDFF; break; } } /****************************************************************************/ /** Deallocate all resources taken by InitMachine() **/ /****************************************************************************/ void TrashMachine(void) { Mouse_Exit (); TrashSound (); 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 if (Img) XDestroyImage (Img); } if (Dsp) XCloseDisplay (Dsp); } static unsigned SwapBytes (unsigned val,unsigned depth) { if (depth==8) return val; if (depth==16) return ((val>>8)&0xFF)+((val<<8)&0xFF00); return ((val>>24)&0xFF)+((val>>8)&0xFF00)+ ((val<<8)&0xFF0000)+((val<<24)&0xFF000000); } static int NextFile (char *s) { char *p; p=s+strlen(s)-1; if (*p=='9') { *p='0'; --p; if (*p=='9') { (*p)++; if (*p=='0') return 0; } else (*p)++; } else (*p)++; return 1; } static int NextSnapshotFile (void) { return NextFile (szSnapshotFile); } /****************************************************************************/ /** Allocate resources needed by X-Windows-dependent code **/ /****************************************************************************/ int InitMachine(void) { int i; Screen *Scr; XSizeHints Hints; XWMHints WMHints; XColor Colour; FILE *snapshotfile; width=WIDTH; height=HEIGHT; switch (videomode) { case 1: width*=2; break; case 2: width*=2; height*=2; break; default: videomode=0; } if (Verbose) printf ("Initialising Unix/X drivers...\n"); if (Verbose) printf (" 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); bpp=DefaultDepthOfScreen (Scr); if (bpp!=8 && bpp!=16 && bpp!=32) { printf ("FAILED - Only 8,16 and 32 bpp displays are supported\n"); return 0; } if (bpp==32 && sizeof(unsigned)!=4) { printf ("FAILED - 32 bpp displays are only supported on 32 bit machines\n"); return 0; } if (Verbose) printf ("OK\n Opening window... "); Wnd=XCreateSimpleWindow (Dsp,RootWindowOfScreen(Scr), 0,0,width,height,0,White,Black); if (!Wnd) { if (Verbose) printf ("FAILED\n"); return 0; } Hints.flags=PSize|PMinSize|PMaxSize; Hints.min_width=Hints.max_width=Hints.base_width=width; Hints.min_height=Hints.max_height=Hints.base_height=height; 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); if (Verbose) printf ("OK\n"); #ifdef MITSHM if (UseSHM) { if (Verbose) printf (" Using shared memory:\n Creating image... "); Img=XShmCreateImage (Dsp,DefaultVisualOfScreen(Scr),bpp, 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... "); Img->data=SHMInfo.shmaddr=shmat(SHMInfo.shmid,0,0); DisplayBuf=Img->data; if (!DisplayBuf) { 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 (" Allocating screen buffer... "); DisplayBuf=malloc(bpp*width*height/8); if (!DisplayBuf) { if (Verbose) printf ("FAILED\n"); return 0; } if (Verbose) printf ("OK\n Creating image... "); Img=XCreateImage (Dsp,DefaultVisualOfScreen(Scr),bpp,ZPixmap, 0,DisplayBuf,width,height,8,0); if (!Img) { if (Verbose) printf ("FAILED\n"); return 0; } } switch (bpp) { case 8: PutPixelProc=PutPixelProcTable[videomode][0]; break; case 16: PutPixelProc=PutPixelProcTable[videomode][1]; break; case 32: PutPixelProc=PutPixelProcTable[videomode][2]; break; } if (Verbose) printf ("OK\n Allocating colours... "); for (i=0;i<16;++i) { if (Coleco_Palette[i*3+0]==0 && Coleco_Palette[i*3+1]==0 && Coleco_Palette[i*3+2]==0) PalBuf[i]=Black; else if ( Coleco_Palette[i*3+0]==255 && Coleco_Palette[i*3+1]==255 && Coleco_Palette[i*3+2]==255) PalBuf[i]=White; else { Colour.flags=DoRed|DoGreen|DoBlue; Colour.red=Coleco_Palette[i*3+0]<<8; Colour.green=Coleco_Palette[i*3+1]<<8; Colour.blue=Coleco_Palette[i*3+2]<<8; if (XAllocColor(Dsp,DefaultCMap,&Colour)) #ifdef LSB_FIRST if (BitmapBitOrder(Dsp)==LSBFirst) #else if (BitmapBitOrder(Dsp)==MSBFirst) #endif PalBuf[i]=Colour.pixel; else PalBuf[i]=SwapBytes (Colour.pixel,bpp); else { if (Verbose) puts ("FAILED"); return 0; } } } if (Verbose) puts ("OK"); while ((snapshotfile=fopen(szSnapshotFile,"rb"))!=NULL) { fclose (snapshotfile); if (!NextSnapshotFile()) break; } if (Verbose) printf (" Next snapshot will be %s\n",szSnapshotFile); JoyState[0]=JoyState[1]=MouseJoyState[0]=MouseJoyState[1]= JoystickJoyState[0]=JoystickJoyState[1]=0x7F7F; InitSound (); if (expansionmode==2 || expansionmode==3 || (expansionmode!=1 && expansionmode!=4 && joystick)) Joy_Init (); if (expansionmode==1 || expansionmode==4 || expansionmode==5 || expansionmode==6 || expansionmode==7) i=Mouse_Detect (); if (mouse_sens<=0 || mouse_sens>1000) mouse_sens=default_mouse_sens; switch (expansionmode) { case 2: case 3: if (!gotjoy) { expansionmode=0; break; } CalibrateJoystick (); break; case 1: case 4: case 5: case 6: case 7: if (!got_mouse) expansionmode=0; break; default: expansionmode=0; default_mouse_sens*=5; break; } if (syncemu) OldTimer=ReadTimer (); /* Parse keyboard mapping string */ sscanf (szKeys,"%03X%03X%03X%03X%03X%03X%03X%03X", &KEY_LEFT,&KEY_RIGHT,&KEY_UP,&KEY_DOWN, &KEY_BUTTONA,&KEY_BUTTONB,&KEY_BUTTONC,&KEY_BUTTOND); Mouse_Init (); keyboardmode=(EmuMode)? 1:0; return 1; } /****************************************************************************/ /** Routines to modify the Coleco gamport status **/ /****************************************************************************/ static int numkeypressed (int nScanCode) { int nOr; switch (nScanCode) { case SCANCODE_1: case SCANCODE_KEYPAD1: nOr=1; break; case SCANCODE_2: case SCANCODE_KEYPAD2: nOr=2; break; case SCANCODE_3: case SCANCODE_KEYPAD3: nOr=3; break; case SCANCODE_4: case SCANCODE_KEYPAD4: nOr=4; break; case SCANCODE_5: case SCANCODE_KEYPAD5: nOr=5; break; case SCANCODE_6: case SCANCODE_KEYPAD6: nOr=6; break; case SCANCODE_7: case SCANCODE_KEYPAD7: nOr=7; break; case SCANCODE_8: case SCANCODE_KEYPAD8: nOr=8; break; case SCANCODE_9: case SCANCODE_KEYPAD9: nOr=9; break; case SCANCODE_EQUAL: case SCANCODE_KEYPADENTER: nOr=10; break; case SCANCODE_MINUS: case SCANCODE_KEYPADPERIOD: nOr=11; break; default: nOr=0; } return nOr; } static void Joysticks (void) { int i,tmp,tmp2; MouseJoyState[0]|=0x7F7F; MouseJoyState[1]|=0x7F7F; Mouse_Check (); JoystickJoyState[0]|=0x7F7F; JoystickJoyState[1]|=0x7F7F; Joy_Check (); JoyState[1]=(MouseJoyState[0] & JoystickJoyState[0]); JoyState[0]=(MouseJoyState[1] & JoystickJoyState[1]); if (!keyboardmode) { if (keybstatus[KEY_BUTTONA]) JoyState[0]&=(swapbuttons&2)? 0xFFBF:0xBFFF; if (keybstatus[KEY_BUTTONB]) JoyState[0]&=(swapbuttons&2)? 0xBFFF:0xFFBF; if (keybstatus[KEY_DOWN]) JoyState[0]&=0xFBFF; if (keybstatus[KEY_UP]) JoyState[0]&=0xFEFF; if (keybstatus[KEY_LEFT]) JoyState[0]&=0xF7FF; if (keybstatus[KEY_RIGHT]) JoyState[0]&=0xFDFF; for (i=SCANCODE_0;i<=SCANCODE_9;++i) if (keybstatus[i]) { tmp=numkeypressed(i); JoyState[0]=(JoyState[0]&0xFFF0)|tmp; } if (keybstatus[SCANCODE_MINUS]) { tmp=numkeypressed(SCANCODE_MINUS); JoyState[0]=(JoyState[0]&0xFFF0)|tmp; } if (keybstatus[SCANCODE_EQUAL]) { tmp=numkeypressed(SCANCODE_EQUAL); JoyState[0]=(JoyState[0]&0xFFF0)|tmp; } if (keybstatus[KEY_BUTTONC]) JoyState[0]=(JoyState[0]&0xFFF0)|12; if (keybstatus[KEY_BUTTOND]) JoyState[0]=(JoyState[0]&0xFFF0)|13; for (i=SCANCODE_KEYPAD7;i<=SCANCODE_KEYPAD9;++i) if (keybstatus[i]) { tmp=numkeypressed((keypadmode)? (i-SCANCODE_KEYPAD7+SCANCODE_KEYPAD1) : i); JoyState[1]=(JoyState[1]&0xFFF0)|tmp; } for (i=SCANCODE_KEYPAD4;i<=SCANCODE_KEYPAD6;++i) if (keybstatus[i]) { tmp=numkeypressed(i); JoyState[1]=(JoyState[1]&0xFFF0)|tmp; } for (i=SCANCODE_KEYPAD1;i<=SCANCODE_KEYPAD3;++i) if (keybstatus[i]) { tmp=numkeypressed((keypadmode)? (i-SCANCODE_KEYPAD1+SCANCODE_KEYPAD7) : i); JoyState[1]=(JoyState[1]&0xFFF0)|tmp; } if (keybstatus[SCANCODE_KEYPAD0]) { tmp=numkeypressed((keypadmode)? SCANCODE_KEYPADPERIOD : SCANCODE_KEYPAD0); JoyState[1]=(JoyState[1]&0xFFF0)|tmp; } if (keybstatus[SCANCODE_KEYPADPERIOD]) { tmp=numkeypressed((keypadmode)? SCANCODE_KEYPAD0 : SCANCODE_KEYPADPERIOD); JoyState[1]=(JoyState[1]&0xFFF0)|tmp; } if (keybstatus[SCANCODE_KEYPADENTER]) { tmp=numkeypressed(SCANCODE_KEYPADENTER); JoyState[1]=(JoyState[1]&0xFFF0)|tmp; } if (keybstatus[SCANCODE_KEYPADPLUS]) JoyState[1]=(JoyState[1]&0xFFF0)|13; if (keybstatus[SCANCODE_KEYPADMINUS]) JoyState[1]=(JoyState[1]&0xFFF0)|12; } switch (expansionmode) { case 1: /* emulate roller controller with mouse */ case 2: /* emulate RC with joystick */ if ((JoyState[1]&0x0F)==12 || (JoyState[1]&0x0F)==13) JoyState[1]|=0x0F; if ((JoyState[0]&0x0F)==12 || (JoyState[0]&0x0F)==13) JoyState[0]|=0x0F; tmp=JoyState[1]; JoyState[1]=(JoyState[0]&0x707F)|0x0F00; JoyState[0]=(tmp&0x7F7F); if ((JoyState[1]&0xF)!=0xF) JoyState[0]=(JoyState[0]&0xFFF0)|(JoyState[1]&0x0F); JoyState[1]=(JoyState[1]&0xFFF0)|(JoyState[0]&0x0F); break; case 3: /* emulate driving module with joystick */ case 4: /* emulate driving module with mouse */ if ((JoyState[1]&0x0F)==12 || (JoyState[1]&0x0F)==13) JoyState[1]|=0x0F; if ((JoyState[0]&0x0F)==12 || (JoyState[0]&0x0F)==13) JoyState[0]|=0x0F; if ((JoyState[1]&0xF)!=0xF) JoyState[0]=(JoyState[0]&0xFFF0)|(JoyState[1]&0x0F); if ((JoyState[1]&0x0100)==0) JoyState[1]&=0xBFFF; else JoyState[1]|=0x4000; JoyState[1]|=0x0F7F; tmp=JoyState[1]; JoyState[1]=JoyState[0]; JoyState[0]=tmp|0x0040; break; default: switch (joystick) { case 1: /* Joystick 1=Joystick 2 */ tmp=JoyState[0]&0x0F; tmp2=JoyState[1]&0x0F; if (tmp==12 || tmp==13) JoyState[1]=(JoyState[1]&0xFFF0)|(JoyState[0]&0xF); else if (tmp2==12 || tmp2==13) JoyState[0]=(JoyState[0]&0xFFF0)|(JoyState[1]&0xF); else if (tmp2!=15) { JoyState[0]=(JoyState[0]&0xFFF0)|(JoyState[1]&0x0F); JoyState[1]|=15; } JoyState[0]&=(JoyState[1]|0xF); JoyState[1]&=(JoyState[0]|0xF); break; case 2: /* Joystick 1=keyb, Joystick 2=joystick */ break; case 3: /* Joystick 1=joystick, Joystick 2=keyb */ tmp=JoyState[0]; JoyState[0]=JoyState[1]; JoyState[1]=tmp; break; } break; } } /****************************************************************************/ /*** Parse keyboard events ***/ /****************************************************************************/ void Keyboard (void) { int tmp; XEvent E; keyboard_update (); /* Check if reset combination is pressed */ if (AltPressed()) { if (keybstatus[SCANCODE_F12]) ResetColeco (0); if (keybstatus[SCANCODE_F11]) ResetColeco (1); } /* Update keyboard buffer */ do { tmp=LocalGetKeyboardChar (); if (tmp) AddToKeyboardBuffer (tmp); } while (tmp); /* Check mouse and joystick events */ Joysticks (); /* Check is PAUSE is pressed */ if (PausePressed) { StopSound (); tmp=0; while (PausePressed) keyboard_update(); ResumeSound (); if (syncemu) OldTimer=ReadTimer (); } /* If saving CPU and focus is out, sleep */ tmp=0; while (XCheckWindowEvent(Dsp,Wnd,FocusChangeMask,&E)) tmp=(E.type==FocusOut); if(SaveCPU&&tmp) { StopSound (); while(!XCheckWindowEvent(Dsp,Wnd,FocusChangeMask,&E)&&Z80_Running) { if(XCheckWindowEvent(Dsp,Wnd,ExposureMask,&E)) PutImage(); XPeekEvent(Dsp,&E); } ResumeSound (); OldTimer=ReadTimer (); } /* Check if a snapshot should be taken */ if (makesnap) { SaveSnapshotFile (szSnapshotFile); NextSnapshotFile (); makesnap--; } /* Check if OptionsDialogue() should be called */ if (calloptions) { calloptions=0; StopSound (); OptionsDialogue (); ResumeSound (); if (syncemu) OldTimer=ReadTimer(); } } /****************************************************************************/ /** Interrupt routines **/ /****************************************************************************/ /* Gets called 50 times per second */ int CheckScreenRefresh (void) { static int skipped=0; if (syncemu) { NewTimer=ReadTimer (); OldTimer+=1000000/IFreq; if ((OldTimer-NewTimer)>0) { do NewTimer=ReadTimer (); while ((NewTimer-OldTimer)<0); skipped=0; return 1; } else if (++skipped>=UPeriod) { OldTimer=ReadTimer (); skipped=0; return 1; } else return 0; } return 2; } FASTCALL static void PutPixel32_0 (int offset,int c) { *(unsigned*)(DisplayBuf+offset*4)=c; } FASTCALL static void PutPixel16_0 (int offset,int c) { *(unsigned short*)(DisplayBuf+offset*2)=c; } FASTCALL static void PutPixel8_0 (int offset,int c) { DisplayBuf[offset]=c; } FASTCALL static void PutPixel32_1 (int offset,int c) { *(unsigned*)(DisplayBuf+offset*4*2)= *(unsigned*)(DisplayBuf+offset*4*2+1)= c; } FASTCALL static void PutPixel16_1 (int offset,int c) { *(unsigned short*)(DisplayBuf+offset*2*2)= *(unsigned short*)(DisplayBuf+offset*2*2+1)= c; } FASTCALL static void PutPixel8_1 (int offset,int c) { DisplayBuf[offset*2]=DisplayBuf[offset*2+1]=c; } FASTCALL static void PutPixel32_2 (int offset,int c) { offset=(offset&0x00FF)+((offset&0xFF00)<<1); *(unsigned*)(DisplayBuf+offset*4*2)= *(unsigned*)(DisplayBuf+offset*4*2+1)= c; } FASTCALL static void PutPixel16_2 (int offset,int c) { offset=(offset&0x00FF)+((offset&0xFF00)<<1); *(unsigned short*)(DisplayBuf+offset*2*2)= *(unsigned short*)(DisplayBuf+offset*2*2+1)= c; } FASTCALL static void PutPixel8_2 (int offset,int c) { offset=(offset&0x00FF)+((offset&0xFF00)<<1); DisplayBuf[offset*2]=DisplayBuf[offset*2+1]=c; } /****************************************************************************/ /** Screen refresh drivers **/ /****************************************************************************/ #include "Common.h"