1 /** ADAMEm: Coleco ADAM emulator ********************************************/
2 /**                                                                        **/
3 /**                                   X.c                                  **/
4 /**                                                                        **/
5 /** This file contains the X-Windows specific routines. It does not        **/
6 /** include the sound emulation code                                       **/
7 /**                                                                        **/
8 /** Copyright (C) Marcel de Kogel 1996,1997,1998,1999                      **/
9 /**     You are not allowed to distribute this software commercially       **/
10 /**     Please, notify me, if you make any changes to this file            **/
11 /****************************************************************************/
12 
13 #include "Coleco.h"
14 #include "X.h"
15 #include "Bitmap.h"
16 #include "Unix.h"
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <signal.h>
22 #include <sys/time.h>
23 #include <X11/Xlib.h>
24 #include <X11/Xutil.h>
25 #include <X11/keysym.h>
26 
27 /* Title for -help output */
28 char Title[]="ADAMEm Unix/X 1.0";
29 
30 char szSnapshotFile[256];         /* Next snapshot file                     */
31 int  videomode;                   /* 0=1x1  1=2x1                           */
32 static int makesnap=0;            /* 1 if snapshot should be written        */
33 static int bpp;			  /* Bits per pixel of the display          */
34 static Display *Dsp;		  /* Default display                        */
35 static Window Wnd;		  /* Our window				    */
36 static Colormap DefaultCMap;	  /* The display's default colours          */
37 static XImage *Img;		  /* Our image                              */
38 static GC DefaultGC;		  /* The default graphics context	    */
39 static int White,Black;		  /* White and black colour values	    */
40 #ifdef MITSHM			  /* SHM extensions			    */
41 #include <sys/ipc.h>
42 #include <sys/shm.h>
43 #include <X11/extensions/XShm.h>
44 XShmSegmentInfo SHMInfo;
45 int UseSHM=1;
46 #endif
47 
48 /* These functions are used to put a pixel on the image buffer */
49 typedef void (*PutPixelProcFn) (int offset,int c)	FASTCALL;
50 static void PutPixel32_0 (int offset,int c)       FASTCALL;
51 static void PutPixel16_0 (int offset,int c)       FASTCALL;
52 static void PutPixel8_0  (int offset,int c)       FASTCALL;
53 static void PutPixel32_1 (int offset,int c)       FASTCALL;
54 static void PutPixel16_1 (int offset,int c)       FASTCALL;
55 static void PutPixel8_1  (int offset,int c)       FASTCALL;
56 static void PutPixel32_2 (int offset,int c)       FASTCALL;
57 static void PutPixel16_2 (int offset,int c)       FASTCALL;
58 static void PutPixel8_2  (int offset,int c)       FASTCALL;
59 static void (*PutPixelProc)(int offset,int c)   FASTCALL;
60 #define PutPixel(P,C)   (*PutPixelProc)(P,C)
61 
62 static PutPixelProcFn PutPixelProcTable[][3]=
63 {
64  { PutPixel8_0, PutPixel16_0, PutPixel32_0 },
65  { PutPixel8_1, PutPixel16_1, PutPixel32_1 },
66  { PutPixel8_2, PutPixel16_2, PutPixel32_2 }
67 };
68 
69 /* Key mapping */
70 static int KEY_LEFT,KEY_RIGHT,KEY_UP,KEY_DOWN,
71            KEY_BUTTONA,KEY_BUTTONB,KEY_BUTTONC,KEY_BUTTOND;
72 
73 static int PalBuf[16],Pal0;       /* Palette buffer                         */
74 static int default_mouse_sens=200;/* Default mouse sensitivity              */
75 static int keyboardmode;          /* 0=joystick, 1=keyboard                 */
76 static word MouseJoyState[2];     /* Current mouse status                   */
77 static word JoystickJoyState[2];  /* Current joystick status                */
78 static int OldTimer=0;            /* Last value of timer                    */
79 static int NewTimer=0;            /* New value of timer                     */
80 static int calloptions=0;         /* If 1, OptionsDialogue() is called      */
81 static int width,height;	  /* width & height of the window           */
82 
83 byte *DisplayBuf;                 /* Screen buffer                          */
84 char szJoystickFileName[256];     /* File holding joystick information      */
85 char *szKeys="1511531521540201E31E107A";
86 				  /* Key scancodes                          */
87 int  mouse_sens=200;              /* Mouse sensitivity                      */
88 int  keypadmode=0;                /* 1 if keypad should be reversed         */
89 int  joystick=1;                  /* Joystick support                       */
90 int  calibrate=0;                 /* Set to 1 to force joystick calibration */
91 int  swapbuttons=0;               /* 1=joystick, 2=keyboard, 4=mouse        */
92 int  expansionmode=0;             /* Expansion module emulated              */
93 int  syncemu=1;                   /* 0 if emulation shouldn't be synced     */
94 int  SaveCPU=1;                   /* If 1, save CPU when focus is out       */
95 
PutImage(void)96 static void PutImage (void)
97 {
98 #ifdef MITSHM
99  if (UseSHM) XShmPutImage (Dsp,Wnd,DefaultGC,Img,0,0,0,0,width,height,False);
100  else
101 #endif
102  XPutImage (Dsp,Wnd,DefaultGC,Img,0,0,0,0,width,height);
103  XFlush (Dsp);
104 }
105 
106 /****************************************************************************/
107 /** Keyboard routines                                                      **/
108 /****************************************************************************/
109 static int PausePressed=0;
110 static byte keybstatus[NR_KEYS];
111 
112 static byte keyboard_buffer[16];
113 static int keyboard_buffer_count=0;
LocalAddToKeyboardBuffer(byte ch)114 static void LocalAddToKeyboardBuffer (byte ch)
115 {
116  keyboard_buffer[keyboard_buffer_count]=ch;
117  keyboard_buffer_count=(keyboard_buffer_count+1)&15;
118  keyboard_buffer[keyboard_buffer_count]=0;
119 }
LocalGetKeyboardChar(void)120 static int LocalGetKeyboardChar (void)
121 {
122  int retval;
123  keyboard_buffer_count=(keyboard_buffer_count-1)&15;
124  retval=keyboard_buffer[keyboard_buffer_count];
125  keyboard_buffer[keyboard_buffer_count]=0;
126  return retval;
127 }
128 
129 static const byte scan2ascii[NR_KEYS] =
130 {
131  0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,	/* 00 */
132  0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
133  0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,	/* 10 */
134  0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
135  0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,	/* 20 */
136  0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
137  0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,	/* 30 */
138  0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
139  0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,	/* 40 */
140  0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
141  0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,	/* 50 */
142  0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
143  0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,	/* 60 */
144  0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
145  0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,	/* 70 */
146  0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
147  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* 80 */
148  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
149  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* 90 */
150  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
151  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* A0 */
152  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
153  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* B0 */
154  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
155  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* C0 */
156  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
157  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* D0 */
158  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
159  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* E0 */
160  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
161  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* F0 */
162  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
163  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF00 */
164     8,   9,0x00,0x00,0x00,  13,0x00,0x00,
165  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF10 */
166  0x00,0x00,0x00,  27,0x00,0x00,0x00,0x00,
167  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF20 */
168  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
169  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF30 */
170  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
171  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF40 */
172  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
173   146, 163, 160, 161, 162, 150, 149, 147,	/* FF50 */
174  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
175  0x00,0x00,0x00, 148,0x00,0x00,0x00,0x00,	/* FF60 */
176  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
177  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF70 */
178  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
179  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF80 */
180  0x00,0x00,0x00,0x00,0x00,  13,0x00,0x00,
181  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF90 */
182  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
183  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FFA0 */
184  0x00,0x00, '*', '+',0x00, '-', '.', '/',
185   '0', 170, 162, 169, 163, 128, 161, 171,	/* FFB0 */
186   160, 168,0x00,0x00,0x00,0x00, 129, 130,
187   131, 132, 133, 134, 144, 145,0x00,0x00,	/* FFC0 */
188  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
189  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FFD0 */
190  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
191  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FFE0 */
192  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
193  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FFF0 */
194  0x00,0x00,0x00,0x00,0x00,0x00,0x00, 151
195 };
196 static const byte scan2ascii_shift[NR_KEYS] =
197 {
198  0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,	/* 00 */
199  0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
200  0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,	/* 10 */
201  0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
202  0x20,0x21,0x22,0x23,0x24,0x25,0x26,  34,	/* 20 */
203  0x28,0x29,0x2A,0x2B, '<', '_', '>', '?',
204   ')', '!', '@', '#', '$', '%', '^', '&',	/* 30 */
205   '*', '(',0x3A, ':',0x3C, '+',0x3E,0x3F,
206  0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g',	/* 40 */
207   'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
208   'p', 'q', 'r', 's', 't', 'u', 'v', 'w',	/* 50 */
209   'x', 'y', 'z', '{', '|', '}',0x5E,0x5F,
210   '~', 'A', 'B', 'C', 'D', 'E', 'F', 'G',	/* 60 */
211   'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
212   'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',	/* 70 */
213   'X', 'Y', 'Z',0x7B,0x7C,0x7D,0x7E,0x7F,
214  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* 80 */
215  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
216  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* 90 */
217  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
218  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* A0 */
219  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
220  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* B0 */
221  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
222  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* C0 */
223  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
224  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* D0 */
225  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
226  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* E0 */
227  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
228  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* F0 */
229  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
230  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF00 */
231   184, 185,0x00,0x00,0x00,0x00,0x00,0x00,
232  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF10 */
233  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
234  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF20 */
235  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
236  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF30 */
237  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
238  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF40 */
239  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
240   154,0x00,0x00,0x00,0x00, 158, 157, 155,	/* FF50 */
241  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
242  0x00,0x00,0x00, 156,0x00,0x00,0x00,0x00,	/* FF60 */
243  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
244  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF70 */
245  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
246  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF80 */
247  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
248  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF90 */
249  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
250  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FFA0 */
251  0x00,0x00, '*', '+',0x00, '-', '.', '/',
252   '0',0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FFB0 */
253  0x00,0x00,0x00,0x00,0x00,0x00, 137, 138,
254   139, 140, 141, 142, 152, 153,0x00,0x00,	/* FFC0 */
255  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
256  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FFD0 */
257  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
258  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FFE0 */
259  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
260  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FFF0 */
261  0x00,0x00,0x00,0x00,0x00,0x00,0x00, 159
262 };
263 static const byte scan2ascii_ctrl[NR_KEYS] =
264 {
265  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* 00 */
266  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
267  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* 10 */
268  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
269  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* 20 */
270  0x00,0x00,0x00,0x00,0x00,  31,0x00,0x00,
271  0x00,0x00,0x00,0x00,0x00,0x00,  30,0x00,	/* 30 */
272  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
273  0x00,   1,   2,   3,   4,   5,   6,   7,	/* 40 */
274     8,   9,  10,  11,  12,  13,  14,  15,
275    16,  17,  18,  19,  20,  21,  22,  23,	/* 50 */
276    24,  25,  26,  27,  28,  29,  30,  31,
277  0x00,   1,   2,   3,   4,   5,   6,   7,	/* 60 */
278     8,   9,  10,  11,  12,  13,  14,  15,
279    16,  17,  18,  19,  20,  21,  22,  23,	/* 70 */
280    24,  25,  26,0x00,0x00,0x00,0x00,0x00,
281  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* 80 */
282  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
283  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* 90 */
284  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
285  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* A0 */
286  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
287  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* B0 */
288  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
289  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* C0 */
290  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
291  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* D0 */
292  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
293  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* E0 */
294  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
295  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* F0 */
296  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
297  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF00 */
298  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
299  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF10 */
300  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
301  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF20 */
302  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
303  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF30 */
304  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
305  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF40 */
306  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
307  0x00, 167, 164, 165, 166,0x00,0x00,0x00,	/* FF50 */
308  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
309  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF60 */
310  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
311  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF70 */
312  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
313  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF80 */
314  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
315  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FF90 */
316  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
317  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FFA0 */
318  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
319  0x00,0x00, 166,0x00, 167,0x00, 165,0x00,	/* FFB0 */
320   164,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
321  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FFC0 */
322  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
323  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FFD0 */
324  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
325  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FFE0 */
326  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
327  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* FFF0 */
328  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
329 };
330 
AltPressed(void)331 static inline int AltPressed (void)
332 {
333  return keybstatus[SCANCODE_LEFTALT] || keybstatus[SCANCODE_RIGHTALT];
334 }
CtrlPressed(void)335 static inline int CtrlPressed (void)
336 {
337  return keybstatus[SCANCODE_LEFTCONTROL] || keybstatus[SCANCODE_RIGHTCONTROL];
338 }
keyb_handler(int code,int newstatus)339 static void keyb_handler (int code,int newstatus)
340 {
341  if (code<0 || code>NR_KEYS)
342   return;
343  if (newstatus) newstatus=1;
344  if (!newstatus)
345   keybstatus[code]=0;
346  else
347  {
348   if (!keybstatus[code])
349   {
350    keybstatus[code]=1;
351    if (CtrlPressed() &&
352        (code==SCANCODE_F11 || code==SCANCODE_F12))
353    {
354     if (code==SCANCODE_F11)
355      PausePressed=2;
356     else
357      PausePressed=1;
358    }
359    else
360     PausePressed=0;
361    switch (code)
362    {
363     case SCANCODE_INSERT:
364      if (!keyboardmode || AltPressed())
365       joystick=1;
366      break;
367     case SCANCODE_HOME:
368      if (!keyboardmode || AltPressed())
369       joystick=2;
370      break;
371     case SCANCODE_PAGEUP:
372      if (!keyboardmode || AltPressed())
373       joystick=3;
374      break;
375     case SCANCODE_REMOVE:
376      if (!keyboardmode || AltPressed())
377       swapbuttons^=1;
378      break;
379     case SCANCODE_END:
380      if (!keyboardmode || AltPressed())
381       swapbuttons^=2;
382      break;
383     case SCANCODE_PAGEDOWN:
384      if (!keyboardmode || AltPressed())
385       swapbuttons^=4;
386      break;
387     case SCANCODE_F1:
388      if (!keyboardmode || AltPressed())
389       ToggleSoundChannel (0);
390      break;
391     case SCANCODE_F2:
392      if (!keyboardmode || AltPressed())
393       ToggleSoundChannel (1);
394      break;
395     case SCANCODE_F3:
396      if (!keyboardmode || AltPressed())
397       ToggleSoundChannel (2);
398      break;
399     case SCANCODE_F4:
400      if (!keyboardmode || AltPressed())
401       ToggleSoundChannel (3);
402      break;
403     case SCANCODE_F5:
404      if (!keyboardmode || AltPressed())
405       ToggleSound ();
406      break;
407     case SCANCODE_F8:
408      if (!keyboardmode || AltPressed())
409       makesnap=1;
410      break;
411     case SCANCODE_F11:
412      if (!PausePressed && !AltPressed()) DecreaseSoundVolume ();
413      break;
414     case SCANCODE_F12:
415      if (!PausePressed && !AltPressed()) IncreaseSoundVolume ();
416      break;
417     case SCANCODE_F10:
418      Z80_Running=0;
419      break;
420     case SCANCODE_F9:
421 #ifdef DEBUG
422      if (keybstatus[SCANCODE_LEFTSHIFT] || keybstatus[SCANCODE_RIGHTSHIFT])
423      {
424       Trace=!Trace;
425       break;
426      }
427 #endif
428      if (EmuMode)
429       if (CtrlPressed())
430        calloptions=1;
431       else
432        keyboardmode=(keyboardmode)? 0:1;
433      break;
434    }
435   }
436   if (keyboardmode && !AltPressed())  /* Modify keyboard buffer           */
437   {
438    /* Check for HOME+Cursor key and Cursor key combinations */
439    if (code==SCANCODE_KEYPAD5)
440    {
441     if (keybstatus[SCANCODE_CURSORLEFT] ||
442         keybstatus[SCANCODE_CURSORBLOCKLEFT])
443     { code=175; goto put_char_in_buf; }
444     if (keybstatus[SCANCODE_CURSORRIGHT] ||
445         keybstatus[SCANCODE_CURSORBLOCKRIGHT])
446     { code=173; goto put_char_in_buf; }
447     if (keybstatus[SCANCODE_CURSORUP] ||
448         keybstatus[SCANCODE_CURSORBLOCKUP])
449     { code=172; goto put_char_in_buf; }
450     if (keybstatus[SCANCODE_CURSORDOWN] ||
451         keybstatus[SCANCODE_CURSORBLOCKDOWN])
452     { code=170; goto put_char_in_buf; }
453    }
454    if (keybstatus[SCANCODE_KEYPAD5])
455    {
456     if (code==SCANCODE_CURSORLEFT) { code=175; goto put_char_in_buf; }
457     if (code==SCANCODE_CURSORRIGHT) { code=173; goto put_char_in_buf; }
458     if (code==SCANCODE_CURSORUP) { code=172; goto put_char_in_buf; }
459     if (code==SCANCODE_CURSORDOWN) { code=170; goto put_char_in_buf; }
460    }
461    if (code==SCANCODE_CURSORUP || code==SCANCODE_CURSORBLOCKUP)
462    {
463     if (keybstatus[SCANCODE_CURSORRIGHT] ||
464         keybstatus[SCANCODE_CURSORBLOCKRIGHT])
465     { code=168; goto put_char_in_buf; }
466     if (keybstatus[SCANCODE_CURSORLEFT] ||
467         keybstatus[SCANCODE_CURSORBLOCKLEFT])
468     { code=171; goto put_char_in_buf; }
469    }
470    if (code==SCANCODE_CURSORRIGHT || code==SCANCODE_CURSORBLOCKRIGHT)
471    {
472     if (keybstatus[SCANCODE_CURSORUP] ||
473         keybstatus[SCANCODE_CURSORBLOCKUP])
474     { code=168; goto put_char_in_buf; }
475     if (keybstatus[SCANCODE_CURSORDOWN] ||
476         keybstatus[SCANCODE_CURSORBLOCKDOWN])
477     { code=169; goto put_char_in_buf; }
478    }
479    if (code==SCANCODE_CURSORDOWN || code==SCANCODE_CURSORBLOCKDOWN)
480    {
481     if (keybstatus[SCANCODE_CURSORRIGHT] ||
482         keybstatus[SCANCODE_CURSORBLOCKRIGHT])
483     { code=169; goto put_char_in_buf; }
484     if (keybstatus[SCANCODE_CURSORLEFT] ||
485         keybstatus[SCANCODE_CURSORBLOCKLEFT])
486     { code=170; goto put_char_in_buf; }
487    }
488    if (code==SCANCODE_CURSORLEFT)
489    {
490     if (keybstatus[SCANCODE_CURSORUP] ||
491         keybstatus[SCANCODE_CURSORBLOCKUP])
492     { code=171; goto put_char_in_buf; }
493     if (keybstatus[SCANCODE_CURSORDOWN] ||
494         keybstatus[SCANCODE_CURSORBLOCKDOWN])
495     { code=170; goto put_char_in_buf; }
496    }
497    if (keybstatus[SCANCODE_LEFTCONTROL] ||
498        keybstatus[SCANCODE_RIGHTCONTROL])
499     code=scan2ascii_ctrl[code];
500    else if (keybstatus[SCANCODE_LEFTSHIFT] ||
501             keybstatus[SCANCODE_RIGHTSHIFT])
502     code=scan2ascii_shift[code];
503    else
504     code=scan2ascii[code];
505 put_char_in_buf:
506    if (keybstatus[SCANCODE_CAPSLOCK])
507    {
508     if (code>='a' && code<='z') code+='A'-'a';
509     else if (code>='A' && code<='Z') code+='a'-'A';
510    }
511    if (code) LocalAddToKeyboardBuffer (code);
512   }
513  }
514 }
515 
516 /* Look for keyboard events and pass them to the keyboard handler */
keyboard_update(void)517 static void keyboard_update (void)
518 {
519  XEvent E;
520  int i;
521  while (XCheckWindowEvent(Dsp,Wnd,KeyPressMask|KeyReleaseMask,&E))
522  {
523   i=XLookupKeysym ((XKeyEvent*)&E,0);
524   if ((i&0xFFFFFF00)==0 || (i&0xFFFFFF00)==0xFF00)
525    keyb_handler (i&511,E.type==KeyPress);
526  }
527 }
528 
529 /****************************************************************************/
530 /** Mouse routines                                                         **/
531 /****************************************************************************/
532 static int mouse_buttons=0;       /* mouse buttons pressed                  */
533 static int mouse_xpos=500;        /* horizontal position (0 - 1000)         */
534 static int mouse_ypos=500;        /* vertical position (0 - 1000)           */
535 static int mouse_x=0;             /* horizontal position (-500 - 500)       */
536 static int mouse_y=0;             /* vertical position (-500 - 500)         */
537 static int got_mouse=0;           /* 1 if mouse was properly initialised    */
538 
Mouse_SetJoyState()539 static void Mouse_SetJoyState ()
540 {
541  if (mouse_buttons&1)
542   MouseJoyState[0]&=0xBFFF;
543  if (mouse_buttons&2)
544   MouseJoyState[0]&=0xFFBF;
545  if (mouse_buttons&4)
546   MouseJoyState[1]&=0xBFFF;
547  if (mouse_buttons&8)
548   MouseJoyState[1]&=0xFFBF;
549  SpinnerPosition[0]=(default_mouse_sens*mouse_x*(abs(mouse_x)+mouse_sens))/
550                     (mouse_sens*mouse_sens);
551  SpinnerPosition[1]=(default_mouse_sens*mouse_y*(abs(mouse_y)+mouse_sens))/
552                     (mouse_sens*mouse_sens);
553 }
554 
Mouse_GetPosition(void)555 static void Mouse_GetPosition (void)
556 {
557 }
558 
Mouse_SetPosition(int x,int y)559 static void Mouse_SetPosition (int x,int y)
560 {
561 }
562 
Mouse_SetHorizontalRange(int x,int y)563 static void Mouse_SetHorizontalRange (int x,int y)
564 {
565 }
566 
Mouse_SetVerticalRange(int x,int y)567 static void Mouse_SetVerticalRange (int x,int y)
568 {
569 }
570 
Mouse_Check(void)571 static void Mouse_Check (void)
572 {
573  int tmp;
574  if (!got_mouse)
575   return;
576  Mouse_GetPosition ();
577  mouse_x=mouse_xpos-500;
578  mouse_y=mouse_ypos-500;
579  tmp=mouse_buttons;
580  if (mouse_x || mouse_y)
581   Mouse_SetPosition (500,500);
582  switch (expansionmode)
583  {
584   case 4:                         /* emulate driving module                 */
585    if (mouse_buttons&7)
586     MouseJoyState[0]&=0xFEFF;
587    mouse_x/=4;
588    mouse_y=0;
589    mouse_buttons=0;
590    break;
591   case 5:                         /* emulate SA speed roller on both ports  */
592    mouse_x/=4;
593    mouse_y=mouse_x;
594    mouse_buttons=0;
595    break;
596   case 6:                         /* emulate SA speed roller on port 1      */
597    mouse_x/=4;
598    mouse_y=0;
599    mouse_buttons=0;
600    break;
601   case 7:                         /* emulate SA speed roller on port 2      */
602    mouse_y=mouse_x/4;
603    mouse_x=0;
604    mouse_buttons=0;
605    break;
606  }
607  if (swapbuttons&4)
608   mouse_buttons=(mouse_buttons&(~3))|
609                 ((mouse_buttons&1)<<1)|
610                 ((mouse_buttons&2)>>1);
611  Mouse_SetJoyState ();
612  mouse_buttons=tmp;
613 }
614 
Mouse_Detect(void)615 static int Mouse_Detect (void)
616 {
617  if (Verbose) puts ("  Detecting mouse... "
618                     "Sorry, mouse support is not implemented yet");
619  return 0;
620 }
621 
Mouse_Init(void)622 static void Mouse_Init (void)
623 {
624  if (!got_mouse)
625  Mouse_SetHorizontalRange (0,1000);
626  Mouse_SetVerticalRange (0,1000);
627  Mouse_SetPosition (500,500);
628  return;
629 }
630 
Mouse_Exit(void)631 static void Mouse_Exit (void)
632 {
633 }
634 
635 /****************************************************************************/
636 /** Joystick routines                                                      **/
637 /****************************************************************************/
638 static int gotjoy=0;              /* 1 if joystick was properly initialised */
639 static joypos_t joycentre;        /* joystick centre position               */
640 static joypos_t joymin;           /* left-upper corner position             */
641 static joypos_t joymax;           /* right-lower corner position            */
642 static joypos_t joy_lowmargin;    /* start of 'dead' region                 */
643 static joypos_t joy_highmargin;   /* end of 'dead' region                   */
644 
Joy_Init(void)645 static int Joy_Init (void)
646 {
647  if (!InitJoystick(1))
648   return 0;
649  ReadJoystick (&joycentre);
650  gotjoy=1;
651  return 1;
652 }
653 
CalibrateJoystick(void)654 static void CalibrateJoystick (void)
655 {
656  FILE *joyfile=NULL;
657  if (!calibrate)
658   joyfile=fopen(szJoystickFileName,"rb");
659  if (!joyfile)
660  {
661   fprintf (stderr,"Move joystick to top left and press enter\n");
662   fflush (stdin); fgetc (stdin);
663   ReadJoystick (&joymin);
664   fprintf (stderr,"Move joystick to bottom right and press enter\n");
665   fflush (stdin); fgetc (stdin);
666   ReadJoystick (&joymax);
667   joyfile=fopen(szJoystickFileName,"wb");
668   if (joyfile)
669   {
670    fwrite (&joymin,sizeof(joymin),1,joyfile);
671    fwrite (&joymax,sizeof(joymax),1,joyfile);
672    fclose (joyfile);
673   }
674  }
675  else
676  {
677   fread (&joymin,sizeof(joymin),1,joyfile);
678   fread (&joymax,sizeof(joymax),1,joyfile);
679   fclose (joyfile);
680  }
681  joy_lowmargin.x=joycentre.x-(joycentre.x-joymin.x)/8;
682  joy_lowmargin.y=joycentre.y-(joycentre.y-joymin.y)/8;
683  joy_highmargin.x=joycentre.x+(joymax.x-joycentre.x)/8;
684  joy_highmargin.y=joycentre.y+(joymax.y-joycentre.y)/8;
685  /* prevent a divide by zero in JoySortOutAnalogue() */
686  if (joy_lowmargin.x-joymin.x==0)
687   joy_lowmargin.x++;
688  if (joymax.x-joy_highmargin.x==0)
689   joy_highmargin.x--;
690  if (joy_lowmargin.y-joymin.y==0)
691   joy_lowmargin.y++;
692  if (joymax.y-joy_highmargin.y==0)
693   joy_highmargin.y--;
694 }
695 
696 #define JOY_RANGE       128
JoySortOutAnalogue(joypos_t * jp)697 static void JoySortOutAnalogue (joypos_t *jp)
698 {
699  if (jp->x < joymin.x)
700   jp->x=-JOY_RANGE;
701  else
702   if (jp->x > joymax.x)
703    jp->x=JOY_RANGE;
704   else
705    if ((jp->x > joy_lowmargin.x) && (jp->x < joy_highmargin.x))
706     jp->x=0;
707    else
708     if (jp->x < joy_lowmargin.x)
709      jp->x=-JOY_RANGE+(jp->x-joymin.x)*JOY_RANGE/(joy_lowmargin.x-joymin.x);
710     else
711      jp->x=JOY_RANGE-(joymax.x-jp->x)*JOY_RANGE/(joymax.x-joy_highmargin.x);
712 
713  if (jp->y < joymin.y)
714   jp->y=-JOY_RANGE;
715  else
716   if (jp->y > joymax.y)
717    jp->y=JOY_RANGE;
718   else
719    if ((jp->y > joy_lowmargin.y) && (jp->y < joy_highmargin.y))
720     jp->y=0;
721    else
722     if (jp->y < joy_lowmargin.y)
723      jp->y=-JOY_RANGE+(jp->y-joymin.y)*JOY_RANGE/(joy_lowmargin.y-joymin.y);
724     else
725      jp->y=JOY_RANGE-(joymax.y-jp->y)*JOY_RANGE/(joymax.y-joy_highmargin.y);
726 }
727 
Joy_Check(void)728 static void Joy_Check (void)
729 {
730  joypos_t jp;
731  if (!gotjoy)
732   return;
733  ReadJoystick (&jp);
734  switch (expansionmode)
735  {
736   case 0:
737   case 5:
738   case 6:
739   case 7:
740    if (jp.x<(joycentre.x*3/4))
741     JoystickJoyState[0]&=0xF7FF;
742    else
743     if (jp.x>(joycentre.x*5/4))
744      JoystickJoyState[0]&=0xFDFF;
745    if (jp.y<(joycentre.y*3/4))
746     JoystickJoyState[0]&=0xFEFF;
747    else
748     if (jp.y>(joycentre.y*5/4))
749      JoystickJoyState[0]&=0xFBFF;
750    if (jp.buttons&1)
751     JoystickJoyState[0]&=(swapbuttons&1)? 0xFFBF:0xBFFF;
752    if (jp.buttons&2)
753     JoystickJoyState[0]&=(swapbuttons&1)? 0xBFFF:0xFFBF;
754    if (jp.buttons&4)
755     JoystickJoyState[0]=(JoyState[0]&0xFFF0)|12;
756    if (jp.buttons&8)
757     JoystickJoyState[0]=(JoyState[0]&0xFFF0)|13;
758    break;
759   case 2:
760    JoySortOutAnalogue (&jp);
761    mouse_x=jp.x;
762    mouse_y=jp.y;
763    mouse_buttons=0;
764    if (jp.buttons&1)
765     mouse_buttons|=(swapbuttons&1)? 2:1;
766    if (jp.buttons&2)
767     mouse_buttons|=(swapbuttons&1)? 1:2;
768    if (jp.buttons&4)
769     mouse_buttons|=4;
770    if (jp.buttons&8)
771     mouse_buttons|=8;
772    Mouse_SetJoyState ();
773    break;
774   case 3:
775    if (jp.y<(joycentre.y*3/4))
776     JoystickJoyState[0]&=0xFEFF;
777    JoySortOutAnalogue (&jp);
778    mouse_x=(jp.x/2);
779    mouse_y=0;
780    Mouse_SetJoyState ();
781    if (jp.buttons&1)
782     JoystickJoyState[1]&=(swapbuttons&1)? 0xFBFF:0xFEFF;
783    if (jp.buttons&2)
784     JoystickJoyState[1]&=(swapbuttons&1)? 0xFEFF:0xFBFF;
785    if (jp.buttons&4)
786     JoystickJoyState[1]&=0xF7FF;
787    if (jp.buttons&8)
788     JoystickJoyState[1]&=0xFDFF;
789    break;
790  }
791 }
792 
793 /****************************************************************************/
794 /** Deallocate all resources taken by InitMachine()                        **/
795 /****************************************************************************/
TrashMachine(void)796 void TrashMachine(void)
797 {
798  Mouse_Exit ();
799  TrashSound ();
800  if (Dsp && Wnd)
801  {
802 #ifdef MITSHM
803   if (UseSHM)
804   {
805    XShmDetach (Dsp,&SHMInfo);
806    if (SHMInfo.shmaddr) shmdt (SHMInfo.shmaddr);
807    if (SHMInfo.shmid>=0) shmctl (SHMInfo.shmid,IPC_RMID,0);
808   }
809   else
810 #endif
811   if (Img) XDestroyImage (Img);
812  }
813  if (Dsp) XCloseDisplay (Dsp);
814 }
815 
SwapBytes(unsigned val,unsigned depth)816 static unsigned SwapBytes (unsigned val,unsigned depth)
817 {
818  if (depth==8)
819   return val;
820  if (depth==16)
821   return ((val>>8)&0xFF)+((val<<8)&0xFF00);
822  return ((val>>24)&0xFF)+((val>>8)&0xFF00)+
823         ((val<<8)&0xFF0000)+((val<<24)&0xFF000000);
824 }
825 
NextFile(char * s)826 static int NextFile (char *s)
827 {
828  char *p;
829  p=s+strlen(s)-1;
830  if (*p=='9')
831  {
832   *p='0';
833   --p;
834   if (*p=='9')
835   {
836    (*p)++;
837    if (*p=='0')
838     return 0;
839   }
840   else
841    (*p)++;
842  }
843  else
844   (*p)++;
845  return 1;
846 }
NextSnapshotFile(void)847 static int NextSnapshotFile (void)
848 {
849  return NextFile (szSnapshotFile);
850 }
851 
852 /****************************************************************************/
853 /** Allocate resources needed by X-Windows-dependent code                  **/
854 /****************************************************************************/
InitMachine(void)855 int InitMachine(void)
856 {
857  int i;
858  Screen *Scr;
859  XSizeHints Hints;
860  XWMHints WMHints;
861  XColor Colour;
862  FILE *snapshotfile;
863  width=WIDTH; height=HEIGHT;
864  switch (videomode)
865  {
866   case 1:  width*=2;
867            break;
868   case 2:  width*=2;
869   	   height*=2;
870   	   break;
871   default: videomode=0;
872  }
873  if (Verbose) printf ("Initialising Unix/X drivers...\n");
874  if (Verbose) printf ("  Opening display... ");
875  Dsp=XOpenDisplay (NULL);
876  if (!Dsp)
877  {
878   if (Verbose) printf ("FAILED\n");
879   return 0;
880  }
881  Scr=DefaultScreenOfDisplay (Dsp);
882  White=WhitePixelOfScreen (Scr);
883  Black=BlackPixelOfScreen (Scr);
884  DefaultGC=DefaultGCOfScreen (Scr);
885  DefaultCMap=DefaultColormapOfScreen (Scr);
886  bpp=DefaultDepthOfScreen (Scr);
887  if (bpp!=8 && bpp!=16 && bpp!=32)
888  {
889   printf ("FAILED - Only 8,16 and 32 bpp displays are supported\n");
890   return 0;
891  }
892  if (bpp==32 && sizeof(unsigned)!=4)
893  {
894   printf ("FAILED - 32 bpp displays are only supported on 32 bit machines\n");
895   return 0;
896  }
897  if (Verbose) printf ("OK\n  Opening window... ");
898  Wnd=XCreateSimpleWindow (Dsp,RootWindowOfScreen(Scr),
899  			  0,0,width,height,0,White,Black);
900  if (!Wnd)
901  {
902   if (Verbose) printf ("FAILED\n");
903   return 0;
904  }
905  Hints.flags=PSize|PMinSize|PMaxSize;
906  Hints.min_width=Hints.max_width=Hints.base_width=width;
907  Hints.min_height=Hints.max_height=Hints.base_height=height;
908  WMHints.input=True;
909  WMHints.flags=InputHint;
910  XSetWMHints (Dsp,Wnd,&WMHints);
911  XSetWMNormalHints (Dsp,Wnd,&Hints);
912  XStoreName (Dsp,Wnd,Title);
913  XSelectInput (Dsp,Wnd,FocusChangeMask|ExposureMask|KeyPressMask|KeyReleaseMask);
914  XMapRaised (Dsp,Wnd);
915  XClearWindow (Dsp,Wnd);
916  if (Verbose) printf ("OK\n");
917 #ifdef MITSHM
918  if (UseSHM)
919  {
920   if (Verbose) printf ("  Using shared memory:\n    Creating image... ");
921   Img=XShmCreateImage (Dsp,DefaultVisualOfScreen(Scr),bpp,
922                        ZPixmap,NULL,&SHMInfo,width,height);
923   if (!Img)
924   {
925    if (Verbose) printf ("FAILED\n");
926    return 0;
927   }
928   if (Verbose) printf ("OK\n    Getting SHM info... ");
929   SHMInfo.shmid=shmget (IPC_PRIVATE,Img->bytes_per_line*Img->height,
930   			IPC_CREAT|0777);
931   if (SHMInfo.shmid<0)
932   {
933    if (Verbose) printf ("FAILED\n");
934    return 0;
935   }
936   if (Verbose) printf ("OK\n    Allocating SHM... ");
937   Img->data=SHMInfo.shmaddr=shmat(SHMInfo.shmid,0,0);
938   DisplayBuf=Img->data;
939   if (!DisplayBuf)
940   {
941    if (Verbose) printf ("FAILED\n");
942    return 0;
943   }
944   SHMInfo.readOnly=False;
945   if (Verbose) printf ("OK\n    Attaching SHM... ");
946   if (!XShmAttach(Dsp,&SHMInfo))
947   {
948    if (Verbose) printf ("FAILED\n");
949    return 0;
950   }
951  }
952  else
953 #endif
954  {
955   if (Verbose) printf ("  Allocating screen buffer... ");
956   DisplayBuf=malloc(bpp*width*height/8);
957   if (!DisplayBuf)
958   {
959    if (Verbose) printf ("FAILED\n");
960    return 0;
961   }
962   if (Verbose) printf ("OK\n  Creating image... ");
963   Img=XCreateImage (Dsp,DefaultVisualOfScreen(Scr),bpp,ZPixmap,
964   		    0,DisplayBuf,width,height,8,0);
965   if (!Img)
966   {
967    if (Verbose) printf ("FAILED\n");
968    return 0;
969   }
970  }
971  switch (bpp)
972  {
973   case 8:  PutPixelProc=PutPixelProcTable[videomode][0];
974            break;
975   case 16: PutPixelProc=PutPixelProcTable[videomode][1];
976            break;
977   case 32: PutPixelProc=PutPixelProcTable[videomode][2];
978            break;
979  }
980  if (Verbose) printf ("OK\n  Allocating colours... ");
981  for (i=0;i<16;++i)
982  {
983   if (Coleco_Palette[i*3+0]==0 &&
984       Coleco_Palette[i*3+1]==0 &&
985       Coleco_Palette[i*3+2]==0)
986    PalBuf[i]=Black;
987   else if (
988       Coleco_Palette[i*3+0]==255 &&
989       Coleco_Palette[i*3+1]==255 &&
990       Coleco_Palette[i*3+2]==255)
991    PalBuf[i]=White;
992   else
993   {
994    Colour.flags=DoRed|DoGreen|DoBlue;
995    Colour.red=Coleco_Palette[i*3+0]<<8;
996    Colour.green=Coleco_Palette[i*3+1]<<8;
997    Colour.blue=Coleco_Palette[i*3+2]<<8;
998    if (XAllocColor(Dsp,DefaultCMap,&Colour))
999 #ifdef LSB_FIRST
1000     if (BitmapBitOrder(Dsp)==LSBFirst)
1001 #else
1002     if (BitmapBitOrder(Dsp)==MSBFirst)
1003 #endif
1004      PalBuf[i]=Colour.pixel;
1005     else
1006      PalBuf[i]=SwapBytes (Colour.pixel,bpp);
1007    else
1008    {
1009     if (Verbose) puts ("FAILED");
1010     return 0;
1011    }
1012   }
1013  }
1014  if (Verbose) puts ("OK");
1015  while ((snapshotfile=fopen(szSnapshotFile,"rb"))!=NULL)
1016  {
1017   fclose (snapshotfile);
1018   if (!NextSnapshotFile())
1019    break;
1020  }
1021  if (Verbose)
1022   printf ("  Next snapshot will be %s\n",szSnapshotFile);
1023  JoyState[0]=JoyState[1]=MouseJoyState[0]=MouseJoyState[1]=
1024  JoystickJoyState[0]=JoystickJoyState[1]=0x7F7F;
1025  InitSound ();
1026  if (expansionmode==2 || expansionmode==3 ||
1027      (expansionmode!=1 && expansionmode!=4 && joystick))
1028   Joy_Init ();
1029  if (expansionmode==1 || expansionmode==4 ||
1030      expansionmode==5 || expansionmode==6 ||
1031      expansionmode==7)
1032   i=Mouse_Detect ();
1033  if (mouse_sens<=0 || mouse_sens>1000)
1034   mouse_sens=default_mouse_sens;
1035  switch (expansionmode)
1036  {
1037   case 2:
1038   case 3:
1039    if (!gotjoy)
1040    {
1041     expansionmode=0;
1042     break;
1043    }
1044    CalibrateJoystick ();
1045    break;
1046   case 1:
1047   case 4:
1048   case 5:
1049   case 6:
1050   case 7:
1051    if (!got_mouse)
1052     expansionmode=0;
1053    break;
1054   default:
1055    expansionmode=0;
1056    default_mouse_sens*=5;
1057    break;
1058  }
1059  if (syncemu)
1060   OldTimer=ReadTimer ();
1061  /* Parse keyboard mapping string */
1062  sscanf (szKeys,"%03X%03X%03X%03X%03X%03X%03X%03X",
1063          &KEY_LEFT,&KEY_RIGHT,&KEY_UP,&KEY_DOWN,
1064          &KEY_BUTTONA,&KEY_BUTTONB,&KEY_BUTTONC,&KEY_BUTTOND);
1065  Mouse_Init ();
1066  keyboardmode=(EmuMode)? 1:0;
1067  return 1;
1068 }
1069 
1070 /****************************************************************************/
1071 /** Routines to modify the Coleco gamport status                           **/
1072 /****************************************************************************/
numkeypressed(int nScanCode)1073 static int numkeypressed (int nScanCode)
1074 {
1075  int nOr;
1076  switch (nScanCode)
1077  {
1078   case SCANCODE_1:
1079   case SCANCODE_KEYPAD1:
1080    nOr=1;
1081    break;
1082   case SCANCODE_2:
1083   case SCANCODE_KEYPAD2:
1084    nOr=2;
1085    break;
1086   case SCANCODE_3:
1087   case SCANCODE_KEYPAD3:
1088    nOr=3;
1089    break;
1090   case SCANCODE_4:
1091   case SCANCODE_KEYPAD4:
1092    nOr=4;
1093    break;
1094   case SCANCODE_5:
1095   case SCANCODE_KEYPAD5:
1096    nOr=5;
1097    break;
1098   case SCANCODE_6:
1099   case SCANCODE_KEYPAD6:
1100    nOr=6;
1101    break;
1102   case SCANCODE_7:
1103   case SCANCODE_KEYPAD7:
1104    nOr=7;
1105    break;
1106   case SCANCODE_8:
1107   case SCANCODE_KEYPAD8:
1108    nOr=8;
1109    break;
1110   case SCANCODE_9:
1111   case SCANCODE_KEYPAD9:
1112    nOr=9;
1113    break;
1114   case SCANCODE_EQUAL:
1115   case SCANCODE_KEYPADENTER:
1116    nOr=10;
1117    break;
1118   case SCANCODE_MINUS:
1119   case SCANCODE_KEYPADPERIOD:
1120    nOr=11;
1121    break;
1122   default:
1123    nOr=0;
1124  }
1125  return nOr;
1126 }
1127 
Joysticks(void)1128 static void Joysticks (void)
1129 {
1130  int i,tmp,tmp2;
1131  MouseJoyState[0]|=0x7F7F;
1132  MouseJoyState[1]|=0x7F7F;
1133  Mouse_Check ();
1134  JoystickJoyState[0]|=0x7F7F;
1135  JoystickJoyState[1]|=0x7F7F;
1136  Joy_Check ();
1137  JoyState[1]=(MouseJoyState[0] & JoystickJoyState[0]);
1138  JoyState[0]=(MouseJoyState[1] & JoystickJoyState[1]);
1139  if (!keyboardmode)
1140  {
1141   if (keybstatus[KEY_BUTTONA])
1142    JoyState[0]&=(swapbuttons&2)? 0xFFBF:0xBFFF;
1143   if (keybstatus[KEY_BUTTONB])
1144    JoyState[0]&=(swapbuttons&2)? 0xBFFF:0xFFBF;
1145   if (keybstatus[KEY_DOWN])
1146    JoyState[0]&=0xFBFF;
1147   if (keybstatus[KEY_UP])
1148    JoyState[0]&=0xFEFF;
1149   if (keybstatus[KEY_LEFT])
1150    JoyState[0]&=0xF7FF;
1151   if (keybstatus[KEY_RIGHT])
1152    JoyState[0]&=0xFDFF;
1153   for (i=SCANCODE_0;i<=SCANCODE_9;++i)
1154    if (keybstatus[i])
1155    {
1156     tmp=numkeypressed(i);
1157     JoyState[0]=(JoyState[0]&0xFFF0)|tmp;
1158    }
1159   if (keybstatus[SCANCODE_MINUS])
1160   {
1161    tmp=numkeypressed(SCANCODE_MINUS);
1162    JoyState[0]=(JoyState[0]&0xFFF0)|tmp;
1163   }
1164   if (keybstatus[SCANCODE_EQUAL])
1165   {
1166    tmp=numkeypressed(SCANCODE_EQUAL);
1167    JoyState[0]=(JoyState[0]&0xFFF0)|tmp;
1168   }
1169   if (keybstatus[KEY_BUTTONC])
1170    JoyState[0]=(JoyState[0]&0xFFF0)|12;
1171   if (keybstatus[KEY_BUTTOND])
1172    JoyState[0]=(JoyState[0]&0xFFF0)|13;
1173   for (i=SCANCODE_KEYPAD7;i<=SCANCODE_KEYPAD9;++i)
1174    if (keybstatus[i])
1175    {
1176     tmp=numkeypressed((keypadmode)? (i-SCANCODE_KEYPAD7+SCANCODE_KEYPAD1) : i);
1177     JoyState[1]=(JoyState[1]&0xFFF0)|tmp;
1178    }
1179   for (i=SCANCODE_KEYPAD4;i<=SCANCODE_KEYPAD6;++i)
1180    if (keybstatus[i])
1181    {
1182     tmp=numkeypressed(i);
1183     JoyState[1]=(JoyState[1]&0xFFF0)|tmp;
1184    }
1185   for (i=SCANCODE_KEYPAD1;i<=SCANCODE_KEYPAD3;++i)
1186    if (keybstatus[i])
1187    {
1188     tmp=numkeypressed((keypadmode)? (i-SCANCODE_KEYPAD1+SCANCODE_KEYPAD7) : i);
1189     JoyState[1]=(JoyState[1]&0xFFF0)|tmp;
1190    }
1191   if (keybstatus[SCANCODE_KEYPAD0])
1192   {
1193    tmp=numkeypressed((keypadmode)? SCANCODE_KEYPADPERIOD : SCANCODE_KEYPAD0);
1194    JoyState[1]=(JoyState[1]&0xFFF0)|tmp;
1195   }
1196   if (keybstatus[SCANCODE_KEYPADPERIOD])
1197   {
1198    tmp=numkeypressed((keypadmode)? SCANCODE_KEYPAD0 : SCANCODE_KEYPADPERIOD);
1199    JoyState[1]=(JoyState[1]&0xFFF0)|tmp;
1200   }
1201   if (keybstatus[SCANCODE_KEYPADENTER])
1202   {
1203    tmp=numkeypressed(SCANCODE_KEYPADENTER);
1204    JoyState[1]=(JoyState[1]&0xFFF0)|tmp;
1205   }
1206   if (keybstatus[SCANCODE_KEYPADPLUS])
1207    JoyState[1]=(JoyState[1]&0xFFF0)|13;
1208   if (keybstatus[SCANCODE_KEYPADMINUS])
1209    JoyState[1]=(JoyState[1]&0xFFF0)|12;
1210  }
1211  switch (expansionmode)
1212  {
1213   case 1:                         /* emulate roller controller with mouse   */
1214   case 2:                         /* emulate RC with joystick               */
1215    if ((JoyState[1]&0x0F)==12 || (JoyState[1]&0x0F)==13)
1216     JoyState[1]|=0x0F;
1217    if ((JoyState[0]&0x0F)==12 || (JoyState[0]&0x0F)==13)
1218     JoyState[0]|=0x0F;
1219    tmp=JoyState[1];
1220    JoyState[1]=(JoyState[0]&0x707F)|0x0F00;
1221    JoyState[0]=(tmp&0x7F7F);
1222    if ((JoyState[1]&0xF)!=0xF)
1223     JoyState[0]=(JoyState[0]&0xFFF0)|(JoyState[1]&0x0F);
1224    JoyState[1]=(JoyState[1]&0xFFF0)|(JoyState[0]&0x0F);
1225    break;
1226   case 3:                         /* emulate driving module with joystick   */
1227   case 4:                         /* emulate driving module with mouse      */
1228    if ((JoyState[1]&0x0F)==12 || (JoyState[1]&0x0F)==13)
1229     JoyState[1]|=0x0F;
1230    if ((JoyState[0]&0x0F)==12 || (JoyState[0]&0x0F)==13)
1231     JoyState[0]|=0x0F;
1232    if ((JoyState[1]&0xF)!=0xF)
1233     JoyState[0]=(JoyState[0]&0xFFF0)|(JoyState[1]&0x0F);
1234    if ((JoyState[1]&0x0100)==0)
1235     JoyState[1]&=0xBFFF;
1236    else
1237     JoyState[1]|=0x4000;
1238    JoyState[1]|=0x0F7F;
1239    tmp=JoyState[1];
1240    JoyState[1]=JoyState[0];
1241    JoyState[0]=tmp|0x0040;
1242    break;
1243   default:
1244    switch (joystick)
1245    {
1246     case 1:                       /* Joystick 1=Joystick 2                  */
1247      tmp=JoyState[0]&0x0F;
1248      tmp2=JoyState[1]&0x0F;
1249      if (tmp==12 || tmp==13)
1250       JoyState[1]=(JoyState[1]&0xFFF0)|(JoyState[0]&0xF);
1251      else
1252       if (tmp2==12 || tmp2==13)
1253        JoyState[0]=(JoyState[0]&0xFFF0)|(JoyState[1]&0xF);
1254       else
1255        if (tmp2!=15)
1256        {
1257         JoyState[0]=(JoyState[0]&0xFFF0)|(JoyState[1]&0x0F);
1258         JoyState[1]|=15;
1259        }
1260      JoyState[0]&=(JoyState[1]|0xF);
1261      JoyState[1]&=(JoyState[0]|0xF);
1262      break;
1263     case 2:                       /* Joystick 1=keyb, Joystick 2=joystick   */
1264      break;
1265     case 3:                       /* Joystick 1=joystick, Joystick 2=keyb   */
1266      tmp=JoyState[0];
1267      JoyState[0]=JoyState[1];
1268      JoyState[1]=tmp;
1269      break;
1270    }
1271    break;
1272  }
1273 }
1274 
1275 /****************************************************************************/
1276 /*** Parse keyboard events                                                ***/
1277 /****************************************************************************/
Keyboard(void)1278 void Keyboard (void)
1279 {
1280  int tmp;
1281  XEvent E;
1282  keyboard_update ();
1283  /* Check if reset combination is pressed */
1284  if (AltPressed())
1285  {
1286   if (keybstatus[SCANCODE_F12]) ResetColeco (0);
1287   if (keybstatus[SCANCODE_F11]) ResetColeco (1);
1288  }
1289  /* Update keyboard buffer */
1290  do
1291  {
1292   tmp=LocalGetKeyboardChar ();
1293   if (tmp) AddToKeyboardBuffer (tmp);
1294  }
1295  while (tmp);
1296  /* Check mouse and joystick events */
1297  Joysticks ();
1298  /* Check is PAUSE is pressed */
1299  if (PausePressed)
1300  {
1301   StopSound ();
1302   tmp=0;
1303   while (PausePressed) keyboard_update();
1304   ResumeSound ();
1305   if (syncemu)
1306    OldTimer=ReadTimer ();
1307  }
1308  /* If saving CPU and focus is out, sleep */
1309  tmp=0;
1310  while (XCheckWindowEvent(Dsp,Wnd,FocusChangeMask,&E))
1311   tmp=(E.type==FocusOut);
1312  if(SaveCPU&&tmp)
1313  {
1314   StopSound ();
1315   while(!XCheckWindowEvent(Dsp,Wnd,FocusChangeMask,&E)&&Z80_Running)
1316   {
1317    if(XCheckWindowEvent(Dsp,Wnd,ExposureMask,&E)) PutImage();
1318    XPeekEvent(Dsp,&E);
1319   }
1320   ResumeSound ();
1321   OldTimer=ReadTimer ();
1322  }
1323 /* Check if a snapshot should be taken */
1324  if (makesnap)
1325  {
1326   SaveSnapshotFile (szSnapshotFile);
1327   NextSnapshotFile ();
1328   makesnap--;
1329  }
1330  /* Check if OptionsDialogue() should be called */
1331  if (calloptions)
1332  {
1333   calloptions=0;
1334   StopSound ();
1335   OptionsDialogue ();
1336   ResumeSound ();
1337   if (syncemu) OldTimer=ReadTimer();
1338  }
1339 }
1340 
1341 /****************************************************************************/
1342 /** Interrupt routines                                                     **/
1343 /****************************************************************************/
1344 /* Gets called 50 times per second */
CheckScreenRefresh(void)1345 int CheckScreenRefresh (void)
1346 {
1347  static int skipped=0;
1348  if (syncemu)
1349  {
1350   NewTimer=ReadTimer ();
1351   OldTimer+=1000000/IFreq;
1352   if ((OldTimer-NewTimer)>0)
1353   {
1354    do
1355     NewTimer=ReadTimer ();
1356    while ((NewTimer-OldTimer)<0);
1357    skipped=0;
1358    return 1;
1359   }
1360   else
1361    if (++skipped>=UPeriod)
1362    {
1363     OldTimer=ReadTimer ();
1364     skipped=0;
1365     return 1;
1366    }
1367    else
1368     return 0;
1369  }
1370  return 2;
1371 }
1372 
PutPixel32_0(int offset,int c)1373 FASTCALL static void PutPixel32_0 (int offset,int c)
1374 {
1375  *(unsigned*)(DisplayBuf+offset*4)=c;
1376 }
1377 
PutPixel16_0(int offset,int c)1378 FASTCALL static void PutPixel16_0 (int offset,int c)
1379 {
1380  *(unsigned short*)(DisplayBuf+offset*2)=c;
1381 }
1382 
PutPixel8_0(int offset,int c)1383 FASTCALL static void PutPixel8_0 (int offset,int c)
1384 {
1385  DisplayBuf[offset]=c;
1386 }
1387 
PutPixel32_1(int offset,int c)1388 FASTCALL static void PutPixel32_1 (int offset,int c)
1389 {
1390  *(unsigned*)(DisplayBuf+offset*4*2)=
1391  *(unsigned*)(DisplayBuf+offset*4*2+1)=
1392  c;
1393 }
1394 
PutPixel16_1(int offset,int c)1395 FASTCALL static void PutPixel16_1 (int offset,int c)
1396 {
1397  *(unsigned short*)(DisplayBuf+offset*2*2)=
1398  *(unsigned short*)(DisplayBuf+offset*2*2+1)=
1399  c;
1400 }
1401 
PutPixel8_1(int offset,int c)1402 FASTCALL static void PutPixel8_1 (int offset,int c)
1403 {
1404  DisplayBuf[offset*2]=DisplayBuf[offset*2+1]=c;
1405 }
1406 
PutPixel32_2(int offset,int c)1407 FASTCALL static void PutPixel32_2 (int offset,int c)
1408 {
1409  offset=(offset&0x00FF)+((offset&0xFF00)<<1);
1410  *(unsigned*)(DisplayBuf+offset*4*2)=
1411  *(unsigned*)(DisplayBuf+offset*4*2+1)=
1412  c;
1413 }
1414 
PutPixel16_2(int offset,int c)1415 FASTCALL static void PutPixel16_2 (int offset,int c)
1416 {
1417  offset=(offset&0x00FF)+((offset&0xFF00)<<1);
1418  *(unsigned short*)(DisplayBuf+offset*2*2)=
1419  *(unsigned short*)(DisplayBuf+offset*2*2+1)=
1420  c;
1421 }
1422 
PutPixel8_2(int offset,int c)1423 FASTCALL static void PutPixel8_2 (int offset,int c)
1424 {
1425  offset=(offset&0x00FF)+((offset&0xFF00)<<1);
1426  DisplayBuf[offset*2]=DisplayBuf[offset*2+1]=c;
1427 }
1428 
1429 /****************************************************************************/
1430 /** Screen refresh drivers                                                 **/
1431 /****************************************************************************/
1432 #include "Common.h"
1433