- compilation fixes for MSVC toolkit 2003
[bochs-mirror.git] / gui / svga.cc
blobc7280a89b17917ce8c8932290397c279c2a9dc1f
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: svga.cc,v 1.17 2008/03/06 21:15:40 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #define _MULTI_THREAD
21 // Define BX_PLUGGABLE in files that can be compiled into plugins. For
22 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
23 // is used to know when we are exporting symbols and when we are importing.
24 #define BX_PLUGGABLE
26 #include "bochs.h"
27 #include "iodev.h"
28 #if BX_WITH_SVGA
30 #include <stdlib.h>
31 #include </usr/include/vga.h>
32 #include <vgagl.h>
33 #include <vgakeyboard.h>
34 #include <vgamouse.h>
36 #include "font/vga.bitmap.h"
37 //#include "icon_bochs.h"
39 class bx_svga_gui_c : public bx_gui_c {
40 public:
41 bx_svga_gui_c (void);
42 DECLARE_GUI_VIRTUAL_METHODS()
43 virtual void set_display_mode (disp_mode_t newmode);
46 // declare one instance of the gui object and call macro to insert the
47 // plugin code
48 static bx_svga_gui_c *theGui = NULL;
50 IMPLEMENT_GUI_PLUGIN_CODE(svga)
52 #define LOG_THIS theGui->
54 static unsigned res_x, res_y;
55 static unsigned fontwidth, fontheight;
56 static unsigned tilewidth, tileheight;
57 static unsigned char vgafont[256 * 16];
58 static int clut8 = 0;
59 GraphicsContext *screen = NULL;
60 static int save_vga_mode;
61 static int save_vga_pal[256 * 3];
62 static Bit8u fontbuffer[0x2000];
64 static bx_bool ctrll_pressed = 0;
65 static unsigned int text_rows=25, text_cols=80;
66 static unsigned prev_cursor_x=0;
67 static unsigned prev_cursor_y=0;
69 void keyboard_handler(int scancode, int press);
70 void mouse_handler(int button, int dx, int dy, int dz,
71 int drx, int dry, int drz);
73 unsigned char reverse_byteorder(unsigned char b)
75 unsigned char ret = 0;
77 for (unsigned i=0;i<8;i++){
78 ret |= (b & 0x01) << (7 - i);
79 b >>= 1;
81 return ret;
84 void create_vga_font()
86 memcpy(vgafont, bx_vgafont, sizeof(bx_vgafont));
88 for (unsigned i=0;i< sizeof(bx_vgafont);i++) {
89 vgafont[i] = reverse_byteorder(vgafont[i]);
93 bx_svga_gui_c::bx_svga_gui_c()
95 put("SVGA");
98 void bx_svga_gui_c::specific_init(
99 int argc,
100 char **argv,
101 unsigned x_tilesize,
102 unsigned y_tilesize,
103 unsigned header_bar_y)
105 tilewidth = x_tilesize;
106 tileheight = y_tilesize;
108 if(vga_init() != 0)
110 LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
111 BX_PANIC (("Unable to initialize SVGAlib"));
112 return;
115 screen = gl_allocatecontext();
117 fontwidth = 8;
118 fontheight = 16;
119 dimension_update(640,400);
120 create_vga_font();
121 gl_setfont(fontwidth, fontheight, (void *)vgafont);
122 gl_setwritemode(FONT_COMPRESSED);
124 keyboard_init();
125 keyboard_seteventhandler((__keyboard_handler) keyboard_handler);
127 vga_setmousesupport(1);
128 mouse_seteventhandler((__mouse_handler) mouse_handler);
129 if (vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_FLAGS) & VGA_CLUT8) {
130 vga_ext_set(VGA_EXT_SET, VGA_CLUT8);
131 clut8 = 1;
133 // Save settings to prepare for mode transition in set_display_mode.
134 // If DISP_MODE_SIM is called first, these values will be used.
135 save_vga_mode = vga_getcurrentmode();
136 vga_getpalvec(0, 256, save_vga_pal);
139 void bx_svga_gui_c::text_update(
140 Bit8u *old_text,
141 Bit8u *new_text,
142 unsigned long cursor_x,
143 unsigned long cursor_y,
144 bx_vga_tminfo_t tm_info)
146 Bit8u *old_line, *new_line;
147 unsigned int curs, hchars, i, j, offset, rows, x, y;
148 char s[] = " ";
149 int fg, bg;
150 bx_bool force_update = 0, blink_state, blink_mode;
151 int text_palette[16];
153 // first check if the screen needs to be redrawn completely
154 blink_mode = (tm_info.blink_flags & BX_TEXT_BLINK_MODE) > 0;
155 blink_state = (tm_info.blink_flags & BX_TEXT_BLINK_STATE) > 0;
156 if (blink_mode) {
157 if (tm_info.blink_flags & BX_TEXT_BLINK_TOGGLE)
158 force_update = 1;
160 if (charmap_updated) {
161 BX_INFO(("charmap update. Font Height is %d", fontheight));
162 for (unsigned c = 0; c<256; c++) {
163 if (char_changed[c]) {
164 j = c * fontheight;
165 for(i=0; i<fontheight; i++) {
166 fontbuffer[j++] = vga_charmap[(c<<5)+i];
168 char_changed[c] = 0;
171 gl_setfont(fontwidth, fontheight, (void *)fontbuffer);
172 force_update = 1;
173 charmap_updated = 0;
175 for (i=0; i<16; i++) {
176 text_palette[i] = DEV_vga_get_actl_pal_idx(i);
179 // invalidate character at previous and new cursor location
180 if((prev_cursor_y < text_rows) && (prev_cursor_x < text_cols)) {
181 curs = prev_cursor_y * tm_info.line_offset + prev_cursor_x * 2;
182 old_text[curs] = ~new_text[curs];
184 if((tm_info.cs_start <= tm_info.cs_end) && (tm_info.cs_start < fontheight) &&
185 (cursor_y < text_rows) && (cursor_x < text_cols)) {
186 curs = cursor_y * tm_info.line_offset + cursor_x * 2;
187 old_text[curs] = ~new_text[curs];
188 } else {
189 curs = 0xffff;
192 rows = text_rows;
193 y = 0;
194 do {
195 hchars = text_cols;
196 new_line = new_text;
197 old_line = old_text;
198 x = 0;
199 offset = y * tm_info.line_offset;
200 do {
201 if (force_update || (old_text[0] != new_text[0])
202 || (old_text[1] != new_text[1])) {
203 s[0] = new_text[0];
204 fg = text_palette[new_text[1] & 0x0F];
205 if (blink_mode) {
206 bg = text_palette[(new_text[1] & 0x70) >> 4];
207 if (!blink_state && (new_text[1] & 0x80))
208 fg = bg;
209 } else {
210 bg = text_palette[(new_text[1] & 0xF0) >> 4];
212 if (offset == curs) {
213 gl_setfontcolors(fg, bg);
214 } else {
215 gl_setfontcolors(bg, fg);
217 gl_write(x * fontwidth, y * fontheight, s);
219 x++;
220 new_text+=2;
221 old_text+=2;
222 offset+=2;
223 } while (--hchars);
224 y++;
225 new_text = new_line + tm_info.line_offset;
226 old_text = old_line + tm_info.line_offset;
227 } while (--rows);
229 prev_cursor_x = cursor_x;
230 prev_cursor_y = cursor_y;
233 int bx_svga_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes)
235 return 0;
238 int bx_svga_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len)
240 return 0;
243 void bx_svga_gui_c::graphics_tile_update(Bit8u *snapshot, unsigned x, unsigned y)
245 if ((y + tileheight) > res_y) {
246 gl_putbox(x, y, tilewidth, (res_y - y), snapshot);
247 } else {
248 gl_putbox(x, y, tilewidth, tileheight, snapshot);
252 static Bit32u vga_to_bx_key(int key)
254 ctrll_pressed = 0;
255 switch (key) {
256 case SCANCODE_ESCAPE: return BX_KEY_ESC;
257 case SCANCODE_1: return BX_KEY_1;
258 case SCANCODE_2: return BX_KEY_2;
259 case SCANCODE_3: return BX_KEY_3;
260 case SCANCODE_4: return BX_KEY_4;
261 case SCANCODE_5: return BX_KEY_5;
262 case SCANCODE_6: return BX_KEY_6;
263 case SCANCODE_7: return BX_KEY_7;
264 case SCANCODE_8: return BX_KEY_8;
265 case SCANCODE_9: return BX_KEY_9;
266 case SCANCODE_0: return BX_KEY_0;
268 case SCANCODE_MINUS: return BX_KEY_MINUS;
269 case SCANCODE_EQUAL: return BX_KEY_EQUALS;
270 case SCANCODE_TAB: return BX_KEY_TAB;
271 case SCANCODE_BACKSPACE: return BX_KEY_BACKSPACE;
273 case SCANCODE_Q: return BX_KEY_Q;
274 case SCANCODE_W: return BX_KEY_W;
275 case SCANCODE_E: return BX_KEY_E;
276 case SCANCODE_R: return BX_KEY_R;
277 case SCANCODE_T: return BX_KEY_T;
278 case SCANCODE_Y: return BX_KEY_Y;
279 case SCANCODE_U: return BX_KEY_U;
280 case SCANCODE_I: return BX_KEY_I;
281 case SCANCODE_O: return BX_KEY_O;
282 case SCANCODE_P: return BX_KEY_P;
284 case SCANCODE_BRACKET_LEFT: return BX_KEY_LEFT_BRACKET;
285 case SCANCODE_BRACKET_RIGHT: return BX_KEY_RIGHT_BRACKET;
287 case SCANCODE_ENTER: return BX_KEY_ENTER;
288 case SCANCODE_LEFTCONTROL:
289 ctrll_pressed = 1;
290 return BX_KEY_CTRL_L;
292 case SCANCODE_A: return BX_KEY_A;
293 case SCANCODE_S: return BX_KEY_S;
294 case SCANCODE_D: return BX_KEY_D;
295 case SCANCODE_F: return BX_KEY_F;
296 case SCANCODE_G: return BX_KEY_G;
297 case SCANCODE_H: return BX_KEY_H;
298 case SCANCODE_J: return BX_KEY_J;
299 case SCANCODE_K: return BX_KEY_K;
300 case SCANCODE_L: return BX_KEY_L;
302 case SCANCODE_SEMICOLON: return BX_KEY_SEMICOLON;
303 case SCANCODE_APOSTROPHE: return BX_KEY_SINGLE_QUOTE;
304 case SCANCODE_GRAVE: return BX_KEY_GRAVE;
306 case SCANCODE_LEFTSHIFT: return BX_KEY_SHIFT_L;
307 case SCANCODE_BACKSLASH: return BX_KEY_BACKSLASH;
309 case SCANCODE_Z: return BX_KEY_Z;
310 case SCANCODE_X: return BX_KEY_X;
311 case SCANCODE_C: return BX_KEY_C;
312 case SCANCODE_V: return BX_KEY_V;
313 case SCANCODE_B: return BX_KEY_B;
314 case SCANCODE_N: return BX_KEY_N;
315 case SCANCODE_M: return BX_KEY_M;
317 case SCANCODE_COMMA: return BX_KEY_COMMA;
318 case SCANCODE_PERIOD: return BX_KEY_PERIOD;
319 case SCANCODE_SLASH: return BX_KEY_SLASH;
321 case SCANCODE_RIGHTSHIFT: return BX_KEY_SHIFT_R;
322 case SCANCODE_KEYPADMULTIPLY: return BX_KEY_KP_MULTIPLY;
324 case SCANCODE_LEFTALT: return BX_KEY_ALT_L;
325 case SCANCODE_SPACE: return BX_KEY_SPACE;
326 case SCANCODE_CAPSLOCK: return BX_KEY_CAPS_LOCK;
328 case SCANCODE_F1: return BX_KEY_F1;
329 case SCANCODE_F2: return BX_KEY_F2;
330 case SCANCODE_F3: return BX_KEY_F3;
331 case SCANCODE_F4: return BX_KEY_F4;
332 case SCANCODE_F5: return BX_KEY_F5;
333 case SCANCODE_F6: return BX_KEY_F6;
334 case SCANCODE_F7: return BX_KEY_F7;
335 case SCANCODE_F8: return BX_KEY_F8;
336 case SCANCODE_F9: return BX_KEY_F9;
337 case SCANCODE_F10: return BX_KEY_F10;
339 case SCANCODE_NUMLOCK: return BX_KEY_NUM_LOCK;
340 case SCANCODE_SCROLLLOCK: return BX_KEY_SCRL_LOCK;
342 case SCANCODE_KEYPAD7: return BX_KEY_KP_HOME;
343 case SCANCODE_KEYPAD8: return BX_KEY_KP_UP;
344 case SCANCODE_KEYPAD9: return BX_KEY_KP_PAGE_UP;
345 case SCANCODE_KEYPADMINUS: return BX_KEY_KP_SUBTRACT;
346 case SCANCODE_KEYPAD4: return BX_KEY_KP_LEFT;
347 case SCANCODE_KEYPAD5: return BX_KEY_KP_5;
348 case SCANCODE_KEYPAD6: return BX_KEY_KP_RIGHT;
349 case SCANCODE_KEYPADPLUS: return BX_KEY_KP_ADD;
350 case SCANCODE_KEYPAD1: return BX_KEY_KP_END;
351 case SCANCODE_KEYPAD2: return BX_KEY_KP_DOWN;
352 case SCANCODE_KEYPAD3: return BX_KEY_KP_PAGE_DOWN;
353 case SCANCODE_KEYPAD0: return BX_KEY_KP_INSERT;
354 // case SCANCODE_KEYPADPERIOD: return BX_KEY_KP_; /* ??? */
356 // case SCANCODE_LESS: return BX_KEY_KP_LESS; /* ??? */
358 case SCANCODE_F11: return BX_KEY_F11;
359 case SCANCODE_F12: return BX_KEY_F12;
361 case SCANCODE_KEYPADENTER: return BX_KEY_KP_ENTER;
362 case SCANCODE_RIGHTCONTROL: return BX_KEY_CTRL_R;
363 case SCANCODE_KEYPADDIVIDE: return BX_KEY_KP_DIVIDE;
364 case SCANCODE_PRINTSCREEN: return BX_KEY_PRINT;
365 case SCANCODE_RIGHTALT: return BX_KEY_ALT_R;
366 case SCANCODE_BREAK: return BX_KEY_PAUSE;
368 case SCANCODE_HOME: return BX_KEY_HOME;
369 case SCANCODE_CURSORBLOCKUP: return BX_KEY_UP;
370 case SCANCODE_PAGEUP: return BX_KEY_PAGE_UP;
371 case SCANCODE_CURSORBLOCKLEFT: return BX_KEY_LEFT;
372 case SCANCODE_CURSORBLOCKRIGHT: return BX_KEY_RIGHT;
373 case SCANCODE_END: return BX_KEY_END;
374 case SCANCODE_CURSORBLOCKDOWN: return BX_KEY_DOWN;
375 case SCANCODE_PAGEDOWN: return BX_KEY_PAGE_DOWN;
376 case SCANCODE_INSERT: return BX_KEY_INSERT;
377 case SCANCODE_REMOVE: return BX_KEY_DELETE;
379 case SCANCODE_RIGHTWIN: return BX_KEY_WIN_R;
380 case SCANCODE_LEFTWIN: return BX_KEY_WIN_L;
382 default: return 0;
386 void keyboard_handler(int scancode, int press)
388 if (scancode != SCANCODE_F12) {
389 int bx_key = vga_to_bx_key(scancode);
390 Bit32u key_state;
392 if (press) {
393 key_state = BX_KEY_PRESSED;
394 } else {
395 key_state = BX_KEY_RELEASED;
398 DEV_kbd_gen_scancode(bx_key | key_state);
399 } else {
400 BX_INFO(("F12 pressed"));
401 // show runtime options menu, which uses stdin/stdout
402 SIM->configuration_interface (NULL, CI_RUNTIME_CONFIG);
406 void mouse_handler(int button, int dx, int dy, int dz,
407 int drx, int dry, int drz)
409 int buttons = 0;
411 if (button & MOUSE_LEFTBUTTON) {
412 buttons |= 0x01;
414 if (button & MOUSE_RIGHTBUTTON) {
415 buttons |= 0x02;
417 if (button & MOUSE_MIDDLEBUTTON) {
418 buttons |= 0x04;
420 if (ctrll_pressed && ((buttons == 0x04) || (buttons == 0x05))) {
421 bx_bool old = SIM->get_param_bool(BXPN_MOUSE_ENABLED)->get();
422 SIM->get_param_bool(BXPN_MOUSE_ENABLED)->set(!old);
423 } else {
424 DEV_mouse_motion((int) (0.25 * dx), (int) -(0.25 * dy), buttons);
428 void bx_svga_gui_c::handle_events(void)
430 keyboard_update();
431 keyboard_clearstate();
432 mouse_update();
435 void bx_svga_gui_c::flush(void)
437 gl_copyscreen(screen);
440 void bx_svga_gui_c::clear_screen(void)
442 gl_clearscreen(0);
445 bx_bool bx_svga_gui_c::palette_change(
446 unsigned index,
447 unsigned red,
448 unsigned green,
449 unsigned blue)
451 if(index > 255) return 0;
453 // without VGA_CLUT8 extension we have only 6 bits for each r,g,b value
454 if (!clut8 && (red > 63 || green > 63 || blue > 63)) {
455 red = red >> 2;
456 green = green >> 2;
457 blue = blue >> 2;
460 vga_setpalette(index, red, green, blue);
462 return 1;
466 void bx_svga_gui_c::dimension_update(
467 unsigned x,
468 unsigned y,
469 unsigned fheight,
470 unsigned fwidth,
471 unsigned bpp)
473 int newmode = 0;
475 if (bpp > 8) {
476 BX_PANIC(("%d bpp graphics mode not supported yet", bpp));
478 if(fheight > 0)
480 text_cols = x / fwidth;
481 text_rows = y / fheight;
482 fontheight = fheight;
483 if (fwidth != 8) {
484 x = x * 8 / fwidth;
486 fontwidth = 8;
489 if ((x == res_x) && (y == res_y)) return;
491 if (x == 640 && y == 480) {
492 newmode = G640x480x256;
493 } else if (x == 640 && y == 400) {
494 newmode = G640x400x256;
495 } else if (x == 800 && y == 600) {
496 newmode = G800x600x256;
497 } else if (x == 1024 && y == 768) {
498 newmode = G1024x768x256;
501 if (!vga_hasmode(newmode)) {
502 newmode = G640x480x256; // trying "default" mode...
505 vga_getpalvec(0, 256, save_vga_pal);
506 if (vga_setmode(newmode) != 0)
508 LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
509 BX_PANIC (("Unable to set requested videomode: %ix%i", x, y));
512 gl_setcontextvga(newmode);
513 gl_getcontext(screen);
514 gl_setcontextvgavirtual(newmode);
515 vga_setpalvec(0, 256, save_vga_pal);
516 save_vga_mode = newmode;
518 res_x = x;
519 res_y = y;
523 unsigned bx_svga_gui_c::create_bitmap(
524 const unsigned char *bmap,
525 unsigned xdim,
526 unsigned ydim)
528 return 0;
532 unsigned bx_svga_gui_c::headerbar_bitmap(
533 unsigned bmap_id,
534 unsigned alignment,
535 void (*f)(void))
537 return 0;
540 void bx_svga_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id)
544 void bx_svga_gui_c::show_headerbar(void)
549 void bx_svga_gui_c::mouse_enabled_changed_specific (bx_bool val)
554 void headerbar_click(int x)
558 void bx_svga_gui_c::exit(void)
560 vga_setmode(TEXT);
561 keyboard_close();
562 mouse_close();
565 void bx_svga_gui_c::set_display_mode (disp_mode_t newmode)
567 // if no mode change, do nothing.
568 if (disp_mode == newmode) return;
569 // remember the display mode for next time
570 disp_mode = newmode;
571 switch (newmode) {
572 case DISP_MODE_CONFIG:
573 BX_DEBUG (("switch to configuration mode (back to console)"));
574 // remember old values and switch to text mode
575 save_vga_mode = vga_getcurrentmode();
576 vga_getpalvec(0, 256, save_vga_pal);
577 keyboard_close();
578 vga_setmode(TEXT);
579 break;
580 case DISP_MODE_SIM:
581 BX_DEBUG (("switch to simulation mode (fullscreen)"));
582 keyboard_init();
583 keyboard_seteventhandler((__keyboard_handler) keyboard_handler);
584 vga_setmode(save_vga_mode);
585 vga_setpalvec(0, 256, save_vga_pal);
586 break;
590 #endif /* if BX_WITH_SVGA */