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