1 /* term_x11.c: X-windows terminal code (screen update and keyboard)
2
3 Copyright (c) 1997-2003, Tarik Isani (xhomer@isani.org)
4
5 This file is part of Xhomer.
6
7 Xhomer is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2
9 as published by the Free Software Foundation.
10
11 Xhomer is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Xhomer; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21
22 /* TBD:
23 -alloc only 2 colors for non-ebo 8-bit
24 -use better technique to detect CLUT modes
25 -add DGA mode that only writes each pixel once
26 -colormap is not loaded for DGA+PCM
27 -get screensaver blanking to work during DGA switch
28
29 Xserver DGA2 bugs:
30
31 Currently, standard X event handling is used, as the DGA stuff is broken
32 in DGA2
33
34 XFree 4.0.2 Neomagic
35 -Use of more than 4MB of graphics memory causes crash during modeswitch
36 -Menu does not work if more than X MB of graphics memory is used
37 -XDGA events are not being seen (see #ifdef DGAXXX)
38 -XDGAFlipImmediate is not supported. So, xhomer will wait until the
39 viewport update has been completed, causing slower scrolling with
40 this server. Servers that support XDGAFlipImmediate are not
41 affected.
42
43 XFree 4.0.2 I128
44 -XDGASetMode(..., ..., 0) does *not* return to initial screen mode
45 -grabbing keyboard and mouse does not work, unless sleep(1) first
46 -framebuffer height is incorrectly reported as that of single a screen
47 -XDGA events are not being seen (see #ifdef DGAXXX)
48 -Expose events are not sent in DGA mode
49 -EnterNotify is sent, instead, *most* of the time
50 -look for "pro_nine_workaround"
51 */
52
53 #ifdef PRO
54
55 #include <X11/Xlib.h>
56 #include <X11/Xutil.h>
57 #include <X11/keysym.h>
58 #ifdef SHM
59 #include <X11/extensions/XShm.h>
60 #include <sys/ipc.h>
61 #include <sys/shm.h>
62 #endif
63 #ifdef DGA
64 #include <X11/extensions/xf86dga.h>
65 #ifndef DGA2
66 #include <X11/extensions/xf86vmode.h>
67 #endif
68 #include <unistd.h>
69 #endif
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <string.h>
73 #include <signal.h>
74 #include <math.h>
75
76 #include "pro_defs.h"
77 #include "pro_lk201.h"
78
79
80 #define PRO_KEYBOARD_FIFO_DEPTH 1024
81
82 int pro_nine_workaround = 0; /* workaround for #9 Xserver bugs */
83 int pro_libc_workaround = 0; /* workaround for pre-glibc-2.0 bug */
84 int pro_window_x = 0; /* window x position */
85 int pro_window_y = 0; /* window y position */
86 int pro_screen_full = 0; /* 0 = window, 1 = full-screen */
87 int pro_screen_window_scale = 2; /* vertical window scale factor */
88 int pro_screen_full_scale = 3; /* vertical DGA scale factor */
89 int pro_screen_gamma = 10; /* 10x gamma correction factor */
90 int pro_screen_pcm = 1; /* 0 = don't use PCM, 1 = use PCM (private color map) */
91 int pro_screen_framebuffers = 0; /* number of DGA framebuffers (1..3 or 0 to auto-detect) */
92
93 LOCAL int pro_screen_open = 0;
94 LOCAL int pro_screen_winheight; /* height of framebuffer */
95 LOCAL int pro_screen_bufheight; /* height of allocated framebuffer */
96 LOCAL int pro_screen_updateheight; /* height to update */
97
98 LOCAL int pro_keyboard_fifo_h; /* FIFO head pointer */
99 LOCAL int pro_keyboard_fifo_t; /* FIFO tail pointer */
100 LOCAL int pro_keyboard_fifo[PRO_KEYBOARD_FIFO_DEPTH];
101
102 int pro_mouse_x = 0; /* mouse x */
103 int pro_mouse_y = 0; /* mouse y */
104 int pro_mouse_l = 0; /* left mouse button */
105 int pro_mouse_m = 0; /* middle mouse button */
106 int pro_mouse_r = 0; /* right mouse button */
107 int pro_mouse_in = 0; /* mouse in window */
108
109 LOCAL Display *ProDisplay; /* pointer to the display */
110 LOCAL int ProScreen;
111 LOCAL Window ProWindow; /* window structure */
112 LOCAL GC ProGC;
113 LOCAL Colormap ProColormap;
114 LOCAL XColor ProColor_map[8];
115 LOCAL XColor ProColor_nonmap[8];
116 LOCAL int ProDepth; /* color depth */
117
118 const long ProEventMask = ExposureMask | KeyPressMask
119 | KeyReleaseMask | PointerMotionMask
120 | ButtonPressMask | ButtonReleaseMask
121 | EnterWindowMask | LeaveWindowMask;
122
123 LOCAL unsigned long ProWhitePixel;
124 LOCAL unsigned long ProBlackPixel;
125
126 #ifdef DGA
127 #ifdef DGA2
128 LOCAL int pro_vid_dga_eventbase;
129 LOCAL int pro_vid_dga_errorbase;
130 #else
131 LOCAL XF86VidModeModeInfo pro_modeline;
132 #endif
133 LOCAL char *pro_vid_dga_addr;
134 LOCAL int pro_vid_dga_width;
135 LOCAL int pro_vid_dga_height;
136 #ifndef DGA2
137 LOCAL int pro_vid_dga_banksize;
138 #endif
139 LOCAL int pro_vid_dga_memsize;
140 LOCAL Cursor ProBlankCursor;
141 LOCAL XColor ProBlackColor;
142 LOCAL int pro_old_scroll; /* used to determine when to scroll */
143 LOCAL int pro_menu_scroll; /* scroll position when menu is first turned on in DGA mode */
144 LOCAL int pro_old_overlay_on; /* used to determine when overlay has been turned off */
145 LOCAL int pro_mouse_y_screen = 0;
146 #endif
147
148 LOCAL XImage *pro_image;
149
150 LOCAL XKeyboardControl pro_keyboard_control;
151 LOCAL XKeyboardState pro_keyboard_state; /* state to be restored on exit */
152 LOCAL unsigned char pro_keyboard_keys[32]; /* key vector */
153
154 LOCAL unsigned char *pro_image_data;
155 LOCAL int pro_image_stride;
156
157 LOCAL int pro_screen_clutmode; /* indicates whether window is in CLUT mode */
158 LOCAL int pro_screen_pixsize; /* bytes per pixel */
159 LOCAL int pro_screen_pixsize_act; /* active bytes per pixel */
160 LOCAL int pro_screen_clsize; /* screen cache line size in bytes */
161 LOCAL int pro_screen_blank = 0; /* indicates whether screen is blanked */
162
163 LOCAL int pro_mask_r; /* mask for red bits */
164 LOCAL int pro_mask_g; /* mask for green bits */
165 LOCAL int pro_mask_b; /* mask for blue bits */
166 LOCAL int pro_nonmap[8]; /* EBO non-mapped colors */
167 LOCAL int pro_colormap[8]; /* 8-entry colormap for EBO */
168 LOCAL int *pro_lut; /* points to nonmap or colormap */
169
170 #ifdef SHM
171 LOCAL int shm_present = 1; /* indicates whether XShm may be used */
172
173 LOCAL XShmSegmentInfo shminfo;
174
175 LOCAL int (*OldXErrorHandler)(Display*, XErrorEvent*);
176
XShmErrorHandler(Display * dpy,XErrorEvent * xev)177 LOCAL int XShmErrorHandler(Display *dpy, XErrorEvent *xev)
178 {
179 char error[256];
180
181 XGetErrorText(dpy, xev->error_code, error, 255); error[255] = '\0';
182 fprintf(stderr, "warning: can't use Shm - %s\r\n", error);
183 shm_present = 0;
184 return 0;
185 }
186 #endif
187
188 LOCAL char* current_title = NULL;
189 LOCAL int title_needs_update = 0;
190
191
192 /* Put a title on the display window */
193
pro_screen_title(char * title)194 void pro_screen_title (char *title)
195 {
196 if (current_title)
197 free(current_title);
198
199 current_title = strdup(title);
200 title_needs_update = 1;
201 }
202
203
pro_screen_clear()204 void pro_screen_clear ()
205 {
206 int i, j, k;
207 unsigned char *mptr;
208
209
210 /* Clear image buffer */
211
212 mptr = pro_image_data;
213
214 for(i=0; i<pro_screen_bufheight;
215 i++, mptr += pro_image_stride*pro_screen_pixsize)
216 for(j=0; j<PRO_VID_SCRWIDTH; j++)
217 for(k=0; k<pro_screen_pixsize; k++)
218 *mptr++ = ProBlackPixel >> (8*k);
219 }
220
221
222 /* Save and restore keyboard control settings */
223
pro_screen_save_old_keyboard()224 void pro_screen_save_old_keyboard ()
225 {
226 XGetKeyboardControl(ProDisplay, &pro_keyboard_state);
227 }
228
229
pro_screen_restore_old_keyboard()230 void pro_screen_restore_old_keyboard ()
231 {
232 XKeyboardControl key_control;
233
234
235 key_control.bell_pitch = (int)pro_keyboard_state.bell_pitch;
236 key_control.bell_duration = (int)pro_keyboard_state.bell_duration;
237 key_control.bell_percent = pro_keyboard_state.bell_percent;
238 key_control.key_click_percent = pro_keyboard_state.key_click_percent;
239 key_control.auto_repeat_mode = pro_keyboard_state.global_auto_repeat;
240
241 XChangeKeyboardControl(ProDisplay, KBAutoRepeatMode | KBKeyClickPercent
242 | KBBellPitch | KBBellDuration | KBBellPercent,
243 &key_control);
244 }
245
246
pro_screen_restore_keyboard()247 void pro_screen_restore_keyboard ()
248 {
249 if (pro_mouse_in == 1)
250 XChangeKeyboardControl(ProDisplay, KBAutoRepeatMode | KBKeyClickPercent
251 | KBBellPitch | KBBellDuration | KBBellPercent,
252 &pro_keyboard_control);
253 }
254
255
256 /* Keycode lookup routine (key press) */
257
pro_keyboard_lookup_down(int xkey)258 LOCAL int pro_keyboard_lookup_down (int xkey)
259 {
260 switch (xkey)
261 {
262 case XK_Escape: return PRO_LK201_HOLD;
263 case XK_F1: return PRO_LK201_PRINT;
264 case XK_F2: return PRO_LK201_SETUP;
265 case XK_F3: return PRO_LK201_FFOUR;
266 case XK_F4: return PRO_LK201_BREAK;
267 case XK_F5: return PRO_LK201_INT;
268 case XK_F6: return PRO_LK201_RESUME;
269 case XK_F7: return PRO_LK201_CANCEL;
270 case XK_F8: return PRO_LK201_MAIN;
271 case XK_F9: return PRO_LK201_EXIT;
272 case XK_F10: return PRO_LK201_ESC;
273 case XK_F11: return PRO_LK201_BS;
274 case XK_F12: return PRO_LK201_LF;
275 case XK_Num_Lock: /* XXX temp., since Sys_Req is broken! */
276 #ifndef XK_Sys_Req
277 #define XK_Sys_Req 0xFF15
278 #endif
279 case XK_Sys_Req: return PRO_LK201_ADDOP; /* XXX seems broken */
280 case XK_Multi_key: return PRO_LK201_HELP; /* XXX check this! */
281 case XK_Pause: return PRO_LK201_DO;
282
283 case XK_a: return PRO_LK201_A;
284 case XK_b: return PRO_LK201_B;
285 case XK_c: return PRO_LK201_C;
286 case XK_d: return PRO_LK201_D;
287 case XK_e: return PRO_LK201_E;
288 case XK_f: return PRO_LK201_F;
289 case XK_g: return PRO_LK201_G;
290 case XK_h: return PRO_LK201_H;
291 case XK_i: return PRO_LK201_I;
292 case XK_j: return PRO_LK201_J;
293 case XK_k: return PRO_LK201_K;
294 case XK_l: return PRO_LK201_L;
295 case XK_m: return PRO_LK201_M;
296 case XK_n: return PRO_LK201_N;
297 case XK_o: return PRO_LK201_O;
298 case XK_p: return PRO_LK201_P;
299 case XK_q: return PRO_LK201_Q;
300 case XK_r: return PRO_LK201_R;
301 case XK_s: return PRO_LK201_S;
302 case XK_t: return PRO_LK201_T;
303 case XK_u: return PRO_LK201_U;
304 case XK_v: return PRO_LK201_V;
305 case XK_w: return PRO_LK201_W;
306 case XK_x: return PRO_LK201_X;
307 case XK_y: return PRO_LK201_Y;
308 case XK_z: return PRO_LK201_Z;
309
310 case XK_0: return PRO_LK201_0;
311 case XK_1: return PRO_LK201_1;
312 case XK_2: return PRO_LK201_2;
313 case XK_3: return PRO_LK201_3;
314 case XK_4: return PRO_LK201_4;
315 case XK_5: return PRO_LK201_5;
316 case XK_6: return PRO_LK201_6;
317 case XK_7: return PRO_LK201_7;
318 case XK_8: return PRO_LK201_8;
319 case XK_9: return PRO_LK201_9;
320
321 case XK_minus: return PRO_LK201_MINUS;
322 case XK_equal: return PRO_LK201_EQUAL;
323 case XK_bracketleft: return PRO_LK201_LEFTB;
324 case XK_bracketright: return PRO_LK201_RIGHTB;
325
326 case XK_semicolon: return PRO_LK201_SEMI;
327 case XK_quoteright: return PRO_LK201_QUOTE;
328 case XK_backslash: return PRO_LK201_BACKSL;
329 case XK_comma: return PRO_LK201_COMMA;
330 case XK_period: return PRO_LK201_PERIOD;
331 case XK_slash: return PRO_LK201_SLASH;
332 case XK_quoteleft: return PRO_LK201_TICK;
333
334 case XK_space: return PRO_LK201_SPACE;
335
336 case XK_BackSpace: return PRO_LK201_DEL;
337 case XK_Return: return PRO_LK201_RETURN;
338 case XK_Tab: return PRO_LK201_TAB;
339
340 case XK_Up: return PRO_LK201_UP;
341 case XK_Down: return PRO_LK201_DOWN;
342 case XK_Left: return PRO_LK201_LEFT;
343 case XK_Right: return PRO_LK201_RIGHT;
344
345 case XK_Find: return PRO_LK201_FIND;
346 case XK_Home: return PRO_LK201_INSERT;
347 case XK_Prior: return PRO_LK201_REMOVE;
348 case XK_Delete: return PRO_LK201_SELECT;
349 case XK_End: return PRO_LK201_PREV;
350 case XK_Next: return PRO_LK201_NEXT;
351
352 case XK_Caps_Lock: return PRO_LK201_LOCK;
353 case XK_Shift_L: return PRO_LK201_SHIFT;
354 case XK_Shift_R: return PRO_LK201_SHIFT;
355 case XK_Control_L: return PRO_LK201_CTRL;
356 case XK_Control_R: return PRO_LK201_CTRL;
357 case XK_Alt_L: return PRO_LK201_COMPOSE;
358
359 default: return PRO_NOCHAR;
360 }
361 }
362
363
364 /* Keycode lookup routine (key release) */
365
pro_keyboard_lookup_up(int xkey)366 LOCAL int pro_keyboard_lookup_up (int xkey)
367 {
368 switch (xkey)
369 {
370 case XK_Shift_L: return PRO_LK201_ALLUPS;
371 case XK_Shift_R: return PRO_LK201_ALLUPS;
372 case XK_Control_L: return PRO_LK201_ALLUPS;
373 case XK_Control_R: return PRO_LK201_ALLUPS;
374
375 default: return PRO_NOCHAR;
376 }
377 }
378
379
380 /* Put character in keycode FIFO */
381
pro_keyboard_fifo_put(int key)382 LOCAL void pro_keyboard_fifo_put (int key)
383 {
384 /* Filter keycodes for commands */
385
386 /* This is to avoid changing the menu state while screen is closed */
387
388 if (pro_screen_open)
389 key = pro_menu(key);
390
391 if (key != PRO_NOCHAR)
392 {
393 /* First check if FIFO is full */
394
395 if ((pro_keyboard_fifo_h != (pro_keyboard_fifo_t-1))
396 && ((pro_keyboard_fifo_h != (PRO_KEYBOARD_FIFO_DEPTH-1))
397 || (pro_keyboard_fifo_t != 0)))
398 {
399 pro_keyboard_fifo[pro_keyboard_fifo_h] = key;
400 pro_keyboard_fifo_h++;
401 if (pro_keyboard_fifo_h == PRO_KEYBOARD_FIFO_DEPTH)
402 pro_keyboard_fifo_h = 0;
403 }
404 }
405 }
406
407
408 /* External keyboard polling routine */
409
pro_keyboard_get()410 int pro_keyboard_get ()
411 {
412 int key;
413
414
415 /* Get character from keycode FIFO */
416
417 /* Check if FIFO is empty */
418
419 if (pro_keyboard_fifo_h == pro_keyboard_fifo_t)
420 key = PRO_NOCHAR;
421 else
422 {
423 key = pro_keyboard_fifo[pro_keyboard_fifo_t];
424 pro_keyboard_fifo_t++;
425 if (pro_keyboard_fifo_t == PRO_KEYBOARD_FIFO_DEPTH)
426 pro_keyboard_fifo_t = 0;
427 }
428
429 return key;
430 }
431
432
433 /* Save keymap */
434
pro_screen_save_keys()435 void pro_screen_save_keys ()
436 {
437 int i;
438 unsigned char keys[32];
439
440
441 XQueryKeymap(ProDisplay, keys);
442
443 for(i=0; i<32; i++)
444 pro_keyboard_keys[i] = keys[i];
445 }
446
447
448 /* Bring emulator state up to date with shift/ctrl key state that may have changed
449 while focus was lost */
450
pro_screen_update_keys()451 void pro_screen_update_keys ()
452 {
453 int i, key, oldkey, curkey;
454 unsigned char keys[32];
455
456
457 XQueryKeymap(ProDisplay, keys);
458
459 for(i=0; i<32*8; i++)
460 {
461 oldkey = pro_keyboard_keys[i/8]&(1<<(i%8));
462 curkey = keys[i/8]&(1<<(i%8));
463
464 if (oldkey != curkey)
465 {
466 key = XKeycodeToKeysym(ProDisplay, i, 0);
467
468 if (curkey == 0)
469 key = pro_keyboard_lookup_up(key);
470 else
471 key = pro_keyboard_lookup_down(key);
472
473 if ((key == PRO_LK201_SHIFT) || (key == PRO_LK201_CTRL)
474 || (key == PRO_LK201_ALLUPS))
475 pro_keyboard_fifo_put(key);
476 }
477 }
478 }
479
480
481 /* Initialize the display */
482
pro_screen_init()483 int pro_screen_init ()
484 {
485 XSetWindowAttributes ProWindowAttributes; /* structure of window attibutes */
486 unsigned long ProWindowMask; /* mask for window attributes */
487 XSizeHints ProSizeHints; /* window hints for window manger */
488 int x, y; /* window position */
489 int border_width = 0; /* border width of the window */
490
491 XGCValues ProGCValues;
492
493 int i, index;
494
495 unsigned long planeret[8];
496 unsigned long pixret[8];
497
498 XEvent event;
499 Window focus_window;
500 int revert_to;
501 #ifdef DGA
502 int old_uid = geteuid();
503 #endif
504
505
506 if (pro_screen_open == 0)
507 {
508 #ifndef DGA
509 if (pro_screen_full)
510 {
511 printf("Emulator not compiled with DGA support!\r\n");
512 return PRO_FAIL;
513 }
514 #endif
515
516 /* Set window coordinates */
517
518 x = pro_window_x;
519 y = pro_window_y;
520
521 ProDisplay = XOpenDisplay ("");
522 if (ProDisplay == NULL)
523 {
524 fprintf (stderr,
525 "ERROR: Could not open a connection to X on display %s\r\n",
526 XDisplayName (NULL));
527 return PRO_FAIL;
528 }
529
530 ProScreen = DefaultScreen (ProDisplay);
531
532 ProDepth = DefaultDepth (ProDisplay, ProScreen);
533
534 ProWhitePixel = WhitePixel(ProDisplay, ProScreen);
535 ProBlackPixel = BlackPixel(ProDisplay, ProScreen);
536
537 ProWindowAttributes.border_pixel = BlackPixel (ProDisplay, ProScreen);
538 ProWindowAttributes.background_pixel = BlackPixel (ProDisplay, ProScreen);
539 ProWindowAttributes.override_redirect = False;
540 ProWindowAttributes.event_mask = ProEventMask;
541
542 ProWindowMask = CWEventMask | CWBackPixel | CWBorderPixel;
543
544 #ifdef DGA
545 if (pro_screen_full)
546 {
547 int modecount;
548 #ifdef DGA2
549 XDGADevice *dgadevice;
550 XDGAMode *dgamode;
551 #else
552 int clk;
553 XF86VidModeModeLine ml;
554 XF86VidModeModeInfo **modesinfo;
555 #endif
556
557 if (seteuid(0) != 0)
558 {
559 printf("DGA error: emulator must be run as root or setuid root\r\n");
560 return PRO_FAIL;
561 }
562
563 #ifdef DGA2
564 XDGAOpenFramebuffer(ProDisplay, ProScreen);
565 dgamode = XDGAQueryModes(ProDisplay, ProScreen, &modecount);
566
567 for(i=0; i<modecount; i++)
568 if ((dgamode[i].viewportWidth == PRO_VID_SCRWIDTH)
569 && (dgamode[i].viewportHeight == pro_screen_full_scale*PRO_VID_SCRHEIGHT))
570 break;
571 XFree(dgamode);
572
573 if (i == modecount)
574 {
575 printf("DGA2 Error - unable to find correct screen mode\r\n");
576 printf("%d x %d viewport required\r\n", PRO_VID_SCRWIDTH, pro_screen_full_scale*PRO_VID_SCRHEIGHT);
577 seteuid(old_uid);
578 return PRO_FAIL;
579 }
580
581 dgadevice = XDGASetMode(ProDisplay, ProScreen, i+1);
582
583 pro_vid_dga_addr = dgadevice -> data;
584 pro_vid_dga_width = (dgadevice -> mode).imageWidth;
585 pro_vid_dga_height = (dgadevice -> mode).imageHeight;
586
587 if (pro_nine_workaround)
588 {
589 /* This is a workaround for a #9 DGA2 bug that reports
590 framebuffer height incorrectly as that of a single screen */
591
592 if (pro_vid_dga_height <= 1024)
593 pro_vid_dga_height = 2304;
594 }
595
596 pro_vid_dga_memsize = pro_vid_dga_height * (dgadevice -> mode).bytesPerScanline / 1024;
597 XFree(dgadevice);
598
599 #ifdef DGAXXX
600 /* XXX Does not seem to pass DGA events ??? Use XEvents for now... */
601
602 XDGASelectInput(ProDisplay, ProScreen, ProEventMask);
603 #endif
604 XDGAQueryExtension(ProDisplay, &pro_vid_dga_eventbase, &pro_vid_dga_errorbase);
605
606 #else /* DGA1 */
607
608 /* Get current screen mode */
609
610 XF86VidModeGetModeLine(ProDisplay, ProScreen, &clk, &ml);
611 if (ml.privsize != 0)
612 XFree(ml.private);
613
614 /* Attempt to find appropriate screen mode */
615
616 XF86VidModeGetAllModeLines(ProDisplay, ProScreen, &modecount, &modesinfo);
617
618 for(i=0; i<modecount; i++)
619 if ((modesinfo[i]->hdisplay == PRO_VID_SCRWIDTH)
620 && (modesinfo[i]->vdisplay == pro_screen_full_scale*PRO_VID_SCRHEIGHT))
621 break;
622
623 if (i == modecount)
624 {
625 printf("DGA1 Error - unable to find correct screen mode\r\n");
626 printf("%d x %d viewport required\r\n", PRO_VID_SCRWIDTH, pro_screen_full_scale*PRO_VID_SCRHEIGHT);
627 seteuid(old_uid);
628 return PRO_FAIL;
629 }
630
631 /* Save current screen mode */
632
633 memset(&pro_modeline, 0, sizeof(pro_modeline));
634
635 pro_modeline.dotclock = clk;
636 pro_modeline.hdisplay = ml.hdisplay;
637 pro_modeline.hsyncstart = ml.hsyncstart;
638 pro_modeline.hsyncend = ml.hsyncend;
639 pro_modeline.htotal = ml.htotal;
640 pro_modeline.vdisplay = ml.vdisplay;
641 pro_modeline.vsyncstart = ml.vsyncstart;
642 pro_modeline.vsyncend = ml.vsyncend;
643 pro_modeline.vtotal = ml.vtotal;
644 pro_modeline.flags = ml.flags;
645
646 /* XXX Blank screen here */
647
648 /* Switch screen mode */
649
650 XF86VidModeSwitchToMode(ProDisplay, ProScreen, modesinfo[i]);
651
652 /* XXX is this correct? */
653
654 for(i=0; i<modecount; i++)
655 if (modesinfo[i]->privsize != 0)
656 XFree(modesinfo[i]->private);
657
658 XFree(modesinfo); /* XXX correct? */
659
660 /* Get frame buffer parameters */
661
662 XF86DGAGetVideo(ProDisplay, ProScreen,
663 &pro_vid_dga_addr,
664 &pro_vid_dga_width,
665 &pro_vid_dga_banksize,
666 &pro_vid_dga_memsize);
667
668 /* Enter DGA mode */
669
670 XF86DGADirectVideo(ProDisplay, ProScreen,
671 XF86DGADirectGraphics
672 | XF86DGADirectMouse
673 | XF86DGADirectKeyb);
674 #endif
675
676 seteuid(old_uid);
677
678 x = 0;
679 y = 0;
680 }
681 #endif
682
683 /* Determine pixel depth */
684 /* XXX
685 printf("%d bpp\r\n", ProDepth);
686 */
687
688 /* XXX use better technique to detect CLUT modes */
689
690 switch(ProDepth)
691 {
692 case 8:
693 pro_screen_clutmode = 1;
694 pro_screen_pixsize = 1;
695 pro_screen_pixsize_act = 1;
696 break;
697
698 case 12:
699 pro_screen_clutmode = 1;
700 pro_screen_pixsize = 2;
701 pro_screen_pixsize_act = 2;
702 break;
703
704 case 15:
705 case 16:
706 pro_screen_clutmode = 0;
707 pro_screen_pixsize = 2;
708 pro_screen_pixsize_act = 2;
709 break;
710
711 case 24:
712 pro_screen_clutmode = 0;
713 pro_screen_pixsize = 4;
714 pro_screen_pixsize_act = 3;
715 break;
716
717 default:
718 printf("Unsupported pixel depth\r\n");
719 return PRO_FAIL;
720 }
721
722 #ifdef DGA
723 if (pro_screen_full)
724 {
725 /* Check if number of framebuffers should be auto-detected */
726
727 if (pro_screen_framebuffers == 0)
728 {
729 pro_screen_framebuffers = (pro_vid_dga_memsize*1024) /
730 (pro_vid_dga_width*pro_screen_pixsize*pro_screen_full_scale*PRO_VID_MEMHEIGHT);
731
732 if (pro_screen_framebuffers > 3)
733 pro_screen_framebuffers = 3;
734
735 if (pro_screen_framebuffers < 1)
736 pro_screen_framebuffers = 1;
737
738 printf("Auto-detected %d framebuffer", pro_screen_framebuffers);
739 if (pro_screen_framebuffers > 1)
740 printf("s");
741 printf("\r\n");
742 }
743
744 pro_screen_bufheight = pro_screen_framebuffers*pro_screen_full_scale*PRO_VID_MEMHEIGHT;
745 pro_screen_winheight = pro_screen_bufheight;
746 pro_screen_updateheight = PRO_VID_MEMHEIGHT;
747 }
748 else
749 #endif
750 {
751 pro_screen_bufheight = PRO_VID_SCRHEIGHT;
752 pro_screen_winheight = pro_screen_window_scale*pro_screen_bufheight;
753 pro_screen_updateheight = PRO_VID_SCRHEIGHT;
754 }
755
756
757 ProWindow = XCreateWindow (ProDisplay,
758 RootWindow (ProDisplay, ProScreen),
759 x, y, PRO_VID_SCRWIDTH, pro_screen_winheight, border_width,
760 ProDepth, InputOutput, CopyFromParent,
761 ProWindowMask, &ProWindowAttributes);
762
763 ProSizeHints.flags = PSize | PMinSize | PMaxSize;
764
765 if ((x != 0) && (y != 0))
766 {
767 ProSizeHints.flags |= PPosition;
768 ProSizeHints.x = x;
769 ProSizeHints.y = y;
770 }
771
772 ProSizeHints.width = ProSizeHints.min_width = ProSizeHints.max_width
773 = PRO_VID_SCRWIDTH;
774 ProSizeHints.height = ProSizeHints.min_height = ProSizeHints.max_height
775 = pro_screen_winheight;
776
777 XSetNormalHints (ProDisplay, ProWindow, &ProSizeHints);
778
779 ProGC = XCreateGC (ProDisplay,
780 ProWindow,
781 (unsigned long) 0,
782 &ProGCValues);
783
784 /* error... cannot create gc */
785 if (ProGC == 0)
786 {
787 XDestroyWindow(ProDisplay, ProScreen);
788 return PRO_FAIL;
789 }
790
791 XSetForeground (ProDisplay, ProGC, ProBlackPixel);
792 XSetBackground (ProDisplay, ProGC, ProWhitePixel);
793
794
795 XMapWindow (ProDisplay, ProWindow);
796
797 /* Wait for window to become visible */
798 /* XXX #9 server sometimes hangs here with no events */
799
800 #ifdef DGA
801 #ifdef DGA2
802 /* XXX Major #9 hack to account for missing Expose/EnterNotify
803 events in DGA mode */
804
805 if (!pro_screen_full || !pro_nine_workaround)
806 #endif
807 #endif
808 do
809 XNextEvent(ProDisplay, &event);
810 while ((event.type != Expose) && (event.type != EnterNotify));
811
812 /* Determine whether window has input focus */
813
814 #ifdef DGA
815 if (pro_screen_full)
816 pro_mouse_in = 1;
817 else
818 #endif
819 {
820 XGetInputFocus (ProDisplay, &focus_window, &revert_to);
821
822 if (focus_window == ProWindow)
823 pro_mouse_in = 1;
824 else
825 pro_mouse_in = 0;
826 }
827
828 pro_screen_title("Pro 350");
829
830 pro_screen_clsize = PRO_VID_CLS_PIX * pro_screen_pixsize;
831
832 if ((pro_screen_pcm == 1) && (pro_screen_clutmode == 1))
833
834 /* Allocate private colormap */
835
836 ProColormap = XCreateColormap(ProDisplay,
837 ProWindow,
838 DefaultVisual(ProDisplay, DefaultScreen(ProDisplay)),
839 AllocNone);
840 else
841 /* Use default colormap */
842
843 ProColormap = DefaultColormap(ProDisplay, ProScreen);
844
845 /* Allocate colors */
846
847 /* XXX also, alloc only 2 colors if non-ebo */
848
849 if (pro_screen_clutmode == 1)
850 XAllocColorCells(ProDisplay, ProColormap, True, planeret, 0, pixret, 8);
851
852 for(i=0; i<8; i++)
853 {
854 if (pro_screen_clutmode == 1)
855 {
856 index = pixret[i];
857 ProColor_nonmap[i].pixel = index;
858 ProColor_map[i].pixel = index;
859
860 /* Determine whether PRO is in colormapped mode */
861
862 if ((pro_vid_csr & PRO_VID_CME) != 0)
863 XStoreColor(ProDisplay, ProColormap, &ProColor_map[i]);
864 else
865 XStoreColor(ProDisplay, ProColormap, &ProColor_nonmap[i]);
866
867 pro_colormap[i] = index;
868 pro_nonmap[i] = index;
869 }
870 else
871 {
872 XAllocColor(ProDisplay, ProColormap, &ProColor_nonmap[i]);
873 pro_nonmap[i] = ProColor_nonmap[i].pixel;
874
875 XAllocColor(ProDisplay, ProColormap, &ProColor_map[i]);
876 pro_colormap[i] = ProColor_map[i].pixel;
877 }
878 }
879
880
881 /* Assign RGB mask values (for overlay blending) */
882
883 if (pro_screen_clutmode == 1)
884 {
885 pro_mask_r = ~0;
886 pro_mask_g = 0;
887 pro_mask_b = 0;
888 }
889 else
890 {
891 pro_mask_r = pro_nonmap[1];
892 pro_mask_g = pro_nonmap[2];
893 pro_mask_b = pro_nonmap[4];
894 }
895
896 XSetWindowColormap(ProDisplay, ProWindow, ProColormap);
897
898 #if !PRO_EBO_PRESENT
899 pro_nonmap[1] = pro_nonmap[7]; /* XXX change this to 1 */
900 #endif
901
902 /* Create image buffer for screen updates */
903 #ifdef DGA
904 if (pro_screen_full)
905 {
906 pro_image_data = pro_vid_dga_addr;
907 pro_image_stride = pro_vid_dga_width - PRO_VID_SCRWIDTH;
908 }
909 else
910 #endif
911 {
912 pro_image_stride = 0;
913 #ifdef SHM
914 if (XShmQueryExtension(ProDisplay))
915 {
916 /* Use shared memory */
917
918 OldXErrorHandler = XSetErrorHandler(XShmErrorHandler);
919
920 memset(&shminfo, 0, sizeof(shminfo));
921 if (!(pro_image = XShmCreateImage(ProDisplay,
922 DefaultVisual(ProDisplay, DefaultScreen(ProDisplay)),
923 ProDepth,
924 ZPixmap,
925 NULL,
926 &shminfo,
927 PRO_VID_SCRWIDTH, PRO_VID_SCRHEIGHT)))
928 shm_present = 0;
929 else if ((shminfo.shmid =
930 shmget(IPC_PRIVATE, pro_image->bytes_per_line*PRO_VID_SCRHEIGHT, IPC_CREAT|0777))==-1)
931 shm_present = 0;
932 else if ((shminfo.shmaddr = pro_image->data = shmat(shminfo.shmid, 0, 0))==(char*)-1)
933 shm_present = 0;
934 else
935 {
936 if (XShmAttach(ProDisplay, &shminfo)==0) shm_present = 0;
937 XSync(ProDisplay, True);
938 shmctl(shminfo.shmid, IPC_RMID, 0);
939
940 if (!shm_present) shmdt(shminfo.shmaddr);
941 }
942 if (pro_image && !shm_present) XDestroyImage(pro_image);
943 XSync(ProDisplay, True);
944 XSetErrorHandler(OldXErrorHandler);
945 }
946 else shm_present = 0;
947
948 if (shm_present != 0)
949 pro_image_data = pro_image->data;
950 else
951 #endif /* SHM */
952 {
953 /* Use non-shared memory */
954
955 pro_image_data = (unsigned char *)malloc(PRO_VID_SCRWIDTH*PRO_VID_SCRHEIGHT*pro_screen_pixsize);
956
957 pro_image = XCreateImage(ProDisplay,
958 DefaultVisual(ProDisplay, DefaultScreen(ProDisplay)),
959 ProDepth,
960 ZPixmap,
961 0,
962 (char*) pro_image_data,
963 PRO_VID_SCRWIDTH, PRO_VID_SCRHEIGHT,
964 pro_screen_pixsize*8,
965 PRO_VID_CLS_PIX*pro_screen_pixsize);
966 }
967 }
968
969 /* Save old keyboard state */
970
971 pro_screen_save_old_keyboard ();
972
973 /* Restore emulator keyboard state */
974
975 pro_screen_restore_keyboard();
976
977 XFlush (ProDisplay);
978
979 /* Make emulator state consistent with keyboard state */
980
981 pro_screen_update_keys();
982
983
984 /* Initialize the overlay frame buffer */
985
986 pro_overlay_init(pro_screen_pixsize, pro_screen_clutmode,
987 (int)ProBlackPixel, (int)ProWhitePixel);
988
989 pro_screen_open = 1;
990
991 #ifdef DGA
992 if (pro_screen_full)
993 {
994 /* Check if enough video memory */
995
996 if (pro_screen_winheight*pro_vid_dga_width*pro_screen_pixsize
997 > pro_vid_dga_memsize*1024)
998 {
999 printf("DGA error: not enough video memory! (%d required, only %d present)\r\n",
1000 pro_screen_winheight*pro_vid_dga_width*pro_screen_pixsize,
1001 pro_vid_dga_memsize*1024);
1002 return PRO_FAIL;
1003 }
1004
1005 #ifdef DGA2
1006 XDGASetViewport(ProDisplay, ProScreen, 0, 0, XDGAFlipImmediate);
1007 #else
1008 XF86DGASetViewPort(ProDisplay, ProScreen, 0, 0);
1009 #endif
1010
1011 /* Turn off X cursor */
1012
1013 ProBlackColor.red = 0;
1014 ProBlackColor.green = 0;
1015 ProBlackColor.blue = 0;
1016
1017 ProBlankCursor = XCreatePixmapCursor(ProDisplay,
1018 XCreatePixmap(ProDisplay, ProWindow, 1, 1, 1),
1019 XCreatePixmap(ProDisplay, ProWindow, 1, 1, 1),
1020 &ProBlackColor, &ProBlackColor, 0 ,0);
1021
1022 XDefineCursor(ProDisplay, ProWindow, ProBlankCursor);
1023
1024 #ifdef DGA2
1025 if (pro_screen_full)
1026 XDGASync(ProDisplay, ProScreen); /* XXX not sure if needed */
1027
1028 /* XXX Keyboard grabbing sometimes fails without this
1029 on #9 server */
1030
1031 if (pro_nine_workaround)
1032 sleep(1);
1033 #endif
1034 /* Grab Keyboard */
1035
1036 if (XGrabKeyboard(ProDisplay, ProWindow, True, GrabModeAsync,
1037 GrabModeAsync, CurrentTime) != GrabSuccess)
1038 {
1039 printf("DGA error: unable to grab keyboard\r\n");
1040 return PRO_FAIL;
1041 }
1042
1043 /* Grab Mouse */
1044
1045 if (XGrabPointer(ProDisplay, ProWindow, True,
1046 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
1047 GrabModeAsync, GrabModeAsync, None, None,
1048 CurrentTime) != GrabSuccess)
1049 {
1050 printf("DGA error: unable to grab mouse\r\n");
1051 return PRO_FAIL;
1052 }
1053
1054 pro_old_scroll = -2;
1055 pro_old_overlay_on = 0;
1056
1057 /* XXX Unblank screen here */
1058 }
1059 #endif
1060 /* Clear image buffer */
1061
1062 pro_screen_clear();
1063
1064 /* Invalidate display cache */
1065
1066 pro_clear_mvalid();
1067 }
1068
1069 return PRO_SUCCESS;
1070 }
1071
1072
pro_screen_close()1073 void pro_screen_close ()
1074 {
1075 /* XXX not currently used - see below
1076 XWindowAttributes winattr;
1077 */
1078
1079
1080 if (pro_libc_workaround)
1081 printf("1 DDD\r\n");
1082
1083 if (pro_screen_open)
1084 {
1085 if (pro_libc_workaround)
1086 printf("2 DDD\r\n");
1087
1088 pro_screen_open = 0;
1089
1090 /* XXX deallocate colors? */
1091
1092 /* Restore keyboard parameters */
1093
1094 if (pro_libc_workaround)
1095 printf("3 DDD\r\n");
1096
1097 if (pro_mouse_in == 1)
1098 pro_screen_restore_old_keyboard();
1099
1100 if (pro_libc_workaround)
1101 printf("4 DDD\r\n");
1102
1103 /* Save keymap */
1104
1105 pro_screen_save_keys();
1106
1107 if (pro_libc_workaround)
1108 printf("5 DDD\r\n");
1109
1110
1111 /* Close screen */
1112
1113 #ifdef DGA
1114 if (pro_screen_full)
1115 {
1116 /* XXX Blank screen here */
1117
1118 if (pro_libc_workaround)
1119 printf("6 DDD\r\n");
1120
1121 XUngrabKeyboard(ProDisplay, CurrentTime);
1122
1123 if (pro_libc_workaround)
1124 printf("7 DDD\r\n");
1125
1126 XUngrabPointer(ProDisplay, CurrentTime);
1127
1128 if (pro_libc_workaround)
1129 printf("8 DDD\r\n");
1130
1131 #ifdef DGA2
1132 XDGACloseFramebuffer(ProDisplay, ProScreen);
1133
1134 /* XXX Major #9 hack to return screen to proper mode */
1135
1136 if (pro_nine_workaround)
1137 XDGASetMode(ProDisplay, ProScreen, 1);
1138
1139 XDGASetMode(ProDisplay, ProScreen, 0);
1140 #else
1141 XF86DGADirectVideo(ProDisplay, ProScreen, 0);
1142
1143 if (pro_libc_workaround)
1144 printf("9 DDD\r\n");
1145
1146 XF86VidModeSwitchToMode(ProDisplay, ProScreen, &pro_modeline);
1147
1148 if (pro_libc_workaround)
1149 printf("10 DDD\r\n");
1150 #endif
1151 }
1152 else
1153 #endif
1154 {
1155 #ifdef SHM
1156 if (shm_present)
1157 {
1158 if (pro_libc_workaround)
1159 printf("11 DDD\r\n");
1160
1161 XShmDetach(ProDisplay, &shminfo);
1162
1163 if (pro_libc_workaround)
1164 printf("12 DDD\r\n");
1165
1166 XDestroyImage(pro_image);
1167
1168 if (pro_libc_workaround)
1169 printf("13 DDD\r\n");
1170
1171 shmdt(shminfo.shmaddr);
1172
1173 if (pro_libc_workaround)
1174 printf("14 DDD\r\n");
1175 }
1176 else
1177 #endif
1178 XDestroyImage(pro_image);
1179 }
1180
1181 /* Save window x, y coordinates */
1182
1183 /* XXX broken - always returns (0,0)
1184 XGetWindowAttributes (ProDisplay, ProWindow, &winattr);
1185
1186 pro_window_x = winattr.x;
1187 pro_window_y = winattr.y;
1188 */
1189
1190 if (pro_libc_workaround)
1191 printf("15 DDD\r\n");
1192
1193 XFreeGC (ProDisplay, ProGC);
1194
1195 if (pro_libc_workaround)
1196 printf("16 DDD\r\n");
1197
1198 XDestroyWindow (ProDisplay, ProWindow);
1199
1200 if (pro_libc_workaround)
1201 printf("17 DDD\r\n");
1202
1203 XCloseDisplay (ProDisplay);
1204
1205 if (pro_libc_workaround)
1206 printf("18 DDD\r\n");
1207
1208 /* Close the overlay frame buffer */
1209
1210 pro_overlay_close();
1211
1212 if (pro_libc_workaround)
1213 printf("19 DDD\r\n");
1214 }
1215
1216 /* XXX Unblank screen here */
1217 }
1218
1219
1220 /* Reset routine (called only once) */
1221
pro_screen_reset()1222 void pro_screen_reset ()
1223 {
1224 int r, g, b, i;
1225
1226
1227 /* Clear keymap */
1228
1229 memset(&pro_keyboard_keys, 0, sizeof(pro_keyboard_keys));
1230
1231 /* Reset keyboard control parameters */
1232
1233 pro_keyboard_control.bell_pitch = PRO_LK201_BELL_PITCH;
1234 pro_keyboard_control.bell_duration = PRO_LK201_BELL_DURATION;
1235 pro_keyboard_control.bell_percent = 100;
1236 pro_keyboard_control.key_click_percent = 0;
1237 pro_keyboard_control.auto_repeat_mode = AutoRepeatModeOn;
1238
1239 /* Initialize colormaps */
1240
1241 for(r=0; r<=1; r++)
1242 for(g=0; g<=1; g++)
1243 for(b=0; b<=1; b++)
1244 {
1245 i = (r | (g<<1) | (b<<2));
1246
1247 ProColor_nonmap[i].red = r * 65535;
1248 ProColor_nonmap[i].green = g * 65535;
1249 ProColor_nonmap[i].blue = b * 65535;
1250 ProColor_nonmap[i].flags = DoRed|DoGreen|DoBlue;
1251
1252 ProColor_map[i].red = 0;
1253 ProColor_map[i].green = 0;
1254 ProColor_map[i].blue = 0;
1255 ProColor_map[i].flags = DoRed|DoGreen|DoBlue;
1256 }
1257 }
1258
1259
1260 /* This function is called whenever the colormap mode changes.
1261 A new X11 colormap is loaded for private colormap modes,
1262 mvalid is cleared otherwise */
1263
pro_mapchange()1264 void pro_mapchange ()
1265 {
1266 XColor *ProColor;
1267
1268 if (pro_screen_clutmode == 1)
1269 {
1270 if ((pro_vid_csr & PRO_VID_CME) != 0)
1271 ProColor = ProColor_map;
1272 else
1273 ProColor = ProColor_nonmap;
1274
1275 /* XXX only 2 colors for non-ebo */
1276
1277 XStoreColors(ProDisplay, ProColormap, ProColor, 8);
1278 }
1279 else
1280 pro_clear_mvalid();
1281 }
1282
1283 /* This writes an 8-bit (3-3-2) RGB value into the PRO's colormap */
1284
pro_colormap_write(int index,int rgb)1285 void pro_colormap_write (int index, int rgb)
1286 {
1287 unsigned long pixel;
1288 double r, g, b;
1289
1290 #if PRO_EBO_PRESENT
1291 /* Calculate linear color component values 0.0 - 1.0 */
1292
1293 r = (double)((rgb & PRO_VID_R_MASK) >> 5)/7.0;
1294 g = (double)((rgb & PRO_VID_G_MASK) >> 2)/7.0;
1295 b = (double)(rgb & PRO_VID_B_MASK)/3.0;
1296
1297 /* Perform gamma correction */
1298
1299 r = pow(r, 10.0/(double)pro_screen_gamma);
1300 g = pow(g, 10.0/(double)pro_screen_gamma);
1301 b = pow(b, 10.0/(double)pro_screen_gamma);
1302
1303 ProColor_map[index].red = (int)(r * 65535.0);
1304 ProColor_map[index].green = (int)(g * 65535.0);
1305 ProColor_map[index].blue = (int)(b * 65535.0);
1306
1307 if (pro_screen_clutmode == 0)
1308 {
1309 /* Free old color */
1310
1311 pixel = pro_colormap[index];
1312
1313 XFreeColors(ProDisplay, ProColormap, &pixel, 1, 0L);
1314
1315 /* Allocate new color */
1316
1317 XAllocColor(ProDisplay, ProColormap, &ProColor_map[index]);
1318
1319 pro_colormap[index] = ProColor_map[index].pixel;
1320 }
1321
1322 /* Check if in colormapped mode */
1323
1324 if ((pro_vid_csr & PRO_VID_CME) != 0)
1325 {
1326 if (pro_screen_clutmode == 1)
1327 {
1328 XStoreColor(ProDisplay, ProColormap, &ProColor_map[index]);
1329 }
1330 else
1331 {
1332 /* The cache gets cleared only for non-private colormap X11 modes */
1333
1334 pro_clear_mvalid();
1335 }
1336 }
1337 #endif
1338
1339 /* XXX
1340 printf("Colormap write: index = %x rgb = %x colormap = %x\r\n", index, rgb, pro_colormap[index]);
1341 */
1342 }
1343
1344
1345 /* This is called whenever the scroll register changes */
1346
pro_scroll()1347 void pro_scroll ()
1348 {
1349 /* Clear entire display cache if DGA disabled,
1350 or if DGA is using only a single framebuffer */
1351
1352 #ifdef DGA
1353 if ((pro_screen_full == 0) || (pro_screen_framebuffers == 1))
1354 #endif
1355 pro_clear_mvalid();
1356 }
1357
1358
1359 /* Blending functions used for overlays */
1360
1361 #define blend \
1362 a = pro_overlay_alpha[pnum]; \
1363 na = PRO_OVERLAY_MAXA - a; \
1364 color = (((na*(pro_mask_r&color) + a*(pro_mask_r&opix))/PRO_OVERLAY_MAXA)&pro_mask_r) \
1365 + (((na*(pro_mask_g&color) + a*(pro_mask_g&opix))/PRO_OVERLAY_MAXA)&pro_mask_g) \
1366 + (((na*(pro_mask_b&color) + a*(pro_mask_b&opix))/PRO_OVERLAY_MAXA)&pro_mask_b)
1367
1368
1369 /* This is called every emulated vertical retrace */
1370
pro_screen_update()1371 void pro_screen_update ()
1372 {
1373 int i, vdata0, vdata1, vdata2, vindex, vpix, vpixs, vpixe, x, y;
1374 int a, na, opix, pnum, color, cindex;
1375 int offset, reps;
1376 #ifdef DGA
1377 int j, cur_scroll, scroll;
1378 #endif
1379 unsigned char *image_data;
1380
1381
1382 /* Service X events */
1383
1384 pro_screen_service_events();
1385
1386 image_data = pro_image_data;
1387
1388 #ifdef DGA
1389 scroll = -1; /* viewport will be updated if > -1 */
1390
1391 if (pro_screen_full && (pro_screen_framebuffers > 1))
1392 {
1393 /* Check if scroll register has changed */
1394 /* (only cause screen scroll if overlay is off) */
1395
1396 cur_scroll = pro_vid_scl & 0xff;
1397
1398 offset = (PRO_VID_SCRWIDTH+pro_image_stride)*pro_screen_pixsize
1399 *pro_screen_winheight/pro_screen_framebuffers;
1400
1401 reps = 2;
1402
1403 if (pro_overlay_on == 0)
1404 {
1405 vindex = 0;
1406
1407 /* Restore the viewport position if overlay was just turned off */
1408 /* Or scroll viewport if scroll register has changed */
1409
1410 if ((pro_old_overlay_on != 0) || (cur_scroll != pro_old_scroll))
1411 scroll = cur_scroll;
1412 }
1413 else
1414 {
1415 vindex = vmem(0);
1416
1417 /* Reset the viewport position if overlay was just turned on */
1418 /* And force full screen redraw */
1419
1420 if (pro_old_overlay_on == 0)
1421 {
1422 pro_clear_mvalid();
1423
1424 if (pro_screen_framebuffers == 3)
1425 scroll = 2*PRO_VID_MEMHEIGHT;
1426 else
1427 scroll = pro_menu_scroll = cur_scroll;
1428 }
1429
1430 /* If the overlay is on, scroll the screen by redrawing */
1431
1432 if (cur_scroll != pro_old_scroll)
1433 pro_clear_mvalid();
1434
1435 /* Use third frame buffer for overlay mode (if enabled) */
1436 /* Otherwise, align frame buffer with visible portion of
1437 screen when menu was turned on */
1438
1439 if (pro_screen_framebuffers == 3)
1440 image_data += 2*offset;
1441 else
1442 image_data += (PRO_VID_SCRWIDTH+pro_image_stride)
1443 *pro_screen_pixsize*pro_screen_full_scale
1444 *pro_menu_scroll;
1445 }
1446
1447 pro_old_scroll = cur_scroll;
1448 pro_old_overlay_on = pro_overlay_on;
1449 }
1450 else
1451 #endif
1452 {
1453 offset = 0;
1454 reps = 1;
1455 vindex = vmem(0);
1456 }
1457
1458 /* Check whether screen has been blanked */
1459
1460 if ((pro_vid_p1c & PRO_VID_P1_HRS) == PRO_VID_P1_OFF)
1461 {
1462 if (pro_screen_blank == 0)
1463 {
1464 /* Blank the screen */
1465
1466 #ifdef DGA
1467 if (pro_screen_full)
1468 pro_screen_clear();
1469 else
1470 #endif
1471 XClearWindow(ProDisplay, ProWindow);
1472
1473 pro_screen_blank = 1;
1474 }
1475 }
1476 else
1477 {
1478 if (pro_screen_blank == 1)
1479 {
1480 /* Unblank the screen */
1481
1482 pro_clear_mvalid();
1483 pro_screen_blank = 0;
1484 }
1485
1486 #if PRO_EBO_PRESENT
1487 /* Determine whether system is in color mapped mode */
1488
1489 if ((pro_vid_csr & PRO_VID_CME) != 0)
1490 pro_lut = pro_colormap;
1491 else
1492 pro_lut = pro_nonmap;
1493 #else
1494 pro_lut = pro_nonmap;
1495 #endif
1496
1497 /* Redraw portions of screen that have changed */
1498
1499 for(y=0; y<pro_screen_updateheight; y++)
1500 {
1501 for(x=0; x<PRO_VID_SCRWIDTH; x+=PRO_VID_CLS_PIX)
1502 {
1503 /* Update screen segment only if display cache is invalid */
1504
1505 if (pro_vid_mvalid[cmem(vindex)] == 0)
1506 {
1507 if (pro_overlay_on == 0)
1508 #ifdef DGA
1509 for(j = 1; j >= (3-2*reps); image_data += j*offset, j -= 2)
1510 {
1511 #endif
1512 for(i=0; i<(PRO_VID_CLS_PIX/16); i++)
1513 {
1514 vpixs = i * 16;
1515 vpixe = vpixs + 16;
1516
1517 vdata0 = PRO_VRAM[0][vindex+i];
1518 vdata1 = PRO_VRAM[1][vindex+i] << 1;
1519 vdata2 = PRO_VRAM[2][vindex+i] << 2;
1520
1521 for(vpix=vpixs; vpix<vpixe; vpix++)
1522 {
1523 cindex = (vdata2 & 04) | (vdata1 & 02) | (vdata0 & 01);
1524 color = pro_lut[cindex];
1525
1526 switch(pro_screen_pixsize)
1527 {
1528 case 1:
1529 image_data[vpix] = color;
1530 break;
1531 case 2:
1532 ((unsigned short *)image_data)[vpix] = color;
1533 break;
1534 case 4:
1535 ((unsigned int *)image_data)[vpix] = color;
1536 break;
1537 default:
1538 break;
1539 }
1540
1541 vdata0 = vdata0 >> 1;
1542 vdata1 = vdata1 >> 1;
1543 vdata2 = vdata2 >> 1;
1544 }
1545 }
1546 #ifdef DGA
1547 }
1548 #endif
1549 else
1550 /* XXX putting this in a function might speed things up */
1551
1552 for(i=0; i<(PRO_VID_CLS_PIX/16); i++)
1553 {
1554 vpixs = i * 16;
1555 vpixe = vpixs + 16;
1556
1557 vdata0 = PRO_VRAM[0][vindex+i];
1558 vdata1 = PRO_VRAM[1][vindex+i] << 1;
1559 vdata2 = PRO_VRAM[2][vindex+i] << 2;
1560
1561 for(vpix=vpixs; vpix<vpixe; vpix++)
1562 {
1563 cindex = (vdata2 & 04) | (vdata1 & 02) | (vdata0 & 01);
1564 color = pro_lut[cindex];
1565
1566 pnum = y*PRO_VID_SCRWIDTH+x+vpix;
1567
1568 switch(pro_screen_pixsize)
1569 {
1570 case 1:
1571 opix = pro_overlay_data[pnum];
1572 blend;
1573 image_data[vpix] = color;
1574 break;
1575 case 2:
1576 opix = ((unsigned short *)pro_overlay_data)[pnum];
1577 blend;
1578 ((unsigned short *)image_data)[vpix] = color;
1579 break;
1580 case 4:
1581 opix = ((unsigned int *)pro_overlay_data)[pnum];
1582 blend;
1583 ((unsigned int *)image_data)[vpix] = color;
1584 break;
1585 default:
1586 break;
1587 }
1588
1589 vdata0 = vdata0 >> 1;
1590 vdata1 = vdata1 >> 1;
1591 vdata2 = vdata2 >> 1;
1592 }
1593 }
1594
1595 /* Draw cache-line on screen */
1596 #ifdef DGA
1597 if (pro_screen_full == 0)
1598 #endif
1599 {
1600 #ifdef SHM
1601 if (shm_present)
1602 XShmPutImage(ProDisplay, ProWindow, ProGC, pro_image, x, y,
1603 x, y*pro_screen_window_scale, PRO_VID_CLS_PIX, 1, False);
1604 else
1605 #endif
1606 XPutImage(ProDisplay, ProWindow, ProGC, pro_image, x, y,
1607 x, y*pro_screen_window_scale, PRO_VID_CLS_PIX, 1);
1608 }
1609
1610 /* Mark cache entry valid */
1611
1612 pro_vid_mvalid[cmem(vindex)] = 1;
1613 }
1614
1615 vindex = (vindex + (PRO_VID_CLS_PIX/16)) & PRO_VID_VADDR_MASK;
1616
1617 image_data += pro_screen_clsize;
1618 }
1619 #ifdef DGA
1620 if (pro_screen_full)
1621 image_data += ((pro_screen_full_scale-1)*PRO_VID_SCRWIDTH+pro_screen_full_scale*pro_image_stride)*pro_screen_pixsize;
1622 #endif
1623 }
1624
1625 XFlush (ProDisplay);
1626 }
1627
1628 /* Check if title needs to be updated */
1629
1630 if (title_needs_update)
1631 {
1632 title_needs_update = 0;
1633 #ifdef DGA
1634 /* XXX
1635 if (pro_screen_full)
1636 printf("%s\r\n", current_title);
1637 */
1638 #endif
1639 XStoreName(ProDisplay, ProWindow, current_title);
1640 XFlush(ProDisplay);
1641 }
1642
1643 #ifdef DGA
1644 /* Move viewport, if required */
1645
1646 if (pro_screen_full)
1647 {
1648 if (scroll >= 0)
1649 #ifdef DGA2
1650 {
1651 XDGASetViewport(ProDisplay, ProScreen, 0, pro_screen_full_scale*scroll, XDGAFlipImmediate);
1652
1653 /* Wait for viewport update in case XDGAFlipImmediate is not
1654 supported */
1655
1656 while(XDGAGetViewportStatus(ProDisplay, ProScreen));
1657 }
1658 #else
1659 XF86DGASetViewPort(ProDisplay, ProScreen, 0, pro_screen_full_scale*scroll);
1660 #endif
1661 }
1662 #endif
1663 }
1664
1665
1666 /* Set keyboard bell volume */
1667
pro_keyboard_bell_vol(int vol)1668 void pro_keyboard_bell_vol (int vol)
1669 {
1670 /* XXX This actually seems to change the duration under Linux!? */
1671
1672 /* vol is in the range 0 (loudest) to 7 (softest) */
1673
1674 pro_keyboard_control.bell_percent = (100*(7-vol))/7;
1675
1676 pro_screen_restore_keyboard();
1677
1678 XFlush(ProDisplay);
1679 }
1680
1681
1682 /* Sound keyboard bell */
1683
pro_keyboard_bell()1684 void pro_keyboard_bell ()
1685 {
1686 XBell(ProDisplay, 0);
1687 XFlush(ProDisplay);
1688 }
1689
1690
1691 /* Turn off auto-repeat */
1692
pro_keyboard_auto_off()1693 void pro_keyboard_auto_off ()
1694 {
1695 pro_keyboard_control.auto_repeat_mode = AutoRepeatModeOff;
1696
1697 pro_screen_restore_keyboard();
1698
1699 XFlush(ProDisplay);
1700 }
1701
1702
1703 /* Turn on auto-repeat */
1704
pro_keyboard_auto_on()1705 void pro_keyboard_auto_on ()
1706 {
1707 pro_keyboard_control.auto_repeat_mode = AutoRepeatModeOn;
1708
1709 pro_screen_restore_keyboard();
1710
1711 XFlush(ProDisplay);
1712 }
1713
1714
1715 /* Turn off keyclick */
1716
pro_keyboard_click_off()1717 void pro_keyboard_click_off ()
1718 {
1719 pro_keyboard_control.key_click_percent = 0;
1720
1721 pro_screen_restore_keyboard();
1722
1723 XFlush(ProDisplay);
1724 }
1725
1726
1727 /* Turn on keyclick */
1728
pro_keyboard_click_on()1729 void pro_keyboard_click_on ()
1730 {
1731 pro_keyboard_control.key_click_percent = 100;
1732
1733 pro_screen_restore_keyboard();
1734
1735 XFlush(ProDisplay);
1736 }
1737
1738
1739 /* The following is a workaround for an x11-hang bug under Linux */
1740
XCheckMaskEvent_nohang(Display * dpy,long event_mask,XEvent * event)1741 int XCheckMaskEvent_nohang(Display* dpy, long event_mask, XEvent* event)
1742 {
1743 static int checkready = 0;
1744 static sigset_t checkmask;
1745 sigset_t oldmask;
1746 Bool event_return;
1747
1748 if (!checkready)
1749 {
1750 checkready = 1;
1751 sigemptyset(&checkmask);
1752 /*
1753 sigaddset(&checkmask, SIGUSR1);
1754 sigaddset(&checkmask, SIGUSR2);
1755 */
1756 sigaddset(&checkmask, SIGALRM);
1757 /*
1758 * Add any other signals to the mask that might otherwise
1759 * be set off during the XCheckMaskEvent. It is possible
1760 * that none of this is needed if libX11 is compiled with
1761 * linux libc-6, because a lot of the code in libX11 compiles
1762 * differently with libc-6 (because of improved thread support.)
1763 * Meanwhile, this hack should allow it to work with libc-5.
1764 */
1765 }
1766 sigprocmask(SIG_BLOCK, &checkmask, &oldmask);
1767 event_return = XCheckMaskEvent(dpy, event_mask, event);
1768 sigprocmask(SIG_UNBLOCK, &oldmask, 0);
1769 return event_return;
1770 }
1771
1772
1773 /* Service X events */
1774
pro_screen_service_events()1775 void pro_screen_service_events ()
1776 {
1777 XEvent event; /* XXX should this be XDGAEvent for DGA2? */
1778 #ifdef DGAXXX
1779 XKeyEvent keyevent;
1780 #endif
1781 int expose = 0;
1782 int key;
1783 int eventtype;
1784
1785
1786 /* If multiple events are buffered up, flush them all out */
1787
1788 /* XXX bug workaround */
1789
1790 while (XCheckMaskEvent_nohang(ProDisplay, ProEventMask, (XEvent *)&event))
1791 {
1792 eventtype = event.type;
1793
1794 #ifdef DGAXXX
1795 if (pro_screen_full)
1796 eventtype -= pro_vid_dga_eventbase;
1797 #endif
1798
1799 switch (eventtype)
1800 {
1801 case Expose:
1802 expose = 1;
1803 break;
1804
1805 case KeyPress:
1806 #ifdef DGAXXX
1807 #ifdef DGA
1808 #ifdef DGA2
1809 if (pro_screen_full)
1810 {
1811 XDGAKeyEventToXKeyEvent((XDGAKeyEvent*)&event.xkey, (XKeyEvent*)&keyevent);
1812 key = XLookupKeysym((XKeyEvent*)&keyevent, 0);
1813 }
1814 else
1815 #endif
1816 #endif
1817 #endif
1818 key = XLookupKeysym((XKeyEvent*)&event, 0);
1819 key = pro_keyboard_lookup_down(key);
1820 if (key != PRO_NOCHAR)
1821 pro_keyboard_fifo_put(key);
1822 break;
1823
1824 case KeyRelease:
1825 #ifdef DGAXXX
1826 #ifdef DGA
1827 #ifdef DGA2
1828 if (pro_screen_full)
1829 {
1830 XDGAKeyEventToXKeyEvent((XDGAKeyEvent*)&event.xkey, (XKeyEvent*)&keyevent);
1831 key = XLookupKeysym((XKeyEvent*)&keyevent, 0);
1832 }
1833 else
1834 #endif
1835 #endif
1836 #endif
1837 key = XLookupKeysym((XKeyEvent*)&event, 0);
1838 key = pro_keyboard_lookup_up(key);
1839 if (key != PRO_NOCHAR)
1840 pro_keyboard_fifo_put(key);
1841 break;
1842
1843 case MotionNotify:
1844 #ifdef DGA
1845 if (pro_screen_full)
1846 {
1847 /* DGA mouse events are returned as *relative* motion */
1848
1849 pro_mouse_x += ((XMotionEvent*)&event)->x_root;
1850 pro_mouse_y_screen += ((XMotionEvent*)&event)->y_root;
1851 pro_mouse_y = pro_mouse_y_screen/pro_screen_full_scale;
1852 if (pro_mouse_x >= PRO_VID_SCRWIDTH)
1853 pro_mouse_x = PRO_VID_SCRWIDTH-1;
1854 if (pro_mouse_x < 0)
1855 pro_mouse_x = 0;
1856 if (pro_mouse_y >= PRO_VID_SCRHEIGHT)
1857 pro_mouse_y = PRO_VID_SCRHEIGHT-1;
1858 if (pro_mouse_y < 0)
1859 pro_mouse_y = 0;
1860 }
1861 else
1862 #endif
1863 {
1864 pro_mouse_x = ((XMotionEvent*)&event)->x;
1865 pro_mouse_y = (((XMotionEvent*)&event)->y)/pro_screen_window_scale;
1866 }
1867
1868 break;
1869
1870 case ButtonPress:
1871 switch (((XButtonEvent *)&event)->button)
1872 {
1873 case Button1:
1874 pro_mouse_l = 1;
1875 break;
1876
1877 case Button2:
1878 pro_mouse_m = 1;
1879 break;
1880
1881 case Button3:
1882 pro_mouse_r = 1;
1883 break;
1884 }
1885 break;
1886
1887 case ButtonRelease:
1888 switch (((XButtonEvent *)&event)->button)
1889 {
1890 case Button1:
1891 pro_mouse_l = 0;
1892 break;
1893
1894 case Button2:
1895 pro_mouse_m = 0;
1896 break;
1897
1898 case Button3:
1899 pro_mouse_r = 0;
1900 break;
1901 }
1902 break;
1903
1904 case EnterNotify:
1905 if (pro_mouse_in == 0)
1906 {
1907 pro_screen_save_old_keyboard();
1908 pro_mouse_in = 1;
1909 pro_screen_restore_keyboard();
1910 pro_screen_update_keys();
1911 }
1912 break;
1913
1914 case LeaveNotify:
1915 if (pro_mouse_in == 1)
1916 {
1917 pro_screen_save_keys();
1918 pro_mouse_in = 0;
1919 pro_screen_restore_old_keyboard();
1920 }
1921 break;
1922 }
1923 }
1924
1925 /* Check if screen should be updated */
1926
1927 if (expose)
1928 {
1929 /* Clear the window */
1930
1931 XClearWindow(ProDisplay, ProWindow);
1932
1933 /* Clear display cache, forcing full update */
1934
1935 pro_clear_mvalid();
1936 }
1937 }
1938 #endif
1939