1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2006 Artsoft Entertainment *
5 * Holger Schemel *
6 * Detmolder Strasse 189 *
7 * 33604 Bielefeld *
8 * Germany *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
11 * msdos.c *
12 ***********************************************************/
13
14 #include "system.h"
15
16
17 #if defined(PLATFORM_MSDOS)
18
19 #include "sound.h"
20 #include "joystick.h"
21 #include "misc.h"
22 #include "setup.h"
23 #include "pcx.h"
24
25 #define AllegroDefaultScreen() (display->screens[display->default_screen])
26
27 /* allegro driver declarations */
28 DECLARE_GFX_DRIVER_LIST(GFX_DRIVER_VBEAF GFX_DRIVER_VESA2L GFX_DRIVER_VESA1)
29 DECLARE_COLOR_DEPTH_LIST(COLOR_DEPTH_8)
30 DECLARE_DIGI_DRIVER_LIST(DIGI_DRIVER_SB)
31 DECLARE_MIDI_DRIVER_LIST()
32 DECLARE_JOYSTICK_DRIVER_LIST(JOYSTICK_DRIVER_STANDARD)
33
34 /* allegro global variables */
35 extern volatile int key_shifts;
36 extern int num_joysticks;
37 extern JOYSTICK_INFO joy[];
38 extern int i_love_bill;
39
40 /* internal variables of msdos.c */
41 static boolean keyboard_auto_repeat = TRUE;
42 static int key_press_state[MAX_SCANCODES];
43 static XEvent event_buffer[MAX_EVENT_BUFFER];
44 static int pending_events;
45 static boolean joystick_event;
46 static boolean mouse_installed = FALSE;
47 static int last_mouse_pos;
48 static int last_mouse_b;
49 static int last_joystick_state;
50 static BITMAP* video_bitmap;
51
52 static RGB global_colormap[MAX_COLORS];
53 static int global_colormap_entries_used = 0;
54
55 boolean wait_for_vsync;
56
57 static BITMAP *Read_PCX_to_AllegroBitmap(char *);
58
allegro_init_drivers()59 static void allegro_init_drivers()
60 {
61 int i;
62
63 for (i = 0; i < MAX_EVENT_BUFFER; i++)
64 event_buffer[i].type = 0;
65
66 for (i = 0; i < MAX_SCANCODES; i++)
67 key_press_state[i] = KeyReleaseMask;
68
69 last_mouse_pos = mouse_pos;
70 last_mouse_b = 0;
71
72 pending_events = 0;
73 clear_keybuf();
74
75 /* enable Windows friendly timer mode (already default under Windows) */
76 i_love_bill = TRUE;
77
78 install_keyboard();
79 install_timer();
80 if (install_mouse() > 0)
81 mouse_installed = TRUE;
82
83 last_joystick_state = 0;
84 joystick_event = FALSE;
85 }
86
allegro_init_audio()87 static boolean allegro_init_audio()
88 {
89 reserve_voices(NUM_MIXER_CHANNELS, 0);
90
91 if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL) == -1)
92 if (install_sound(DIGI_SB, MIDI_NONE, NULL) == -1)
93 return FALSE;
94
95 return TRUE;
96 }
97
hide_mouse(Display * display,int x,int y,unsigned int width,unsigned int height)98 static boolean hide_mouse(Display *display, int x, int y,
99 unsigned int width, unsigned int height)
100 {
101 if (mouse_x + display->mouse_ptr->w < x || mouse_x > x + width)
102 return FALSE;
103 if (mouse_y + display->mouse_ptr->h < y || mouse_y > y + height)
104 return FALSE;
105
106 show_mouse(NULL);
107
108 return TRUE;
109 }
110
unhide_mouse(Display * display)111 static void unhide_mouse(Display *display)
112 {
113 if (mouse_installed)
114 show_mouse(video_bitmap);
115 }
116
ScancodeToKeySym(byte scancode)117 static KeySym ScancodeToKeySym(byte scancode)
118 {
119 switch(scancode)
120 {
121 case KEY_ESC: return XK_Escape;
122 case KEY_1: return XK_1;
123 case KEY_2: return XK_2;
124 case KEY_3: return XK_3;
125 case KEY_4: return XK_4;
126 case KEY_5: return XK_5;
127 case KEY_6: return XK_6;
128 case KEY_7: return XK_7;
129 case KEY_8: return XK_8;
130 case KEY_9: return XK_9;
131 case KEY_0: return XK_0;
132 case KEY_MINUS: return XK_minus;
133 case KEY_EQUALS: return XK_equal;
134 case KEY_BACKSPACE: return XK_BackSpace;
135 case KEY_TAB: return XK_Tab;
136 case KEY_Q: return XK_q;
137 case KEY_W: return XK_w;
138 case KEY_E: return XK_e;
139 case KEY_R: return XK_r;
140 case KEY_T: return XK_t;
141 case KEY_Y: return XK_y;
142 case KEY_U: return XK_u;
143 case KEY_I: return XK_i;
144 case KEY_O: return XK_o;
145 case KEY_P: return XK_p;
146 case KEY_OPENBRACE: return XK_braceleft;
147 case KEY_CLOSEBRACE: return XK_braceright;
148 case KEY_ENTER: return XK_Return;
149 case KEY_LCONTROL: return XK_Control_L;
150 case KEY_A: return XK_a;
151 case KEY_S: return XK_s;
152 case KEY_D: return XK_d;
153 case KEY_F: return XK_f;
154 case KEY_G: return XK_g;
155 case KEY_H: return XK_h;
156 case KEY_J: return XK_j;
157 case KEY_K: return XK_k;
158 case KEY_L: return XK_l;
159 case KEY_COLON: return XK_colon;
160 case KEY_QUOTE: return XK_apostrophe;
161 case KEY_TILDE: return XK_asciitilde;
162 case KEY_LSHIFT: return XK_Shift_L;
163 case KEY_BACKSLASH: return XK_backslash;
164 case KEY_Z: return XK_z;
165 case KEY_X: return XK_x;
166 case KEY_C: return XK_c;
167 case KEY_V: return XK_v;
168 case KEY_B: return XK_b;
169 case KEY_N: return XK_n;
170 case KEY_M: return XK_m;
171 case KEY_COMMA: return XK_comma;
172 case KEY_STOP: return XK_period;
173 case KEY_SLASH: return XK_slash;
174 case KEY_RSHIFT: return XK_Shift_R;
175 case KEY_ASTERISK: return XK_KP_Multiply;
176 case KEY_ALT: return XK_Alt_L;
177 case KEY_SPACE: return XK_space;
178 case KEY_CAPSLOCK: return XK_Caps_Lock;
179 case KEY_F1: return XK_F1;
180 case KEY_F2: return XK_F2;
181 case KEY_F3: return XK_F3;
182 case KEY_F4: return XK_F4;
183 case KEY_F5: return XK_F5;
184 case KEY_F6: return XK_F6;
185 case KEY_F7: return XK_F7;
186 case KEY_F8: return XK_F8;
187 case KEY_F9: return XK_F9;
188 case KEY_F10: return XK_F10;
189 case KEY_NUMLOCK: return XK_Num_Lock;
190 case KEY_SCRLOCK: return XK_Scroll_Lock;
191 case KEY_HOME: return XK_Home;
192 case KEY_UP: return XK_Up;
193 case KEY_PGUP: return XK_Page_Up;
194 case KEY_MINUS_PAD: return XK_KP_Subtract;
195 case KEY_LEFT: return XK_Left;
196 case KEY_5_PAD: return XK_KP_5;
197 case KEY_RIGHT: return XK_Right;
198 case KEY_PLUS_PAD: return XK_KP_Add;
199 case KEY_END: return XK_End;
200 case KEY_DOWN: return XK_Down;
201 case KEY_PGDN: return XK_Page_Down;
202 case KEY_INSERT: return XK_Insert;
203 case KEY_DEL: return XK_Delete;
204 case KEY_PRTSCR: return XK_Print;
205 case KEY_F11: return XK_F11;
206 case KEY_F12: return XK_F12;
207 case KEY_LWIN: return XK_Meta_L;
208 case KEY_RWIN: return XK_Meta_R;
209 case KEY_MENU: return XK_Menu;
210 case KEY_PAD: return XK_VoidSymbol;
211 case KEY_RCONTROL: return XK_Control_R;
212 case KEY_ALTGR: return XK_Alt_R;
213 case KEY_SLASH2: return XK_KP_Divide;
214 case KEY_PAUSE: return XK_Pause;
215
216 case NEW_KEY_BACKSLASH: return XK_backslash;
217 case NEW_KEY_1_PAD: return XK_KP_1;
218 case NEW_KEY_2_PAD: return XK_KP_2;
219 case NEW_KEY_3_PAD: return XK_KP_3;
220 case NEW_KEY_4_PAD: return XK_KP_4;
221 case NEW_KEY_5_PAD: return XK_KP_5;
222 case NEW_KEY_6_PAD: return XK_KP_6;
223 case NEW_KEY_7_PAD: return XK_KP_7;
224 case NEW_KEY_8_PAD: return XK_KP_8;
225 case NEW_KEY_9_PAD: return XK_KP_9;
226 case NEW_KEY_0_PAD: return XK_KP_0;
227 case NEW_KEY_STOP_PAD: return XK_KP_Separator;
228 case NEW_KEY_EQUALS_PAD: return XK_KP_Equal;
229 case NEW_KEY_SLASH_PAD: return XK_KP_Divide;
230 case NEW_KEY_ASTERISK_PAD: return XK_KP_Multiply;
231 case NEW_KEY_ENTER_PAD: return XK_KP_Enter;
232
233 default: return XK_VoidSymbol;
234 }
235 }
236
AllegroAllocColorCell(int r,int g,int b)237 Pixel AllegroAllocColorCell(int r, int g, int b)
238 {
239 byte pixel_mapping = 0;
240 int i;
241
242 r >>= 10;
243 g >>= 10;
244 b >>= 10;
245
246 /* try to use existing colors from the global colormap */
247 for (i = 0; i < global_colormap_entries_used; i++)
248 {
249 if (r == global_colormap[i].r &&
250 g == global_colormap[i].g &&
251 b == global_colormap[i].b) /* color found */
252 {
253 pixel_mapping = i;
254 break;
255 }
256 }
257
258 if (i == global_colormap_entries_used) /* color not found */
259 {
260 if (global_colormap_entries_used < MAX_COLORS)
261 global_colormap_entries_used++;
262
263 i = global_colormap_entries_used - 1;
264
265 global_colormap[i].r = r;
266 global_colormap[i].g = g;
267 global_colormap[i].b = b;
268
269 set_palette(global_colormap);
270
271 pixel_mapping = i;
272 }
273
274 return pixel_mapping;
275 }
276
XMapWindow(Display * display,Window window)277 void XMapWindow(Display *display, Window window)
278 {
279 int x, y;
280 unsigned int width, height;
281 boolean mouse_off;
282
283 x = AllegroDefaultScreen().x;
284 y = AllegroDefaultScreen().y;
285 width = AllegroDefaultScreen().width;
286 height = AllegroDefaultScreen().height;
287
288 mouse_off = hide_mouse(display, x, y, width, height);
289 blit((BITMAP *)window, video_bitmap, 0, 0, x, y, width, height);
290
291 if (mouse_off)
292 unhide_mouse(display);
293 }
294
XOpenDisplay(char * display_name)295 Display *XOpenDisplay(char *display_name)
296 {
297 Screen *screen;
298 Display *display;
299 BITMAP *mouse_bitmap = NULL;
300 char *mouse_filename = getCustomImageFilename(program.msdos_cursor_filename);
301
302 if ((mouse_bitmap = Read_PCX_to_AllegroBitmap(mouse_filename)) == NULL)
303 return NULL;
304
305 screen = malloc(sizeof(Screen));
306 display = malloc(sizeof(Display));
307
308 screen[0].cmap = 0;
309 screen[0].root = 0;
310 screen[0].white_pixel = AllegroAllocColorCell(0xFFFF, 0xFFFF, 0xFFFF);
311 screen[0].black_pixel = AllegroAllocColorCell(0x0000, 0x0000, 0x0000);
312 screen[0].video_bitmap = NULL;
313
314 display->default_screen = 0;
315 display->screens = screen;
316 display->mouse_ptr = mouse_bitmap;
317
318 allegro_init();
319 allegro_init_drivers();
320 set_color_depth(8);
321
322 /* force Windows 95 to switch to fullscreen mode */
323 set_gfx_mode(GFX_AUTODETECT, 320, 200, 0, 0);
324 rest(200);
325 set_gfx_mode(GFX_AUTODETECT, XRES, YRES, 0, 0);
326
327 return display;
328 }
329
XCreateSimpleWindow(Display * display,Window parent,int x,int y,unsigned int width,unsigned int height,unsigned int border_width,unsigned int border,unsigned int background)330 Window XCreateSimpleWindow(Display *display, Window parent, int x, int y,
331 unsigned int width, unsigned int height,
332 unsigned int border_width, unsigned int border,
333 unsigned int background)
334 {
335 video_bitmap = create_video_bitmap(XRES, YRES);
336 clear_to_color(video_bitmap, background);
337
338 AllegroDefaultScreen().video_bitmap = video_bitmap;
339 AllegroDefaultScreen().x = x;
340 AllegroDefaultScreen().y = y;
341 AllegroDefaultScreen().width = XRES;
342 AllegroDefaultScreen().height = YRES;
343
344 set_mouse_sprite(display->mouse_ptr);
345
346 #if 0
347 set_mouse_sprite_focus(1, 1);
348 #endif
349
350 set_mouse_speed(1, 1);
351 set_mouse_range(AllegroDefaultScreen().x + 1,
352 AllegroDefaultScreen().y + 1,
353 AllegroDefaultScreen().x + video.width + 1,
354 AllegroDefaultScreen().y + video.height + 1);
355
356 show_video_bitmap(video_bitmap);
357
358 return (Window)video_bitmap;
359 }
360
XStringListToTextProperty(char ** list,int count,XTextProperty * text_prop_return)361 Status XStringListToTextProperty(char **list, int count,
362 XTextProperty *text_prop_return)
363 {
364 char *string;
365
366 if (count >= 1)
367 {
368 string = malloc(strlen(list[0] + 1));
369 strcpy(string, list[0]);
370 text_prop_return->value = (unsigned char *)string;
371 return 1;
372 }
373 else
374 text_prop_return = NULL;
375
376 return 0;
377 }
378
XFree(void * data)379 void XFree(void *data)
380 {
381 checked_free(data);
382 }
383
XCreateGC(Display * display,Drawable d,unsigned int value_mask,XGCValues * values)384 GC XCreateGC(Display *display, Drawable d, unsigned int value_mask,
385 XGCValues *values)
386 {
387 XGCValues *gcv;
388 gcv = malloc(sizeof(XGCValues));
389 gcv->foreground = values->foreground;
390 gcv->background = values->background;
391 gcv->graphics_exposures = values->graphics_exposures;
392 gcv->clip_mask = values->clip_mask;
393 gcv->clip_x_origin = values->clip_x_origin;
394 gcv->clip_y_origin = values->clip_y_origin;
395 gcv->value_mask = value_mask;
396 return (GC)gcv;
397 }
398
XSetClipMask(Display * display,GC gc,Pixmap pixmap)399 void XSetClipMask(Display *display, GC gc, Pixmap pixmap)
400 {
401 XGCValues *gcv = (XGCValues *)gc;
402
403 gcv->clip_mask = pixmap;
404 gcv->value_mask |= GCClipMask;
405 }
406
XSetClipOrigin(Display * display,GC gc,int x,int y)407 void XSetClipOrigin(Display *display, GC gc, int x, int y)
408 {
409 XGCValues *gcv = (XGCValues *)gc;
410
411 gcv->clip_x_origin = x;
412 gcv->clip_x_origin = y;
413 }
414
XFillRectangle(Display * display,Drawable d,GC gc,int x,int y,unsigned int width,unsigned int height)415 void XFillRectangle(Display *display, Drawable d, GC gc, int x, int y,
416 unsigned int width, unsigned int height)
417 {
418 boolean mouse_off = FALSE;
419
420 if ((BITMAP *)d == video_bitmap)
421 {
422 x += AllegroDefaultScreen().x;
423 y += AllegroDefaultScreen().y;
424 freeze_mouse_flag = TRUE;
425 mouse_off = hide_mouse(display, x, y, width, height);
426 }
427
428 rectfill((BITMAP *)d, x, y, x + width - 1, y + height - 1,
429 ((XGCValues *)gc)->foreground);
430
431 if (mouse_off)
432 unhide_mouse(display);
433
434 freeze_mouse_flag = FALSE;
435 }
436
XCreatePixmap(Display * display,Drawable d,unsigned int width,unsigned int height,unsigned int depth)437 Pixmap XCreatePixmap(Display *display, Drawable d, unsigned int width,
438 unsigned int height, unsigned int depth)
439 {
440 BITMAP *bitmap = NULL;
441
442 if (gfx_capabilities & GFX_HW_VRAM_BLIT &&
443 width == gfx.scrollbuffer_width && height == gfx.scrollbuffer_height)
444 bitmap = create_video_bitmap(width, height);
445
446 if (bitmap == NULL)
447 bitmap = create_bitmap(width, height);
448
449 return (Pixmap)bitmap;
450 }
451
XSync(Display * display,Bool discard_events)452 void XSync(Display *display, Bool discard_events)
453 {
454 wait_for_vsync = TRUE;
455 }
456
XCopyArea(Display * display,Drawable src,Drawable dest,GC gc,int src_x,int src_y,unsigned int width,unsigned int height,int dest_x,int dest_y)457 inline void XCopyArea(Display *display, Drawable src, Drawable dest, GC gc,
458 int src_x, int src_y,
459 unsigned int width, unsigned int height,
460 int dest_x, int dest_y)
461 {
462 boolean mouse_off = FALSE;
463
464 if ((BITMAP *)src == video_bitmap)
465 {
466 src_x += AllegroDefaultScreen().x;
467 src_y += AllegroDefaultScreen().y;
468 }
469
470 if ((BITMAP *)dest == video_bitmap)
471 {
472 dest_x += AllegroDefaultScreen().x;
473 dest_y += AllegroDefaultScreen().y;
474 freeze_mouse_flag = TRUE;
475 mouse_off = hide_mouse(display, dest_x, dest_y, width, height);
476 }
477
478 if (wait_for_vsync)
479 {
480 wait_for_vsync = FALSE;
481 vsync();
482 }
483
484 if (((XGCValues *)gc)->value_mask & GCClipMask)
485 masked_blit((BITMAP *)src, (BITMAP *)dest, src_x, src_y, dest_x, dest_y,
486 width, height);
487 else
488 blit((BITMAP *)src, (BITMAP *)dest, src_x, src_y, dest_x, dest_y,
489 width, height);
490
491 if (mouse_off)
492 unhide_mouse(display);
493
494 freeze_mouse_flag = FALSE;
495 }
496
Image_to_AllegroBitmap(Image * image)497 static BITMAP *Image_to_AllegroBitmap(Image *image)
498 {
499 BITMAP *bitmap;
500 byte *src_ptr = image->data;
501 byte pixel_mapping[MAX_COLORS];
502 unsigned int depth = 8;
503 int i, x, y;
504
505 if (image->type == IMAGETYPE_TRUECOLOR && depth == 8)
506 Error(ERR_EXIT, "cannot handle true-color images on 8-bit display");
507
508 /* allocate new allegro bitmap structure */
509 if ((bitmap = create_bitmap_ex(depth, image->width, image->height)) == NULL)
510 {
511 errno_pcx = PCX_NoMemory;
512 return NULL;
513 }
514
515 clear(bitmap);
516
517 /* try to use existing colors from the global colormap */
518 for (i = 0; i < MAX_COLORS; i++)
519 {
520 if (!image->rgb.color_used[i])
521 continue;
522
523 pixel_mapping[i] = AllegroAllocColorCell(image->rgb.red[i],
524 image->rgb.green[i],
525 image->rgb.blue[i]);
526 }
527
528 /* copy bitmap data */
529 for (y = 0; y < image->height; y++)
530 for (x = 0; x < image->width; x++)
531 putpixel(bitmap, x, y, pixel_mapping[*src_ptr++]);
532
533 return bitmap;
534 }
535
Read_PCX_to_AllegroBitmap(char * filename)536 static BITMAP *Read_PCX_to_AllegroBitmap(char *filename)
537 {
538 BITMAP *bitmap;
539 Image *image;
540
541 /* read the graphic file in PCX format to internal image structure */
542 if ((image = Read_PCX_to_Image(filename)) == NULL)
543 return NULL;
544
545 /* convert internal image structure to allegro bitmap structure */
546 if ((bitmap = Image_to_AllegroBitmap(image)) == NULL)
547 return NULL;
548
549 set_palette(global_colormap);
550
551 return bitmap;
552 }
553
Read_PCX_to_Pixmap(Display * display,Window window,GC gc,char * filename,Pixmap * pixmap,Pixmap * pixmap_mask)554 int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename,
555 Pixmap *pixmap, Pixmap *pixmap_mask)
556 {
557 BITMAP *bitmap;
558
559 if ((bitmap = Read_PCX_to_AllegroBitmap(filename)) == NULL)
560 return errno_pcx;
561
562 *pixmap = (Pixmap)bitmap;
563
564 /* pixmap_mask will never be used in Allegro (which uses masked_blit()),
565 so use non-NULL dummy pointer to empty Pixmap */
566 *pixmap_mask = (Pixmap)DUMMY_MASK;
567
568 return PCX_Success;
569 }
570
XReadBitmapFile(Display * display,Drawable d,char * filename,unsigned int * width_return,unsigned int * height_return,Pixmap * bitmap_return,int * x_hot_return,int * y_hot_return)571 int XReadBitmapFile(Display *display, Drawable d, char *filename,
572 unsigned int *width_return, unsigned int *height_return,
573 Pixmap *bitmap_return,
574 int *x_hot_return, int *y_hot_return)
575 {
576 BITMAP *bitmap;
577
578 if ((bitmap = Read_PCX_to_AllegroBitmap(filename)) == NULL)
579 return BitmapOpenFailed;
580
581 *width_return = bitmap->w;
582 *height_return = bitmap->h;
583 *x_hot_return = -1;
584 *y_hot_return = -1;
585 *bitmap_return = (Pixmap)bitmap;
586
587 return BitmapSuccess;
588 }
589
XFreePixmap(Display * display,Pixmap pixmap)590 void XFreePixmap(Display *display, Pixmap pixmap)
591 {
592 if (pixmap != DUMMY_MASK &&
593 (is_memory_bitmap((BITMAP *)pixmap) ||
594 is_screen_bitmap((BITMAP *)pixmap)))
595 destroy_bitmap((BITMAP *)pixmap);
596 }
597
XFreeGC(Display * display,GC gc)598 void XFreeGC(Display *display, GC gc)
599 {
600 XGCValues *gcv = (XGCValues *)gc;
601
602 checked_free(gcv);
603 }
604
XUnmapWindow(Display * display,Window window)605 void XUnmapWindow(Display *display, Window window)
606 {
607 }
608
XCloseDisplay(Display * display)609 void XCloseDisplay(Display *display)
610 {
611 BITMAP *bitmap = video_bitmap;
612
613 if (is_screen_bitmap(bitmap))
614 destroy_bitmap(bitmap);
615
616 checked_free(display->screens);
617 checked_free(display);
618
619 /* return to text mode (or DOS box on Windows screen) */
620 set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
621 }
622
XNextEvent(Display * display,XEvent * event_return)623 void XNextEvent(Display *display, XEvent *event_return)
624 {
625 while (!pending_events)
626 XPending(display);
627
628 memcpy(event_return, &event_buffer[pending_events], sizeof(XEvent));
629 pending_events--;
630 }
631
NewKeyEvent(int key_press_state,KeySym keysym)632 static void NewKeyEvent(int key_press_state, KeySym keysym)
633 {
634 XKeyEvent *xkey;
635
636 if (pending_events >= MAX_EVENT_BUFFER)
637 return;
638
639 pending_events++;
640 xkey = (XKeyEvent *)&event_buffer[pending_events];
641 xkey->type = key_press_state;
642 xkey->state = (unsigned int)keysym;
643 }
644
645 #define HANDLE_RAW_KB_ALL_KEYS 0
646 #define HANDLE_RAW_KB_MODIFIER_KEYS_ONLY 1
647
648 static int modifier_scancode[] =
649 {
650 KEY_LSHIFT,
651 KEY_RSHIFT,
652 KEY_LCONTROL,
653 KEY_RCONTROL,
654 KEY_ALT,
655 KEY_ALTGR,
656 KEY_LWIN,
657 KEY_RWIN,
658 KEY_CAPSLOCK,
659 KEY_NUMLOCK,
660 KEY_SCRLOCK,
661 -1
662 };
663
HandleKeyboardRaw(int mode)664 static void HandleKeyboardRaw(int mode)
665 {
666 int i;
667
668 for (i = 0; i < MAX_SCANCODES; i++)
669 {
670 int scancode, new_state, event_type;
671 char key_pressed;
672
673 if (mode == HANDLE_RAW_KB_MODIFIER_KEYS_ONLY)
674 {
675 if ((scancode = modifier_scancode[i]) == -1)
676 return;
677 }
678 else
679 scancode = i;
680
681 key_pressed = key[scancode];
682 new_state = (key_pressed ? KeyPressMask : KeyReleaseMask);
683 event_type = (key_pressed ? KeyPress : KeyRelease);
684
685 if (key_press_state[i] == new_state) /* state not changed */
686 continue;
687
688 key_press_state[i] = new_state;
689
690 NewKeyEvent(event_type, ScancodeToKeySym(scancode));
691 }
692 }
693
HandleKeyboardEvent()694 static void HandleKeyboardEvent()
695 {
696 if (keypressed())
697 {
698 int key_info = readkey();
699 int scancode = (key_info >> 8);
700 int ascii = (key_info & 0xff);
701 KeySym keysym = ScancodeToKeySym(scancode);
702
703 if (scancode == KEY_PAD)
704 {
705 /* keys on the numeric keypad return just scancode 'KEY_PAD'
706 for some reason, so we must handle them separately */
707
708 if (ascii >= '0' && ascii <= '9')
709 keysym = XK_KP_0 + (KeySym)(ascii - '0');
710 else if (ascii == '.')
711 keysym = XK_KP_Separator;
712 }
713 else if (ascii >= ' ' && ascii <= 'Z')
714 keysym = XK_space + (KeySym)(ascii - ' ');
715 else if (ascii == '^')
716 keysym = XK_asciicircum;
717 else if (ascii == '_')
718 keysym = XK_underscore;
719 else if (ascii == '�')
720 keysym = XK_Adiaeresis;
721 else if (ascii == '�')
722 keysym = XK_Odiaeresis;
723 else if (ascii == '�')
724 keysym = XK_Udiaeresis;
725 else if (ascii == '�')
726 keysym = XK_adiaeresis;
727 else if (ascii == '�')
728 keysym = XK_odiaeresis;
729 else if (ascii == '�')
730 keysym = XK_udiaeresis;
731 else if (ascii == '�')
732 keysym = XK_ssharp;
733
734 NewKeyEvent(KeyPress, keysym);
735 }
736 else if (key_shifts & (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG))
737 {
738 /* the allegro function keypressed() does not give us single pressed
739 modifier keys, so we must detect them with the internal global
740 allegro variable 'key_shifts' and then handle them separately */
741
742 HandleKeyboardRaw(HANDLE_RAW_KB_MODIFIER_KEYS_ONLY);
743 }
744 }
745
XPending(Display * display)746 int XPending(Display *display)
747 {
748 XButtonEvent *xbutton;
749 XMotionEvent *xmotion;
750 int i;
751
752 /* When using 'HandleKeyboardRaw()', keyboard input is also stored in
753 the allegro keyboard input buffer and would be available a second
754 time by calling 'HandleKeyboardEvent()'. To avoid double keyboard
755 events, the allegro function 'clear_keybuf()' must be called each
756 time when switching from calling 'HandleKeyboardRaw()' to calling
757 'HandleKeyboardEvent()' to get keyboard input, which is actually
758 done by 'XAutoRepeatOn()' which sets keyboard_auto_repeat to TRUE. */
759
760 /* keyboard event */
761 if (keyboard_auto_repeat)
762 HandleKeyboardEvent();
763 else
764 HandleKeyboardRaw(HANDLE_RAW_KB_ALL_KEYS);
765
766 /* mouse motion event */
767 if (mouse_pos != last_mouse_pos)
768 {
769 last_mouse_pos = mouse_pos;
770 pending_events++;
771 xmotion = (XMotionEvent *)&event_buffer[pending_events];
772 xmotion->type = MotionNotify;
773 xmotion->x = mouse_x - AllegroDefaultScreen().x;
774 xmotion->y = mouse_y - AllegroDefaultScreen().y;
775 }
776
777 /* mouse button event */
778 if (mouse_b != last_mouse_b)
779 {
780 for (i = 0; i < 3; i++) /* check all three mouse buttons */
781 {
782 int bitmask = (1 << i);
783
784 if ((last_mouse_b & bitmask) != (mouse_b & bitmask))
785 {
786 int mapping[3] = { 1, 3, 2 };
787
788 pending_events++;
789 xbutton = (XButtonEvent *)&event_buffer[pending_events];
790 xbutton->type = (mouse_b & bitmask ? ButtonPress : ButtonRelease);
791 xbutton->button = mapping[i];
792 xbutton->x = mouse_x - AllegroDefaultScreen().x;
793 xbutton->y = mouse_y - AllegroDefaultScreen().y;
794 }
795 }
796 last_mouse_b = mouse_b;
797 }
798
799 return pending_events;
800 }
801
XLookupKeysym(XKeyEvent * key_event,int index)802 KeySym XLookupKeysym(XKeyEvent *key_event, int index)
803 {
804 return key_event->state;
805 }
806
XLookupString(XKeyEvent * key_event,char * buffer,int buffer_size,KeySym * key,XComposeStatus * compose)807 int XLookupString(XKeyEvent *key_event, char *buffer, int buffer_size,
808 KeySym *key, XComposeStatus *compose)
809 {
810 *key = key_event->state;
811 return 0;
812 }
813
XSetForeground(Display * display,GC gc,unsigned int pixel)814 void XSetForeground(Display *display, GC gc, unsigned int pixel)
815 {
816 XGCValues *gcv = (XGCValues *)gc;
817
818 gcv->foreground = pixel;
819 }
820
XDrawLine(Display * display,Drawable d,GC gc,int x1,int y1,int x2,int y2)821 void XDrawLine(Display *display, Drawable d, GC gc,
822 int x1, int y1, int x2, int y2)
823 {
824 XGCValues *gcv = (XGCValues *)gc;
825 boolean mouse_off = FALSE;
826
827 if ((BITMAP *)d == video_bitmap)
828 {
829 x1 += AllegroDefaultScreen().x;
830 y1 += AllegroDefaultScreen().y;
831 x2 += AllegroDefaultScreen().x;
832 y2 += AllegroDefaultScreen().y;
833 freeze_mouse_flag = TRUE;
834 mouse_off = hide_mouse(display, MIN(x1, x2), MIN(y1, y2),
835 MAX(x1, x2) - MIN(x1, x2),
836 MAX(y1, y2) - MIN(y1, y2));
837 }
838
839 line((BITMAP *)d, x1, y1, x2, y2, gcv->foreground);
840
841 if (mouse_off)
842 unhide_mouse(display);
843
844 freeze_mouse_flag = FALSE;
845 }
846
XDestroyImage(XImage * ximage)847 void XDestroyImage(XImage *ximage)
848 {
849 }
850
XDestroyWindow(Display * display,Window window)851 void XDestroyWindow(Display *display, Window window)
852 {
853 }
854
XQueryPointer(Display * display,Window window,Window * root,Window * child,int * root_x,int * root_y,int * win_x,int * win_y,unsigned int * mask)855 Bool XQueryPointer(Display *display, Window window,
856 Window *root, Window *child, int *root_x, int *root_y,
857 int *win_x, int *win_y, unsigned int *mask)
858 {
859 *win_x = mouse_x - AllegroDefaultScreen().x;
860 *win_y = mouse_y - AllegroDefaultScreen().y;
861
862 return True;
863 }
864
XAutoRepeatOn(Display * display)865 void XAutoRepeatOn(Display *display)
866 {
867 keyboard_auto_repeat = TRUE;
868 clear_keybuf();
869 }
870
XAutoRepeatOff(Display * display)871 void XAutoRepeatOff(Display *display)
872 {
873 keyboard_auto_repeat = FALSE;
874 }
875
AllegroDrawLine(Drawable d,int from_x,int from_y,int to_x,int to_y,Pixel color)876 void AllegroDrawLine(Drawable d, int from_x, int from_y, int to_x, int to_y,
877 Pixel color)
878 {
879 boolean mouse_off = FALSE;
880
881 if ((BITMAP *)d == video_bitmap)
882 {
883 int dx = AllegroDefaultScreen().x;
884 int dy = AllegroDefaultScreen().y;
885 int x1, y1, x2, y2;
886
887 from_x += dx;
888 from_y += dy;
889 to_x += dx;
890 to_y += dy;
891
892 x1 = (from_x < to_x ? from_x : to_x);
893 y1 = (from_y < to_y ? from_y : to_y);
894 x2 = (from_x < to_x ? to_x : from_x);
895 y2 = (from_y < to_y ? to_y : from_y);
896
897 freeze_mouse_flag = TRUE;
898 mouse_off = hide_mouse(display, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
899 }
900
901 line((BITMAP *)d, from_x, from_y, to_x, to_y, color);
902
903 if (mouse_off)
904 unhide_mouse(display);
905
906 freeze_mouse_flag = FALSE;
907 }
908
AllegroGetPixel(Drawable d,int x,int y)909 Pixel AllegroGetPixel(Drawable d, int x, int y)
910 {
911 return getpixel((BITMAP *)d, x, y);
912 }
913
AllegroZoomBitmap(Drawable src,Drawable dst,int src_width,int src_height,int dst_width,int dst_height)914 void AllegroZoomBitmap(Drawable src, Drawable dst,
915 int src_width, int src_height,
916 int dst_width, int dst_height)
917 {
918 stretch_blit((BITMAP *)src, (BITMAP *)dst,
919 0, 0, src_width, src_height, 0, 0, dst_width, dst_height);
920 }
921
MSDOSOpenAudio(void)922 void MSDOSOpenAudio(void)
923 {
924 if (allegro_init_audio())
925 {
926 audio.sound_available = TRUE;
927 audio.music_available = TRUE;
928 audio.loops_available = TRUE;
929 audio.sound_enabled = TRUE;
930
931 audio.num_channels = NUM_MIXER_CHANNELS;
932 audio.music_channel = MUSIC_CHANNEL;
933 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
934
935 Mixer_InitChannels();
936 }
937 }
938
MSDOSCloseAudio(void)939 void MSDOSCloseAudio(void)
940 {
941 /* nothing to be done here */
942 }
943
NetworkServer(int port,int serveronly)944 void NetworkServer(int port, int serveronly)
945 {
946 Error(ERR_WARN, "networking not supported in DOS version");
947 }
948
949
950 /* ========================================================================= */
951 /* joystick functions */
952 /* ========================================================================= */
953
MSDOSInitJoysticks()954 void MSDOSInitJoysticks()
955 {
956 int i;
957
958 /* start from scratch */
959 remove_joystick();
960
961 /* try to access two joysticks; if that fails, try to access just one */
962 if (install_joystick(JOY_TYPE_2PADS) == 0 ||
963 install_joystick(JOY_TYPE_AUTODETECT) == 0)
964 joystick.status = JOYSTICK_ACTIVATED;
965
966 for (i = 0; i < MAX_PLAYERS; i++)
967 {
968 char *device_name = setup.input[i].joy.device_name;
969 int joystick_nr = getJoystickNrFromDeviceName(device_name);
970
971 if (joystick_nr >= num_joysticks)
972 joystick_nr = -1;
973
974 /* misuse joystick file descriptor variable to store joystick number */
975 joystick.fd[i] = joystick_nr;
976 }
977 }
978
MSDOSReadJoystick(int nr,int * x,int * y,boolean * b1,boolean * b2)979 boolean MSDOSReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
980 {
981 /* the allegro global variable 'num_joysticks' contains the number
982 of joysticks found at initialization under MS-DOS / Windows */
983
984 if (nr < 0 || nr >= num_joysticks)
985 return FALSE;
986
987 poll_joystick();
988
989 if (x != NULL)
990 *x = joy[nr].stick[0].axis[0].pos;
991 if (y != NULL)
992 *y = joy[nr].stick[0].axis[1].pos;
993
994 if (b1 != NULL)
995 *b1 = joy[nr].button[0].b;
996 if (b2 != NULL)
997 *b2 = joy[nr].button[1].b;
998
999 return TRUE;
1000 }
1001
1002 #endif /* PLATFORM_MSDOS */
1003