diff options
Diffstat (limited to 'tools/ioemu/gui/svga.cc')
-rw-r--r-- | tools/ioemu/gui/svga.cc | 514 |
1 files changed, 514 insertions, 0 deletions
diff --git a/tools/ioemu/gui/svga.cc b/tools/ioemu/gui/svga.cc new file mode 100644 index 0000000000..33020fca80 --- /dev/null +++ b/tools/ioemu/gui/svga.cc @@ -0,0 +1,514 @@ +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +#define _MULTI_THREAD + +// Define BX_PLUGGABLE in files that can be compiled into plugins. For +// platforms that require a special tag on exported symbols, BX_PLUGGABLE +// is used to know when we are exporting symbols and when we are importing. +#define BX_PLUGGABLE + +#include "bochs.h" +#if BX_WITH_SVGA + +#include <stdlib.h> +#include </usr/include/vga.h> +#include <vgagl.h> +#include <vgakeyboard.h> +#include <vgamouse.h> + +#include "font/vga.bitmap.h" +//#include "icon_bochs.h" + +class bx_svga_gui_c : public bx_gui_c { +public: + bx_svga_gui_c (void); + DECLARE_GUI_VIRTUAL_METHODS() + virtual void set_display_mode (disp_mode_t newmode); +}; + +// declare one instance of the gui object and call macro to insert the +// plugin code +static bx_svga_gui_c *theGui = NULL; + +IMPLEMENT_GUI_PLUGIN_CODE(svga) + +#define LOG_THIS theGui-> + +static unsigned res_x, res_y; +static int fontwidth = 8, fontheight = 16; +static unsigned tilewidth, tileheight; +static unsigned char vgafont[256 * 16]; +static int clut8 = 0; +GraphicsContext *screen = NULL; +static int save_vga_mode; +static int save_vga_pal[256 * 3]; + +void keyboard_handler(int scancode, int press); +void mouse_handler(int button, int dx, int dy, int dz, + int drx, int dry, int drz); + +unsigned char reverse_byteorder(unsigned char b) +{ + unsigned char ret = 0; + + for (unsigned i=0;i<8;i++){ + ret |= (b & 0x01) << (7 - i); + b >>= 1; + } + return ret; +} + +void create_vga_font() +{ + memcpy(vgafont, bx_vgafont, sizeof(bx_vgafont)); + + for (unsigned i=0;i< sizeof(bx_vgafont);i++) { + vgafont[i] = reverse_byteorder(vgafont[i]); + } +} + +bx_svga_gui_c::bx_svga_gui_c () +{ + put("SVGA"); +} + +void bx_svga_gui_c::specific_init( + int argc, + char **argv, + unsigned x_tilesize, + unsigned y_tilesize, + unsigned header_bar_y) +{ + tilewidth = x_tilesize; + tileheight = y_tilesize; + + if(vga_init() != 0 ) + { + LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL); + BX_PANIC (("Unable to initialize SVGAlib")); + return; + } + + screen = gl_allocatecontext(); + + dimension_update(640,400); + create_vga_font(); + gl_setfont(8, 16, (void *)vgafont); + gl_setwritemode(FONT_COMPRESSED); + + keyboard_init(); + keyboard_seteventhandler((__keyboard_handler) keyboard_handler); + + vga_setmousesupport(1); + mouse_seteventhandler((__mouse_handler) mouse_handler); + if (vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_FLAGS) & VGA_CLUT8) { + vga_ext_set(VGA_EXT_SET, VGA_CLUT8); + clut8 = 1; + } + // Save settings to prepare for mode transition in set_display_mode. + // If DISP_MODE_SIM is called first, these values will be used. + save_vga_mode = vga_getcurrentmode(); + vga_getpalvec(0, 256, save_vga_pal); +} + +void bx_svga_gui_c::text_update( + Bit8u *old_text, + Bit8u *new_text, + unsigned long cursor_x, + unsigned long cursor_y, + bx_vga_tminfo_t tm_info, + unsigned rows) +{ + unsigned x, y, i; + unsigned chars, cols; + char s[] = " "; + static unsigned int previ; + unsigned int cursori; + + cols = res_x/fontwidth; + + cursori = (cursor_y*cols + cursor_x) * 2; + + chars = cols*rows; + + for (i=0; i<chars*2; i+=2) { + if (i == cursori || i == previ || old_text[i] != new_text[i] || + old_text[i+1] != new_text[i+1]) { + + s[0] = new_text[i]; + x = (i/2) % cols; + y = (i/2) / cols; + + if (i == cursori) { + gl_setfontcolors(new_text[i+1] & 0x0F, (new_text[i+1] & 0xF0) >> 4); + } else { + gl_setfontcolors((new_text[i+1] & 0xF0) >> 4, new_text[i+1] & 0x0F); + } + gl_write(x * fontwidth, y * fontheight, s); + } + } + previ = cursori; +} + + int +bx_svga_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes) +{ + return 0; +} + + int +bx_svga_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len) +{ + return 0; +} + + +void bx_svga_gui_c::graphics_tile_update( + Bit8u *snapshot, + unsigned x, + unsigned y) +{ + gl_putbox(x, y, tilewidth, tileheight, snapshot); +} + +static Bit32u vga_to_bx_key(int key) +{ + switch (key) { + case SCANCODE_ESCAPE: return BX_KEY_ESC; + case SCANCODE_1: return BX_KEY_1; + case SCANCODE_2: return BX_KEY_2; + case SCANCODE_3: return BX_KEY_3; + case SCANCODE_4: return BX_KEY_4; + case SCANCODE_5: return BX_KEY_5; + case SCANCODE_6: return BX_KEY_6; + case SCANCODE_7: return BX_KEY_7; + case SCANCODE_8: return BX_KEY_8; + case SCANCODE_9: return BX_KEY_9; + case SCANCODE_0: return BX_KEY_0; + + case SCANCODE_MINUS: return BX_KEY_MINUS; + case SCANCODE_EQUAL: return BX_KEY_EQUALS; + case SCANCODE_TAB: return BX_KEY_TAB; + case SCANCODE_BACKSPACE: return BX_KEY_BACKSPACE; + + case SCANCODE_Q: return BX_KEY_Q; + case SCANCODE_W: return BX_KEY_W; + case SCANCODE_E: return BX_KEY_E; + case SCANCODE_R: return BX_KEY_R; + case SCANCODE_T: return BX_KEY_T; + case SCANCODE_Y: return BX_KEY_Y; + case SCANCODE_U: return BX_KEY_U; + case SCANCODE_I: return BX_KEY_I; + case SCANCODE_O: return BX_KEY_O; + case SCANCODE_P: return BX_KEY_P; + + case SCANCODE_BRACKET_LEFT: return BX_KEY_LEFT_BRACKET; + case SCANCODE_BRACKET_RIGHT: return BX_KEY_RIGHT_BRACKET; + + case SCANCODE_ENTER: return BX_KEY_ENTER; + case SCANCODE_LEFTCONTROL: return BX_KEY_CTRL_L; + + case SCANCODE_A: return BX_KEY_A; + case SCANCODE_S: return BX_KEY_S; + case SCANCODE_D: return BX_KEY_D; + case SCANCODE_F: return BX_KEY_F; + case SCANCODE_G: return BX_KEY_G; + case SCANCODE_H: return BX_KEY_H; + case SCANCODE_J: return BX_KEY_J; + case SCANCODE_K: return BX_KEY_K; + case SCANCODE_L: return BX_KEY_L; + + case SCANCODE_SEMICOLON: return BX_KEY_SEMICOLON; + case SCANCODE_APOSTROPHE: return BX_KEY_SINGLE_QUOTE; + case SCANCODE_GRAVE: return BX_KEY_GRAVE; + + case SCANCODE_LEFTSHIFT: return BX_KEY_SHIFT_L; + case SCANCODE_BACKSLASH: return BX_KEY_BACKSLASH; + + case SCANCODE_Z: return BX_KEY_Z; + case SCANCODE_X: return BX_KEY_X; + case SCANCODE_C: return BX_KEY_C; + case SCANCODE_V: return BX_KEY_V; + case SCANCODE_B: return BX_KEY_B; + case SCANCODE_N: return BX_KEY_N; + case SCANCODE_M: return BX_KEY_M; + + case SCANCODE_COMMA: return BX_KEY_COMMA; + case SCANCODE_PERIOD: return BX_KEY_PERIOD; + case SCANCODE_SLASH: return BX_KEY_SLASH; + + case SCANCODE_RIGHTSHIFT: return BX_KEY_SHIFT_R; + case SCANCODE_KEYPADMULTIPLY: return BX_KEY_KP_MULTIPLY; + + case SCANCODE_LEFTALT: return BX_KEY_ALT_L; + case SCANCODE_SPACE: return BX_KEY_SPACE; + case SCANCODE_CAPSLOCK: return BX_KEY_CAPS_LOCK; + + case SCANCODE_F1: return BX_KEY_F1; + case SCANCODE_F2: return BX_KEY_F2; + case SCANCODE_F3: return BX_KEY_F3; + case SCANCODE_F4: return BX_KEY_F4; + case SCANCODE_F5: return BX_KEY_F5; + case SCANCODE_F6: return BX_KEY_F6; + case SCANCODE_F7: return BX_KEY_F7; + case SCANCODE_F8: return BX_KEY_F8; + case SCANCODE_F9: return BX_KEY_F9; + case SCANCODE_F10: return BX_KEY_F10; + + case SCANCODE_NUMLOCK: return BX_KEY_NUM_LOCK; + case SCANCODE_SCROLLLOCK: return BX_KEY_SCRL_LOCK; + + case SCANCODE_KEYPAD7: return BX_KEY_KP_HOME; + case SCANCODE_KEYPAD8: return BX_KEY_KP_UP; + case SCANCODE_KEYPAD9: return BX_KEY_KP_PAGE_UP; + case SCANCODE_KEYPADMINUS: return BX_KEY_KP_SUBTRACT; + case SCANCODE_KEYPAD4: return BX_KEY_KP_LEFT; + case SCANCODE_KEYPAD5: return BX_KEY_KP_5; + case SCANCODE_KEYPAD6: return BX_KEY_KP_RIGHT; + case SCANCODE_KEYPADPLUS: return BX_KEY_KP_ADD; + case SCANCODE_KEYPAD1: return BX_KEY_KP_END; + case SCANCODE_KEYPAD2: return BX_KEY_KP_DOWN; + case SCANCODE_KEYPAD3: return BX_KEY_KP_PAGE_DOWN; + case SCANCODE_KEYPAD0: return BX_KEY_KP_INSERT; +// case SCANCODE_KEYPADPERIOD: return BX_KEY_KP_; /* ??? */ + +// case SCANCODE_LESS: return BX_KEY_KP_LESS; /* ??? */ + + case SCANCODE_F11: return BX_KEY_F11; + case SCANCODE_F12: return BX_KEY_F12; + + case SCANCODE_KEYPADENTER: return BX_KEY_KP_ENTER; + case SCANCODE_RIGHTCONTROL: return BX_KEY_CTRL_R; + case SCANCODE_KEYPADDIVIDE: return BX_KEY_KP_DIVIDE; + case SCANCODE_PRINTSCREEN: return BX_KEY_PRINT; + case SCANCODE_RIGHTALT: return BX_KEY_ALT_R; + case SCANCODE_BREAK: return BX_KEY_PAUSE; + + case SCANCODE_HOME: return BX_KEY_HOME; + case SCANCODE_CURSORBLOCKUP: return BX_KEY_UP; + case SCANCODE_PAGEUP: return BX_KEY_PAGE_UP; + case SCANCODE_CURSORBLOCKLEFT: return BX_KEY_LEFT; + case SCANCODE_CURSORBLOCKRIGHT: return BX_KEY_RIGHT; + case SCANCODE_END: return BX_KEY_END; + case SCANCODE_CURSORBLOCKDOWN: return BX_KEY_DOWN; + case SCANCODE_PAGEDOWN: return BX_KEY_PAGE_DOWN; + case SCANCODE_INSERT: return BX_KEY_INSERT; + case SCANCODE_REMOVE: return BX_KEY_DELETE; + + case SCANCODE_RIGHTWIN: return BX_KEY_WIN_R; + case SCANCODE_LEFTWIN: return BX_KEY_WIN_L; + + default: return 0; + } +} + +void keyboard_handler(int scancode, int press) +{ + if (scancode != SCANCODE_F12) { + int bx_key = vga_to_bx_key(scancode); + Bit32u key_state; + + if (press) { + key_state = BX_KEY_PRESSED; + } else { + key_state = BX_KEY_RELEASED; + } + + DEV_kbd_gen_scancode(bx_key | key_state); + } else { + BX_INFO(("F12 pressed")); + // show runtime options menu, which uses stdin/stdout + SIM->configuration_interface (NULL, CI_RUNTIME_CONFIG); + } +} + +void mouse_handler(int button, int dx, int dy, int dz, + int drx, int dry, int drz) +{ + int buttons = 0; + + if (button & MOUSE_LEFTBUTTON) { + buttons |= 0x01; + } + + if (button & MOUSE_RIGHTBUTTON) { + buttons |= 0x02; + } + DEV_mouse_motion((int) (0.25 * dx), (int) -(0.25 * dy), buttons); +} + +void bx_svga_gui_c::handle_events(void) +{ + keyboard_update(); + keyboard_clearstate(); + mouse_update(); +} + +void bx_svga_gui_c::flush(void) +{ + gl_copyscreen(screen); +} + +void bx_svga_gui_c::clear_screen(void) +{ + gl_clearscreen(0); +} + +bx_bool bx_svga_gui_c::palette_change( + unsigned index, + unsigned red, + unsigned green, + unsigned blue) +{ + if( index > 255 ) return 0; + + // without VGA_CLUT8 extension we have only 6 bits for each r,g,b value + if (!clut8 && (red > 63 || green > 63 || blue > 63)) { + red = red >> 2; + green = green >> 2; + blue = blue >> 2; + } + + vga_setpalette(index, red, green, blue); + + return 1; +} + + +void bx_svga_gui_c::dimension_update( + unsigned x, + unsigned y, + unsigned fheight, + unsigned fwidth, + unsigned bpp) +{ + int newmode = 0; + + if (bpp > 8) { + BX_PANIC(("%d bpp graphics mode not supported yet", bpp)); + } + if( fheight > 0 ) + { + fontheight = fheight; + if (fwidth != 8) { + x = x * 8 / fwidth; + } + fontwidth = 8; + } + + if( (x == res_x) && (y == res_y )) return; + + if (x == 640 && y == 480) { + newmode = G640x480x256; + } else if (x == 640 && y == 400) { + newmode = G640x400x256; + } else if (x == 320 && y == 200) { + newmode = G320x200x256; + } + + if (!vga_hasmode(newmode)) { + newmode = G640x480x256; // trying "default" mode... + } + + if (vga_setmode(newmode) != 0) + { + LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL); + BX_PANIC (("Unable to set requested videomode: %ix%i", x, y)); + } + + gl_setcontextvga(newmode); + gl_getcontext(screen); + gl_setcontextvgavirtual(newmode); + save_vga_mode = newmode; + + res_x = x; + res_y = y; +} + + +unsigned bx_svga_gui_c::create_bitmap( + const unsigned char *bmap, + unsigned xdim, + unsigned ydim) +{ + return 0; +} + + +unsigned bx_svga_gui_c::headerbar_bitmap( + unsigned bmap_id, + unsigned alignment, + void (*f)(void)) +{ + return 0; +} + + +void bx_svga_gui_c::replace_bitmap( + unsigned hbar_id, + unsigned bmap_id) +{ +} + + +void bx_svga_gui_c::show_headerbar(void) +{ +} + + +void bx_svga_gui_c::mouse_enabled_changed_specific (bx_bool val) +{ +} + + +void headerbar_click(int x) +{ +} + +void bx_svga_gui_c::exit(void) +{ + vga_setmode(TEXT); + keyboard_close(); + mouse_close(); +} + +void +bx_svga_gui_c::set_display_mode (disp_mode_t newmode) +{ + // if no mode change, do nothing. + if (disp_mode == newmode) return; + // remember the display mode for next time + disp_mode = newmode; + switch (newmode) { + case DISP_MODE_CONFIG: + BX_DEBUG (("switch to configuration mode (back to console)")); + // remember old values and switch to text mode + save_vga_mode = vga_getcurrentmode(); + vga_getpalvec(0, 256, save_vga_pal); + keyboard_close(); + vga_setmode(TEXT); + break; + case DISP_MODE_SIM: + BX_DEBUG (("switch to simulation mode (fullscreen)")); + keyboard_init(); + keyboard_seteventhandler((__keyboard_handler) keyboard_handler); + vga_setmode(save_vga_mode); + vga_setpalvec(0, 256, save_vga_pal); + break; + } +} + +#endif /* if BX_WITH_SVGA */ |