- added instructions how to update the online documentation
[bochs-mirror.git] / gui / sdl.cc
blob3dce468c518874f3be50b89d62117176047f94ea
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: sdl.cc,v 1.77 2008/10/15 15:26:15 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2002 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 /////////////////////////////////////////////////////////////////////////
28 #define _MULTI_THREAD
30 // Define BX_PLUGGABLE in files that can be compiled into plugins. For
31 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
32 // is used to know when we are exporting symbols and when we are importing.
33 #define BX_PLUGGABLE
35 #include "bochs.h"
36 #include "iodev.h"
37 #if BX_WITH_SDL
39 #include <stdlib.h>
40 #include <SDL.h>
41 #include <SDL_endian.h>
42 #include <SDL_thread.h>
44 #include "icon_bochs.h"
45 #include "sdl.h"
46 #ifdef WIN32
47 #include "win32dialog.h"
48 #endif
50 class bx_sdl_gui_c : public bx_gui_c {
51 public:
52 bx_sdl_gui_c(void);
53 DECLARE_GUI_VIRTUAL_METHODS()
54 DECLARE_GUI_NEW_VIRTUAL_METHODS()
55 virtual void set_display_mode(disp_mode_t newmode);
56 virtual void statusbar_setitem(int element, bx_bool active, bx_bool w = 0);
57 #if BX_SHOW_IPS
58 virtual void show_ips(Bit32u ips_count);
59 #endif
62 void sdl_set_status_text(int element, const char *text, bx_bool active, bx_bool w = 0);
64 // declare one instance of the gui object and call macro to insert the
65 // plugin code
66 static bx_sdl_gui_c *theGui = NULL;
67 IMPLEMENT_GUI_PLUGIN_CODE(sdl)
69 #define LOG_THIS theGui->
71 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
72 const Uint32 status_led_green = 0x00ff0000;
73 const Uint32 status_gray_text = 0x80808000;
74 const Uint32 status_led_red = 0x0040ff00;
75 #else
76 const Uint32 status_led_green = 0x0000ff00;
77 const Uint32 status_gray_text = 0x00808080;
78 const Uint32 status_led_red = 0x00ff4000;
79 #endif
81 static unsigned prev_cursor_x=0;
82 static unsigned prev_cursor_y=0;
83 static Bit32u convertStringToSDLKey (const char *string);
85 #define MAX_SDL_BITMAPS 32
86 struct bitmaps {
87 SDL_Surface *surface;
88 SDL_Rect src,dst;
89 void (*cb)(void);
92 static struct {
93 unsigned bmp_id;
94 unsigned alignment;
95 void (*f)(void);
96 } hb_entry[BX_MAX_HEADERBAR_ENTRIES];
98 unsigned bx_headerbar_entries = 0;
100 SDL_Thread *sdl_thread;
101 SDL_Surface *sdl_screen, *sdl_fullscreen;
102 SDL_Event sdl_event;
103 int sdl_fullscreen_toggle;
104 int sdl_grab;
105 unsigned res_x, res_y;
106 unsigned half_res_x, half_res_y;
107 int headerbar_height;
108 static unsigned bx_bitmap_left_xorigin = 0; // pixels from left
109 static unsigned bx_bitmap_right_xorigin = 0; // pixels from right
110 static unsigned int text_rows = 25, text_cols = 80;
111 Bit8u h_panning = 0, v_panning = 0;
112 Bit16u line_compare = 1023;
113 int fontwidth = 8, fontheight = 16;
114 static unsigned vga_bpp=8;
115 unsigned tilewidth, tileheight;
116 unsigned char menufont[256][8];
117 Uint32 palette[256];
118 Uint32 headerbar_fg, headerbar_bg;
119 Bit8u old_mousebuttons=0, new_mousebuttons=0;
120 int old_mousex=0, new_mousex=0;
121 int old_mousey=0, new_mousey=0;
122 bx_bool just_warped = false;
123 bitmaps *sdl_bitmaps[MAX_SDL_BITMAPS];
124 int n_sdl_bitmaps = 0;
125 int statusbar_height = 18;
126 static unsigned statusitem_pos[12] = {
127 0, 170, 210, 250, 290, 330, 370, 410, 450, 490, 530, 570
129 static bx_bool statusitem_active[12];
130 #if BX_SHOW_IPS
131 static bx_bool sdl_ips_update = 0;
132 static char sdl_ips_text[20];
133 #endif
135 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
136 #define SWAP16(X) (X)
137 #define SWAP32(X) (X)
138 #else
139 #define SWAP16(X) SDL_Swap16(X)
140 #define SWAP32(X) SDL_Swap32(X)
141 #endif
143 static void headerbar_click(int x);
145 #if BX_SHOW_IPS
146 #if defined(__MINGW32__) || defined(_MSC_VER)
147 Uint32 SDLCALL sdlTimer(Uint32 interval);
148 void alarm(int);
149 void bx_signal_handler(int);
150 #endif
151 #endif
154 void switch_to_windowed(void)
156 SDL_Surface *tmp;
157 SDL_Rect src, dst;
158 src.x = 0; src.y = 0;
159 src.w = res_x; src.h = res_y;
160 dst.x = 0; dst.y = 0;
162 tmp = SDL_CreateRGBSurface(
163 SDL_SWSURFACE,
164 res_x,
165 res_y,
167 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
168 0xff000000,
169 0x00ff0000,
170 0x0000ff00,
171 0x000000ff
172 #else
173 0x000000ff,
174 0x0000ff00,
175 0x00ff0000,
176 0xff000000
177 #endif
180 SDL_BlitSurface(sdl_fullscreen,&src,tmp,&dst);
181 SDL_UpdateRect(tmp,0,0,res_x,res_y);
182 SDL_FreeSurface(sdl_fullscreen);
183 sdl_fullscreen = NULL;
185 sdl_screen = SDL_SetVideoMode(res_x,res_y+headerbar_height+statusbar_height,32, SDL_SWSURFACE);
186 dst.y = headerbar_height;
187 SDL_BlitSurface(tmp,&src,sdl_screen,&dst);
188 SDL_UpdateRect(tmp,0,0,res_x,res_y+headerbar_height+statusbar_height);
189 SDL_FreeSurface(tmp);
191 bx_gui->show_headerbar();
192 SDL_ShowCursor(1);
193 if (sdl_grab==1) {
194 SDL_WM_GrabInput(SDL_GRAB_OFF);
196 sdl_grab = 0;
197 bx_gui->toggle_mouse_enable();
199 bx_gui->flush();
202 void switch_to_fullscreen(void)
204 SDL_Surface *tmp;
205 SDL_Rect src, dst;
206 src.x = 0; src.y = headerbar_height;
207 src.w = res_x; src.h = res_y;
208 dst.x = 0; dst.y = 0;
210 tmp = SDL_CreateRGBSurface(
211 SDL_SWSURFACE,
212 res_x,
213 res_y,
215 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
216 0xff000000,
217 0x00ff0000,
218 0x0000ff00,
219 0x000000ff
220 #else
221 0x000000ff,
222 0x0000ff00,
223 0x00ff0000,
224 0xff000000
225 #endif
228 SDL_BlitSurface(sdl_screen,&src,tmp,&dst);
229 SDL_UpdateRect(tmp,0,0,res_x,res_y);
230 SDL_FreeSurface(sdl_screen);
231 sdl_screen = NULL;
233 sdl_fullscreen = SDL_SetVideoMode(res_x,res_y,32, SDL_HWSURFACE|SDL_FULLSCREEN);
234 src.y = 0;
235 SDL_BlitSurface(tmp,&src,sdl_fullscreen,&dst);
236 SDL_UpdateRect(tmp,0,0,res_x,res_y);
237 SDL_FreeSurface(tmp);
239 SDL_ShowCursor(0);
240 if (sdl_grab==0) {
241 SDL_WM_GrabInput(SDL_GRAB_ON);
242 sdl_grab = 1;
243 bx_gui->toggle_mouse_enable();
245 bx_gui->flush();
248 #if BX_SHOW_IPS
249 #if defined(__MINGW32__) || defined(_MSC_VER)
250 Uint32 SDLCALL sdlTimer(Uint32 interval)
252 bx_signal_handler(SIGALRM);
253 return interval;
256 void alarm(int time)
258 SDL_SetTimer(time*1000, sdlTimer);
260 #endif
261 #endif
263 bx_sdl_gui_c::bx_sdl_gui_c ()
267 #ifdef __MORPHOS__
268 void bx_sdl_morphos_exit(void)
270 SDL_Quit();
271 if (PowerSDLBase) CloseLibrary(PowerSDLBase);
273 #endif
275 void bx_sdl_gui_c::specific_init(int argc, char **argv,
276 unsigned x_tilesize,
277 unsigned y_tilesize,
278 unsigned header_bar_y)
280 int i,j;
281 Uint32 flags;
283 put("SDL");
285 UNUSED(bochs_icon_bits);
287 tilewidth = x_tilesize;
288 tileheight = y_tilesize;
289 headerbar_height = header_bar_y;
291 for(i=0;i<256;i++)
292 for(j=0;j<16;j++)
293 vga_charmap[i*32+j] = sdl_font8x16[i][j];
295 for(i=0;i<256;i++)
296 for(j=0;j<8;j++)
297 menufont[i][j] = sdl_font8x8[i][j];
299 #ifdef __MORPHOS__
300 if (!(PowerSDLBase=OpenLibrary("powersdl.library",0)))
302 LOG_THIS setonoff(LOGLEVEL_PANIC, ACT_FATAL);
303 BX_PANIC(("Unable to open SDL libraries"));
304 return;
306 #endif
308 flags = SDL_INIT_VIDEO;
309 #if BX_SHOW_IPS
310 #if defined(__MINGW32__) || defined(_MSC_VER)
311 flags |= SDL_INIT_TIMER;
312 #endif
313 #endif
314 if (SDL_Init(flags) < 0) {
315 LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
316 BX_PANIC(("Unable to initialize SDL libraries"));
317 return;
319 #ifdef __MORPHOS__
320 atexit(bx_sdl_morphos_exit);
321 #else
322 atexit(SDL_Quit);
323 #endif
325 sdl_screen = NULL;
326 sdl_fullscreen_toggle = 0;
327 dimension_update(640,480);
329 SDL_EnableKeyRepeat(250,50);
330 SDL_WM_SetCaption(BOCHS_WINDOW_NAME, "Bochs");
331 SDL_WarpMouse(half_res_x, half_res_y);
333 // load keymap for sdl
334 if (SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get()) {
335 bx_keymap.loadKeymap(convertStringToSDLKey);
338 // parse sdl specific options
339 if (argc > 1) {
340 for (i = 1; i < argc; i++) {
341 if (!strcmp(argv[i], "fullscreen")) {
342 sdl_fullscreen_toggle = 1;
343 switch_to_fullscreen();
344 } else {
345 BX_PANIC(("Unknown sdl option '%s'", argv[i]));
350 new_gfx_api = 1;
351 #ifdef WIN32
352 win32_init_notify_callback();
353 dialog_caps = BX_GUI_DLG_ALL;
354 #endif
357 void sdl_set_status_text(int element, const char *text, bx_bool active, bx_bool w)
359 Uint32 *buf, *buf_row;
360 Uint32 disp, fgcolor, bgcolor;
361 unsigned char *pfont_row, font_row;
362 int rowsleft = statusbar_height - 2;
363 int colsleft, textlen;
364 int x, xleft, xsize;
366 statusitem_active[element] = active;
367 if(!sdl_screen) return;
368 disp = sdl_screen->pitch/4;
369 xleft = statusitem_pos[element] + 2;
370 xsize = statusitem_pos[element+1] - xleft - 1;
371 buf = (Uint32 *)sdl_screen->pixels + (res_y + headerbar_height + 1) * disp + xleft;
372 rowsleft = statusbar_height - 2;
373 fgcolor = active?headerbar_fg:status_gray_text;
374 if (element > 0) {
375 bgcolor = active?(w?status_led_red:status_led_green):headerbar_bg;
376 } else {
377 bgcolor = headerbar_bg;
379 do {
380 colsleft = xsize;
381 buf_row = buf;
384 *buf++ = bgcolor;
385 } while(--colsleft);
386 buf = buf_row + disp;
387 } while(--rowsleft);
388 if ((element > 0) && (strlen(text) > 4)) {
389 textlen = 4;
390 } else {
391 textlen = strlen(text);
393 buf = (Uint32 *)sdl_screen->pixels + (res_y + headerbar_height + 5) * disp + xleft;
394 x = 0;
397 pfont_row = &menufont[(unsigned)text[x]][0];
398 buf_row = buf;
399 rowsleft = 8;
402 font_row = *pfont_row++;
403 colsleft = 8;
406 if((font_row & 0x80) != 0x00)
407 *buf++ = fgcolor;
408 else
409 buf++;
410 font_row <<= 1;
411 } while(--colsleft);
412 buf += (disp - 8);
413 } while(--rowsleft);
414 buf = buf_row + 8;
415 x++;
416 } while (--textlen);
417 SDL_UpdateRect(sdl_screen, xleft,res_y+headerbar_height+1,xsize,statusbar_height-2);
420 void bx_sdl_gui_c::statusbar_setitem(int element, bx_bool active, bx_bool w)
422 if (element < 0) {
423 for (unsigned i = 0; i < statusitem_count; i++) {
424 sdl_set_status_text(i+1, statusitem_text[i], active, w);
426 } else if ((unsigned)element < statusitem_count) {
427 sdl_set_status_text(element+1, statusitem_text[element], active, w);
431 void bx_sdl_gui_c::text_update(
432 Bit8u *old_text,
433 Bit8u *new_text,
434 unsigned long cursor_x,
435 unsigned long cursor_y,
436 bx_vga_tminfo_t tm_info)
438 Bit8u *pfont_row, *old_line, *new_line, *text_base;
439 unsigned int cs_y, i, x, y;
440 unsigned int curs, hchars, offset;
441 Bit8u fontline, fontpixels, fontrows;
442 int rows;
443 Uint32 fgcolor, bgcolor;
444 Uint32 *buf, *buf_row, *buf_char;
445 Uint32 disp;
446 Bit16u font_row, mask;
447 Bit8u cfstart, cfwidth, cfheight, split_fontrows, split_textrow;
448 bx_bool cursor_visible, gfxcharw9, invert, forceUpdate, split_screen;
449 bx_bool blink_mode, blink_state;
450 Uint32 text_palette[16];
452 forceUpdate = 0;
453 blink_mode = (tm_info.blink_flags & BX_TEXT_BLINK_MODE) > 0;
454 blink_state = (tm_info.blink_flags & BX_TEXT_BLINK_STATE) > 0;
455 if (blink_mode) {
456 if (tm_info.blink_flags & BX_TEXT_BLINK_TOGGLE)
457 forceUpdate = 1;
459 if (charmap_updated) {
460 forceUpdate = 1;
461 charmap_updated = 0;
463 for (i=0; i<16; i++) {
464 text_palette[i] = palette[DEV_vga_get_actl_pal_idx(i)];
466 if ((tm_info.h_panning != h_panning) || (tm_info.v_panning != v_panning)) {
467 forceUpdate = 1;
468 h_panning = tm_info.h_panning;
469 v_panning = tm_info.v_panning;
471 if (tm_info.line_compare != line_compare) {
472 forceUpdate = 1;
473 line_compare = tm_info.line_compare;
475 if (sdl_screen) {
476 disp = sdl_screen->pitch/4;
477 buf_row = (Uint32 *)sdl_screen->pixels + headerbar_height*disp;
478 } else {
479 disp = sdl_fullscreen->pitch/4;
480 buf_row = (Uint32 *)sdl_fullscreen->pixels;
482 // first invalidate character at previous and new cursor location
483 if ((prev_cursor_y < text_rows) && (prev_cursor_x < text_cols)) {
484 curs = prev_cursor_y * tm_info.line_offset + prev_cursor_x * 2;
485 old_text[curs] = ~new_text[curs];
487 cursor_visible = ((tm_info.cs_start <= tm_info.cs_end) && (tm_info.cs_start < fontheight));
488 if((cursor_visible) && (cursor_y < text_rows) && (cursor_x < text_cols)) {
489 curs = cursor_y * tm_info.line_offset + cursor_x * 2;
490 old_text[curs] = ~new_text[curs];
491 } else {
492 curs = 0xffff;
495 rows = text_rows;
496 if (v_panning) rows++;
497 y = 0;
498 cs_y = 0;
499 text_base = new_text - tm_info.start_address;
500 split_textrow = (line_compare + v_panning) / fontheight;
501 split_fontrows = ((line_compare + v_panning) % fontheight) + 1;
502 split_screen = 0;
506 buf = buf_row;
507 hchars = text_cols;
508 if (h_panning) hchars++;
509 cfheight = fontheight;
510 cfstart = 0;
511 if (split_screen)
513 if (rows == 1)
515 cfheight = (res_y - line_compare - 1) % fontheight;
516 if (cfheight == 0) cfheight = fontheight;
519 else if (v_panning)
521 if (y == 0)
523 cfheight -= v_panning;
524 cfstart = v_panning;
526 else if (rows == 1)
528 cfheight = v_panning;
531 if (!split_screen && (y == split_textrow))
533 if ((split_fontrows - cfstart) < cfheight)
535 cfheight = split_fontrows - cfstart;
538 new_line = new_text;
539 old_line = old_text;
540 x = 0;
541 offset = cs_y * tm_info.line_offset;
544 cfwidth = fontwidth;
545 if (h_panning)
547 if (hchars > text_cols)
549 cfwidth -= h_panning;
551 else if (hchars == 1)
553 cfwidth = h_panning;
556 // check if char needs to be updated
557 if(forceUpdate || (old_text[0] != new_text[0])
558 || (old_text[1] != new_text[1]))
561 // Get Foreground/Background pixel colors
562 fgcolor = text_palette[new_text[1] & 0x0F];
563 if (blink_mode) {
564 bgcolor = text_palette[(new_text[1] >> 4) & 0x07];
565 if (!blink_state && (new_text[1] & 0x80))
566 fgcolor = bgcolor;
567 } else {
568 bgcolor = text_palette[(new_text[1] >> 4) & 0x0F];
570 invert = ((offset == curs) && (cursor_visible));
571 gfxcharw9 = ((tm_info.line_graphics) && ((new_text[0] & 0xE0) == 0xC0));
573 // Display this one char
574 fontrows = cfheight;
575 fontline = cfstart;
576 if (y > 0)
578 pfont_row = &vga_charmap[(new_text[0] << 5)];
580 else
582 pfont_row = &vga_charmap[(new_text[0] << 5) + cfstart];
584 buf_char = buf;
587 font_row = *pfont_row++;
588 if (gfxcharw9)
590 font_row = (font_row << 1) | (font_row & 0x01);
592 else
594 font_row <<= 1;
596 if (hchars > text_cols)
598 font_row <<= h_panning;
600 fontpixels = cfwidth;
601 if ((invert) && (fontline >= tm_info.cs_start) && (fontline <= tm_info.cs_end))
602 mask = 0x100;
603 else
604 mask = 0x00;
607 if ((font_row & 0x100) == mask)
608 *buf = bgcolor;
609 else
610 *buf = fgcolor;
611 buf++;
612 font_row <<= 1;
613 } while(--fontpixels);
614 buf -= cfwidth;
615 buf += disp;
616 fontline++;
617 } while(--fontrows);
619 // restore output buffer ptr to start of this char
620 buf = buf_char;
622 // move to next char location on screen
623 buf += cfwidth;
625 // select next char in old/new text
626 new_text+=2;
627 old_text+=2;
628 offset+=2;
629 x++;
631 // process one entire horizontal row
632 } while(--hchars);
634 // go to next character row location
635 buf_row += disp * cfheight;
636 if (!split_screen && (y == split_textrow))
638 new_text = text_base;
639 forceUpdate = 1;
640 cs_y = 0;
641 if (tm_info.split_hpanning) h_panning = 0;
642 rows = ((res_y - line_compare + fontheight - 2) / fontheight) + 1;
643 split_screen = 1;
645 else
647 new_text = new_line + tm_info.line_offset;
648 old_text = old_line + tm_info.line_offset;
649 cs_y++;
650 y++;
652 } while(--rows);
653 h_panning = tm_info.h_panning;
654 prev_cursor_x = cursor_x;
655 prev_cursor_y = cursor_y;
658 int bx_sdl_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes)
660 return 0;
663 int bx_sdl_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len)
665 return 0;
668 void bx_sdl_gui_c::graphics_tile_update(Bit8u *snapshot, unsigned x, unsigned y)
670 Uint32 *buf, disp;
671 Uint32 *buf_row;
672 int i,j;
674 if(sdl_screen)
676 disp = sdl_screen->pitch/4;
677 buf = (Uint32 *)sdl_screen->pixels + (headerbar_height+y)*disp + x;
679 else
681 disp = sdl_fullscreen->pitch/4;
682 buf = (Uint32 *)sdl_fullscreen->pixels + y*disp + x;
685 i = tileheight;
686 if(i + y > res_y) i = res_y - y;
688 // FIXME
689 if(i<=0) return;
691 switch (vga_bpp)
693 case 8: /* 8 bpp */
696 buf_row = buf;
697 j = tilewidth;
700 *buf++ = palette[*snapshot++];
701 } while(--j);
702 buf = buf_row + disp;
703 } while(--i);
704 break;
705 default:
706 BX_PANIC(("%u bpp modes handled by new graphics API", vga_bpp));
707 return;
711 bx_svga_tileinfo_t *bx_sdl_gui_c::graphics_tile_info(bx_svga_tileinfo_t *info)
713 if (!info) {
714 info = (bx_svga_tileinfo_t *)malloc(sizeof(bx_svga_tileinfo_t));
715 if (!info) {
716 return NULL;
720 if (sdl_screen) {
721 info->bpp = sdl_screen->format->BitsPerPixel;
722 info->pitch = sdl_screen->pitch;
723 info->red_shift = sdl_screen->format->Rshift + 8 - sdl_screen->format->Rloss;
724 info->green_shift = sdl_screen->format->Gshift + 8 - sdl_screen->format->Gloss;
725 info->blue_shift = sdl_screen->format->Bshift + 8 - sdl_screen->format->Bloss;
726 info->red_mask = sdl_screen->format->Rmask;
727 info->green_mask = sdl_screen->format->Gmask;
728 info->blue_mask = sdl_screen->format->Bmask;
729 info->is_indexed = (sdl_screen->format->palette != NULL);
731 else {
732 info->bpp = sdl_fullscreen->format->BitsPerPixel;
733 info->pitch = sdl_fullscreen->pitch;
734 info->red_shift = sdl_fullscreen->format->Rshift + 8 - sdl_fullscreen->format->Rloss;
735 info->green_shift = sdl_fullscreen->format->Gshift + 8 - sdl_fullscreen->format->Gloss;
736 info->blue_shift = sdl_fullscreen->format->Bshift + 8 - sdl_fullscreen->format->Bloss;
737 info->red_mask = sdl_fullscreen->format->Rmask;
738 info->green_mask = sdl_fullscreen->format->Gmask;
739 info->blue_mask = sdl_fullscreen->format->Bmask;
740 info->is_indexed = (sdl_fullscreen->format->palette != NULL);
743 #ifdef BX_LITTLE_ENDIAN
744 info->is_little_endian = 1;
745 #else
746 info->is_little_endian = 0;
747 #endif
749 return info;
752 Bit8u *bx_sdl_gui_c::graphics_tile_get(unsigned x0, unsigned y0,
753 unsigned *w, unsigned *h)
755 if (x0+tilewidth > res_x) {
756 *w = res_x - x0;
758 else {
759 *w = tilewidth;
762 if (y0+tileheight > res_y) {
763 *h = res_y - y0;
765 else {
766 *h = tileheight;
769 if (sdl_screen) {
770 return (Bit8u *)sdl_screen->pixels +
771 sdl_screen->pitch*(headerbar_height+y0) +
772 sdl_screen->format->BytesPerPixel*x0;
774 else {
775 return (Bit8u *)sdl_fullscreen->pixels +
776 sdl_fullscreen->pitch*(y0) +
777 sdl_fullscreen->format->BytesPerPixel*x0;
781 void bx_sdl_gui_c::graphics_tile_update_in_place(unsigned x0, unsigned y0,
782 unsigned w, unsigned h)
786 static Bit32u sdl_sym_to_bx_key (SDLKey sym)
788 switch (sym)
790 // case SDLK_UNKNOWN: return BX_KEY_UNKNOWN;
791 // case SDLK_FIRST: return BX_KEY_FIRST;
792 case SDLK_BACKSPACE: return BX_KEY_BACKSPACE;
793 case SDLK_TAB: return BX_KEY_TAB;
794 // case SDLK_CLEAR: return BX_KEY_CLEAR;
795 case SDLK_RETURN: return BX_KEY_ENTER;
796 case SDLK_PAUSE: return BX_KEY_PAUSE;
797 case SDLK_ESCAPE: return BX_KEY_ESC;
798 case SDLK_SPACE: return BX_KEY_SPACE;
799 // case SDLK_EXCLAIM: return BX_KEY_EXCLAIM;
800 // case SDLK_QUOTEDBL: return BX_KEY_QUOTEDBL;
801 // case SDLK_HASH: return BX_KEY_HASH;
802 // case SDLK_DOLLAR: return BX_KEY_DOLLAR;
803 // case SDLK_AMPERSAND: return BX_KEY_AMPERSAND;
804 case SDLK_QUOTE: return BX_KEY_SINGLE_QUOTE;
805 // case SDLK_LEFTPAREN: return BX_KEY_LEFTPAREN;
806 // case SDLK_RIGHTPAREN: return BX_KEY_RIGHTPAREN;
807 // case SDLK_ASTERISK: return BX_KEY_ASTERISK;
808 // case SDLK_PLUS: return BX_KEY_PLUS;
809 case SDLK_COMMA: return BX_KEY_COMMA;
810 case SDLK_MINUS: return BX_KEY_MINUS;
811 case SDLK_PERIOD: return BX_KEY_PERIOD;
812 case SDLK_SLASH: return BX_KEY_SLASH;
813 case SDLK_0: return BX_KEY_0;
814 case SDLK_1: return BX_KEY_1;
815 case SDLK_2: return BX_KEY_2;
816 case SDLK_3: return BX_KEY_3;
817 case SDLK_4: return BX_KEY_4;
818 case SDLK_5: return BX_KEY_5;
819 case SDLK_6: return BX_KEY_6;
820 case SDLK_7: return BX_KEY_7;
821 case SDLK_8: return BX_KEY_8;
822 case SDLK_9: return BX_KEY_9;
823 // case SDLK_COLON: return BX_KEY_COLON;
824 case SDLK_SEMICOLON: return BX_KEY_SEMICOLON;
825 // case SDLK_LESS: return BX_KEY_LESS;
826 case SDLK_EQUALS: return BX_KEY_EQUALS;
827 // case SDLK_GREATER: return BX_KEY_GREATER;
828 // case SDLK_QUESTION: return BX_KEY_QUESTION;
829 // case SDLK_AT: return BX_KEY_AT;
831 Skip uppercase letters
833 case SDLK_LEFTBRACKET: return BX_KEY_LEFT_BRACKET;
834 case SDLK_BACKSLASH: return BX_KEY_BACKSLASH;
835 case SDLK_RIGHTBRACKET: return BX_KEY_RIGHT_BRACKET;
836 // case SDLK_CARET: return BX_KEY_CARET;
837 // case SDLK_UNDERSCORE: return BX_KEY_UNDERSCORE;
838 case SDLK_BACKQUOTE: return BX_KEY_GRAVE;
839 case SDLK_a: return BX_KEY_A;
840 case SDLK_b: return BX_KEY_B;
841 case SDLK_c: return BX_KEY_C;
842 case SDLK_d: return BX_KEY_D;
843 case SDLK_e: return BX_KEY_E;
844 case SDLK_f: return BX_KEY_F;
845 case SDLK_g: return BX_KEY_G;
846 case SDLK_h: return BX_KEY_H;
847 case SDLK_i: return BX_KEY_I;
848 case SDLK_j: return BX_KEY_J;
849 case SDLK_k: return BX_KEY_K;
850 case SDLK_l: return BX_KEY_L;
851 case SDLK_m: return BX_KEY_M;
852 case SDLK_n: return BX_KEY_N;
853 case SDLK_o: return BX_KEY_O;
854 case SDLK_p: return BX_KEY_P;
855 case SDLK_q: return BX_KEY_Q;
856 case SDLK_r: return BX_KEY_R;
857 case SDLK_s: return BX_KEY_S;
858 case SDLK_t: return BX_KEY_T;
859 case SDLK_u: return BX_KEY_U;
860 case SDLK_v: return BX_KEY_V;
861 case SDLK_w: return BX_KEY_W;
862 case SDLK_x: return BX_KEY_X;
863 case SDLK_y: return BX_KEY_Y;
864 case SDLK_z: return BX_KEY_Z;
865 case SDLK_DELETE: return BX_KEY_DELETE;
866 /* End of ASCII mapped keysyms */
868 /* Numeric keypad */
869 case SDLK_KP0: return BX_KEY_KP_INSERT;
870 case SDLK_KP1: return BX_KEY_KP_END;
871 case SDLK_KP2: return BX_KEY_KP_DOWN;
872 case SDLK_KP3: return BX_KEY_KP_PAGE_DOWN;
873 case SDLK_KP4: return BX_KEY_KP_LEFT;
874 case SDLK_KP5: return BX_KEY_KP_5;
875 case SDLK_KP6: return BX_KEY_KP_RIGHT;
876 case SDLK_KP7: return BX_KEY_KP_HOME;
877 case SDLK_KP8: return BX_KEY_KP_UP;
878 case SDLK_KP9: return BX_KEY_KP_PAGE_UP;
879 case SDLK_KP_PERIOD: return BX_KEY_KP_DELETE;
880 case SDLK_KP_DIVIDE: return BX_KEY_KP_DIVIDE;
881 case SDLK_KP_MULTIPLY: return BX_KEY_KP_MULTIPLY;
882 case SDLK_KP_MINUS: return BX_KEY_KP_SUBTRACT;
883 case SDLK_KP_PLUS: return BX_KEY_KP_ADD;
884 case SDLK_KP_ENTER: return BX_KEY_KP_ENTER;
885 // case SDLK_KP_EQUALS: return BX_KEY_KP_EQUALS;
887 /* Arrows + Home/End pad */
888 case SDLK_UP: return BX_KEY_UP;
889 case SDLK_DOWN: return BX_KEY_DOWN;
890 case SDLK_RIGHT: return BX_KEY_RIGHT;
891 case SDLK_LEFT: return BX_KEY_LEFT;
892 case SDLK_INSERT: return BX_KEY_INSERT;
893 case SDLK_HOME: return BX_KEY_HOME;
894 case SDLK_END: return BX_KEY_END;
895 case SDLK_PAGEUP: return BX_KEY_PAGE_UP;
896 case SDLK_PAGEDOWN: return BX_KEY_PAGE_DOWN;
898 /* Function keys */
899 case SDLK_F1: return BX_KEY_F1;
900 case SDLK_F2: return BX_KEY_F2;
901 case SDLK_F3: return BX_KEY_F3;
902 case SDLK_F4: return BX_KEY_F4;
903 case SDLK_F5: return BX_KEY_F5;
904 case SDLK_F6: return BX_KEY_F6;
905 case SDLK_F7: return BX_KEY_F7;
906 case SDLK_F8: return BX_KEY_F8;
907 case SDLK_F9: return BX_KEY_F9;
908 case SDLK_F10: return BX_KEY_F10;
909 case SDLK_F11: return BX_KEY_F11;
910 case SDLK_F12: return BX_KEY_F12;
911 // case SDLK_F13: return BX_KEY_F13;
912 // case SDLK_F14: return BX_KEY_F14;
913 // case SDLK_F15: return BX_KEY_F15;
915 /* Key state modifier keys */
916 case SDLK_NUMLOCK: return BX_KEY_NUM_LOCK;
917 case SDLK_CAPSLOCK: return BX_KEY_CAPS_LOCK;
918 case SDLK_SCROLLOCK: return BX_KEY_SCRL_LOCK;
919 case SDLK_RSHIFT: return BX_KEY_SHIFT_R;
920 case SDLK_LSHIFT: return BX_KEY_SHIFT_L;
921 case SDLK_RCTRL: return BX_KEY_CTRL_R;
922 case SDLK_LCTRL: return BX_KEY_CTRL_L;
923 case SDLK_RALT: return BX_KEY_ALT_R;
924 case SDLK_LALT: return BX_KEY_ALT_L;
925 case SDLK_RMETA: return BX_KEY_ALT_R;
926 case SDLK_LMETA: return BX_KEY_WIN_L;
927 case SDLK_LSUPER: return BX_KEY_WIN_L;
928 case SDLK_RSUPER: return BX_KEY_WIN_R;
929 // case SDLK_MODE: return BX_KEY_MODE;
930 // case SDLK_COMPOSE: return BX_KEY_COMPOSE;
932 /* Miscellaneous function keys */
933 case SDLK_PRINT: return BX_KEY_PRINT;
934 case SDLK_BREAK: return BX_KEY_PAUSE;
935 case SDLK_MENU: return BX_KEY_MENU;
936 #if 0
937 case SDLK_HELP: return BX_KEY_HELP;
938 case SDLK_SYSREQ: return BX_KEY_SYSREQ;
939 case SDLK_POWER: return BX_KEY_POWER;
940 case SDLK_EURO: return BX_KEY_EURO;
941 case SDLK_UNDO: return BX_KEY_UNDO;
942 #endif
943 default:
944 BX_ERROR(("sdl keysym %d not mapped", (int)sym));
945 return BX_KEY_UNHANDLED;
949 void bx_sdl_gui_c::handle_events(void)
951 Bit32u key_event;
952 Bit8u mouse_state;
953 int wheel_status;
955 while(SDL_PollEvent(&sdl_event))
957 wheel_status = 0;
958 switch(sdl_event.type)
960 case SDL_VIDEOEXPOSE:
961 if(sdl_fullscreen_toggle == 0)
962 SDL_UpdateRect(sdl_screen, 0,0, res_x, res_y+headerbar_height+statusbar_height);
963 else
964 SDL_UpdateRect(sdl_fullscreen, 0, headerbar_height, res_x, res_y);
965 break;
967 case SDL_MOUSEMOTION:
968 //fprintf (stderr, "mouse event to (%d,%d), relative (%d,%d)\n", (int)(sdl_event.motion.x), (int)(sdl_event.motion.y), (int)sdl_event.motion.xrel, (int)sdl_event.motion.yrel);
969 if (!sdl_grab) {
970 //fprintf (stderr, "ignore mouse event because sdl_grab is off\n");
971 break;
973 if (just_warped
974 && sdl_event.motion.x == half_res_x
975 && sdl_event.motion.y == half_res_y) {
976 // This event was generated as a side effect of the WarpMouse,
977 // and it must be ignored.
978 //fprintf (stderr, "ignore mouse event because it is a side effect of SDL_WarpMouse\n");
979 just_warped = false;
980 break;
982 //fprintf (stderr, "processing relative mouse event\n");
983 new_mousebuttons = ((sdl_event.motion.state & 0x01)|((sdl_event.motion.state>>1)&0x02)
984 |((sdl_event.motion.state<<1)&0x04));
985 DEV_mouse_motion_ext(
986 sdl_event.motion.xrel,
987 -sdl_event.motion.yrel,
988 wheel_status,
989 new_mousebuttons);
990 old_mousebuttons = new_mousebuttons;
991 old_mousex = (int)(sdl_event.motion.x);
992 old_mousey = (int)(sdl_event.motion.y);
993 //fprintf (stderr, "warping mouse to center\n");
994 SDL_WarpMouse(half_res_x, half_res_y);
995 just_warped = 1;
996 break;
998 case SDL_MOUSEBUTTONDOWN:
999 if((sdl_event.button.button == SDL_BUTTON_MIDDLE)
1000 && ((SDL_GetModState() & KMOD_CTRL) > 0)
1001 && (sdl_fullscreen_toggle == 0))
1003 if(sdl_grab == 0)
1005 SDL_ShowCursor(0);
1006 SDL_WM_GrabInput(SDL_GRAB_ON);
1008 else
1010 SDL_ShowCursor(1);
1011 SDL_WM_GrabInput(SDL_GRAB_OFF);
1013 sdl_grab = ~sdl_grab;
1014 toggle_mouse_enable();
1015 break;
1016 } else if (sdl_event.button.y < headerbar_height) {
1017 headerbar_click(sdl_event.button.x);
1018 break;
1020 #ifdef SDL_BUTTON_WHEELUP
1021 // get the wheel status
1022 if (sdl_event.button.button == SDL_BUTTON_WHEELUP) {
1023 wheel_status = 1;
1025 if (sdl_event.button.button == SDL_BUTTON_WHEELDOWN) {
1026 wheel_status = -1;
1028 #endif
1029 case SDL_MOUSEBUTTONUP:
1030 // figure out mouse state
1031 new_mousex = (int)(sdl_event.button.x);
1032 new_mousey = (int)(sdl_event.button.y);
1033 // SDL_GetMouseState() returns the state of all buttons
1034 mouse_state = SDL_GetMouseState(NULL, NULL);
1035 new_mousebuttons =
1036 (mouse_state & 0x01) |
1037 ((mouse_state>>1)&0x02) |
1038 ((mouse_state<<1)&0x04);
1039 // filter out middle button if not fullscreen
1040 if(sdl_fullscreen_toggle == 0)
1041 new_mousebuttons &= 0x07;
1042 // send motion information
1043 DEV_mouse_motion_ext(
1044 new_mousex - old_mousex,
1045 -(new_mousey - old_mousey),
1046 wheel_status,
1047 new_mousebuttons);
1048 // mark current state to diff with next packet
1049 old_mousebuttons = new_mousebuttons;
1050 old_mousex = new_mousex;
1051 old_mousey = new_mousey;
1052 break;
1054 case SDL_KEYDOWN:
1056 // Windows/Fullscreen toggle-check
1057 if(sdl_event.key.keysym.sym == SDLK_SCROLLOCK)
1059 // SDL_WM_ToggleFullScreen(sdl_screen);
1060 sdl_fullscreen_toggle = ~sdl_fullscreen_toggle;
1061 if(sdl_fullscreen_toggle == 0)
1062 switch_to_windowed();
1063 else
1064 switch_to_fullscreen();
1065 bx_gui->show_headerbar();
1066 bx_gui->flush();
1067 break;
1070 // convert sym->bochs code
1071 if (sdl_event.key.keysym.sym > SDLK_LAST) break;
1072 if (!SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get()) {
1073 key_event = sdl_sym_to_bx_key (sdl_event.key.keysym.sym);
1074 BX_DEBUG(("keypress scancode=%d, sym=%d, bx_key = %d", sdl_event.key.keysym.scancode, sdl_event.key.keysym.sym, key_event));
1075 } else {
1076 /* use mapping */
1077 BXKeyEntry *entry = bx_keymap.findHostKey (sdl_event.key.keysym.sym);
1078 if (!entry) {
1079 BX_ERROR(("host key %d (0x%x) not mapped!",
1080 (unsigned) sdl_event.key.keysym.sym,
1081 (unsigned) sdl_event.key.keysym.sym));
1082 break;
1084 key_event = entry->baseKey;
1086 if (key_event == BX_KEY_UNHANDLED) break;
1087 DEV_kbd_gen_scancode( key_event);
1088 if ((key_event == BX_KEY_NUM_LOCK) || (key_event == BX_KEY_CAPS_LOCK)) {
1089 DEV_kbd_gen_scancode(key_event | BX_KEY_RELEASED);
1091 break;
1093 case SDL_KEYUP:
1095 // filter out release of Windows/Fullscreen toggle and unsupported keys
1096 if ((sdl_event.key.keysym.sym != SDLK_SCROLLOCK)
1097 && (sdl_event.key.keysym.sym < SDLK_LAST))
1099 // convert sym->bochs code
1100 if (!SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get()) {
1101 key_event = sdl_sym_to_bx_key (sdl_event.key.keysym.sym);
1102 } else {
1103 /* use mapping */
1104 BXKeyEntry *entry = bx_keymap.findHostKey (sdl_event.key.keysym.sym);
1105 if (!entry) {
1106 BX_ERROR(("host key %d (0x%x) not mapped!",
1107 (unsigned) sdl_event.key.keysym.sym,
1108 (unsigned) sdl_event.key.keysym.sym));
1109 break;
1111 key_event = entry->baseKey;
1113 if (key_event == BX_KEY_UNHANDLED) break;
1114 if ((key_event == BX_KEY_NUM_LOCK) || (key_event == BX_KEY_CAPS_LOCK)) {
1115 DEV_kbd_gen_scancode(key_event);
1117 DEV_kbd_gen_scancode(key_event | BX_KEY_RELEASED);
1119 break;
1121 case SDL_QUIT:
1122 LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
1123 BX_PANIC(("User requested shutdown."));
1126 #if BX_SHOW_IPS
1127 if (sdl_ips_update) {
1128 sdl_ips_update = 0;
1129 sdl_set_status_text(0, sdl_ips_text, 1);
1131 #endif
1134 void bx_sdl_gui_c::flush(void)
1136 if(sdl_screen)
1137 SDL_UpdateRect(sdl_screen,0,0,res_x,res_y+headerbar_height);
1138 else
1139 SDL_UpdateRect(sdl_fullscreen,0,0,res_x,res_y);
1142 void bx_sdl_gui_c::clear_screen(void)
1144 int i = res_y, j;
1145 Uint32 color;
1146 Uint32 *buf, *buf_row;
1147 Uint32 disp;
1149 if(sdl_screen)
1151 color = SDL_MapRGB(sdl_screen->format, 0,0,0);
1152 disp = sdl_screen->pitch/4;
1153 buf = (Uint32 *)sdl_screen->pixels + headerbar_height*disp;
1155 else if(sdl_fullscreen)
1157 color = SDL_MapRGB(sdl_fullscreen->format, 0,0, 0);
1158 disp = sdl_fullscreen->pitch/4;
1159 buf = (Uint32 *)sdl_fullscreen->pixels;
1161 else return;
1165 buf_row = buf;
1166 j = res_x;
1167 while(j--) *buf++ = color;
1168 buf = buf_row + disp;
1169 } while(--i);
1171 if(sdl_screen)
1172 SDL_UpdateRect(sdl_screen,0,0,res_x,res_y+headerbar_height);
1173 else
1174 SDL_UpdateRect(sdl_fullscreen,0,0,res_x,res_y);
1177 bx_bool bx_sdl_gui_c::palette_change(unsigned index, unsigned red, unsigned green, unsigned blue)
1179 unsigned char palred = red & 0xFF;
1180 unsigned char palgreen = green & 0xFF;
1181 unsigned char palblue = blue & 0xFF;
1183 if(index > 255) return 0;
1185 if(sdl_screen)
1186 palette[index] = SDL_MapRGB(sdl_screen->format, palred, palgreen, palblue);
1187 else if(sdl_fullscreen)
1188 palette[index] = SDL_MapRGB(sdl_fullscreen->format, palred, palgreen, palblue);
1190 return 1;
1193 void bx_sdl_gui_c::dimension_update(
1194 unsigned x,
1195 unsigned y,
1196 unsigned fheight,
1197 unsigned fwidth,
1198 unsigned bpp)
1200 if ((bpp == 8) || (bpp == 15) || (bpp == 16) || (bpp == 24) || (bpp == 32)) {
1201 vga_bpp = bpp;
1203 else
1205 BX_PANIC(("%d bpp graphics mode not supported", bpp));
1207 if(fheight > 0)
1209 fontheight = fheight;
1210 fontwidth = fwidth;
1211 text_cols = x / fontwidth;
1212 text_rows = y / fontheight;
1215 if((x == res_x) && (y == res_y)) return;
1217 if(sdl_screen)
1219 SDL_FreeSurface(sdl_screen);
1220 sdl_screen = NULL;
1222 if(sdl_fullscreen)
1224 SDL_FreeSurface(sdl_fullscreen);
1225 sdl_fullscreen = NULL;
1228 if(sdl_fullscreen_toggle == 0)
1230 sdl_screen = SDL_SetVideoMode(x, y+headerbar_height+statusbar_height, 32, SDL_SWSURFACE);
1231 if(!sdl_screen)
1233 LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
1234 BX_PANIC(("Unable to set requested videomode: %ix%i: %s",x,y,SDL_GetError()));
1236 headerbar_fg = SDL_MapRGB(
1237 sdl_screen->format,
1238 BX_HEADERBAR_FG_RED,
1239 BX_HEADERBAR_FG_GREEN,
1240 BX_HEADERBAR_FG_BLUE);
1241 headerbar_bg = SDL_MapRGB(
1242 sdl_screen->format,
1243 BX_HEADERBAR_BG_RED,
1244 BX_HEADERBAR_BG_GREEN,
1245 BX_HEADERBAR_BG_BLUE);
1247 else
1249 sdl_fullscreen = SDL_SetVideoMode(x, y, 32, SDL_HWSURFACE|SDL_FULLSCREEN);
1250 if(!sdl_fullscreen)
1252 LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
1253 BX_PANIC(("Unable to set requested videomode: %ix%i: %s",x,y,SDL_GetError()));
1256 res_x = x;
1257 res_y = y;
1258 half_res_x = x/2;
1259 half_res_y = y/2;
1260 bx_gui->show_headerbar();
1263 unsigned bx_sdl_gui_c::create_bitmap(const unsigned char *bmap,
1264 unsigned xdim, unsigned ydim)
1266 bitmaps *tmp = new bitmaps;
1267 Uint32 *buf, *buf_row;
1268 Uint32 disp;
1269 unsigned char pixels;
1271 if (n_sdl_bitmaps >= MAX_SDL_BITMAPS) {
1272 BX_PANIC(("too many SDL bitmaps. To fix, increase MAX_SDL_BITMAPS"));
1273 return 0;
1276 tmp->surface = SDL_CreateRGBSurface(
1277 SDL_SWSURFACE,
1278 xdim,
1279 ydim,
1281 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1282 0xff000000,
1283 0x00ff0000,
1284 0x0000ff00,
1285 0x00000000
1286 #else
1287 0x000000ff,
1288 0x0000ff00,
1289 0x00ff0000,
1290 0x00000000
1291 #endif
1293 if(!tmp->surface)
1295 delete tmp;
1296 bx_gui->exit();
1297 LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
1298 BX_PANIC(("Unable to create requested bitmap"));
1300 tmp->src.w = xdim;
1301 tmp->src.h = ydim;
1302 tmp->src.x = 0;
1303 tmp->src.y = 0;
1304 tmp->dst.x = -1;
1305 tmp->dst.y = 0;
1306 tmp->dst.w = xdim;
1307 tmp->dst.h = ydim;
1308 tmp->cb = NULL;
1309 buf = (Uint32 *)tmp->surface->pixels;
1310 disp = tmp->surface->pitch/4;
1313 buf_row = buf;
1314 xdim = tmp->src.w / 8;
1317 pixels = *bmap++;
1318 for(unsigned i=0;i<8;i++)
1320 if((pixels & 0x01) == 0)
1321 *buf++ = headerbar_bg;
1322 else
1323 *buf++ = headerbar_fg;
1324 pixels = pixels >> 1;
1326 } while(--xdim);
1327 buf = buf_row + disp;
1328 } while(--ydim);
1329 SDL_UpdateRect(
1330 tmp->surface,
1331 0, 0,
1332 tmp->src.w,
1333 tmp->src.h);
1334 sdl_bitmaps[n_sdl_bitmaps] = tmp;
1335 return n_sdl_bitmaps++;
1338 unsigned bx_sdl_gui_c::headerbar_bitmap(
1339 unsigned bmap_id,
1340 unsigned alignment,
1341 void (*f)(void))
1343 unsigned hb_index;
1345 if(bmap_id >= (unsigned)n_sdl_bitmaps) return 0;
1347 if ((bx_headerbar_entries+1) > BX_MAX_HEADERBAR_ENTRIES)
1348 BX_PANIC(("too many headerbar entries, increase BX_MAX_HEADERBAR_ENTRIES"));
1350 bx_headerbar_entries++;
1351 hb_index = bx_headerbar_entries - 1;
1353 hb_entry[hb_index].bmp_id = bmap_id;
1354 hb_entry[hb_index].alignment = alignment;
1355 hb_entry[hb_index].f = f;
1356 if (alignment == BX_GRAVITY_LEFT) {
1357 sdl_bitmaps[bmap_id]->dst.x = bx_bitmap_left_xorigin;
1358 bx_bitmap_left_xorigin += sdl_bitmaps[bmap_id]->src.w;
1359 } else {
1360 bx_bitmap_right_xorigin += sdl_bitmaps[bmap_id]->src.w;
1361 sdl_bitmaps[bmap_id]->dst.x = bx_bitmap_right_xorigin;
1363 return hb_index;
1366 void bx_sdl_gui_c::replace_bitmap(
1367 unsigned hbar_id,
1368 unsigned bmap_id)
1370 SDL_Rect hb_dst;
1371 unsigned old_id;
1372 if (!sdl_screen) return;
1374 old_id = hb_entry[hbar_id].bmp_id;
1375 hb_dst = sdl_bitmaps[old_id]->dst;
1376 sdl_bitmaps[old_id]->dst.x = -1;
1377 hb_entry[hbar_id].bmp_id = bmap_id;
1378 sdl_bitmaps[bmap_id]->dst.x = hb_dst.x;
1379 if(sdl_bitmaps[bmap_id]->dst.x != -1)
1381 if (hb_entry[hbar_id].alignment == BX_GRAVITY_RIGHT) {
1382 hb_dst.x = res_x - hb_dst.x;
1384 SDL_BlitSurface(
1385 sdl_bitmaps[bmap_id]->surface,
1386 &sdl_bitmaps[bmap_id]->src,
1387 sdl_screen,
1388 &hb_dst);
1389 SDL_UpdateRect(
1390 sdl_screen,
1391 hb_dst.x,
1392 sdl_bitmaps[bmap_id]->dst.y,
1393 sdl_bitmaps[bmap_id]->src.w,
1394 sdl_bitmaps[bmap_id]->src.h);
1398 void bx_sdl_gui_c::show_headerbar(void)
1400 Uint32 *buf;
1401 Uint32 *buf_row;
1402 Uint32 disp;
1403 int rowsleft = headerbar_height;
1404 int colsleft, sb_item;
1405 int bitmapscount = bx_headerbar_entries;
1406 unsigned current_bmp, pos_x;
1407 SDL_Rect hb_dst;
1409 if(!sdl_screen) return;
1410 disp = sdl_screen->pitch/4;
1411 buf = (Uint32 *)sdl_screen->pixels;
1413 // draw headerbar background
1416 colsleft = res_x;
1417 buf_row = buf;
1420 *buf++ = headerbar_bg;
1421 } while(--colsleft);
1422 buf = buf_row + disp;
1423 } while(--rowsleft);
1424 SDL_UpdateRect( sdl_screen, 0,0,res_x,headerbar_height);
1426 // go thru the bitmaps and display the active ones
1427 while(bitmapscount--)
1429 current_bmp = hb_entry[bitmapscount].bmp_id;
1430 if(sdl_bitmaps[current_bmp]->dst.x != -1)
1432 hb_dst = sdl_bitmaps[current_bmp]->dst;
1433 if (hb_entry[bitmapscount].alignment == BX_GRAVITY_RIGHT) {
1434 hb_dst.x = res_x - hb_dst.x;
1436 SDL_BlitSurface(
1437 sdl_bitmaps[current_bmp]->surface,
1438 &sdl_bitmaps[current_bmp]->src,
1439 sdl_screen,
1440 &hb_dst);
1441 SDL_UpdateRect(
1442 sdl_screen,
1443 hb_dst.x,
1444 sdl_bitmaps[current_bmp]->dst.y,
1445 sdl_bitmaps[current_bmp]->src.w,
1446 sdl_bitmaps[current_bmp]->src.h);
1449 // draw statusbar background
1450 rowsleft = statusbar_height;
1451 buf = (Uint32 *)sdl_screen->pixels + (res_y + headerbar_height) * disp;
1454 colsleft = res_x;
1455 buf_row = buf;
1456 sb_item = 1;
1457 pos_x = 0;
1460 if (pos_x == statusitem_pos[sb_item])
1462 *buf++ = headerbar_fg;
1463 if (sb_item < 11) sb_item++;
1465 else
1467 *buf++ = headerbar_bg;
1469 pos_x++;
1470 } while(--colsleft);
1471 buf = buf_row + disp;
1472 } while(--rowsleft);
1473 SDL_UpdateRect( sdl_screen, 0,res_y+headerbar_height,res_x,statusbar_height);
1474 for (unsigned i=0; i<statusitem_count; i++) {
1475 sdl_set_status_text(i+1, statusitem_text[i], statusitem_active[i+1]);
1479 void bx_sdl_gui_c::mouse_enabled_changed_specific (bx_bool val)
1481 if(val == 1)
1483 SDL_ShowCursor(0);
1484 SDL_WM_GrabInput(SDL_GRAB_ON);
1486 else
1488 SDL_ShowCursor(1);
1489 SDL_WM_GrabInput(SDL_GRAB_OFF);
1491 sdl_grab = val;
1495 void headerbar_click(int x)
1497 int xdim,xorigin;
1499 for (unsigned i=0; i<bx_headerbar_entries; i++) {
1500 xdim = sdl_bitmaps[hb_entry[i].bmp_id]->src.w;
1501 if (hb_entry[i].alignment == BX_GRAVITY_LEFT)
1502 xorigin = sdl_bitmaps[hb_entry[i].bmp_id]->dst.x;
1503 else
1504 xorigin = res_x - sdl_bitmaps[hb_entry[i].bmp_id]->dst.x;
1505 if ((x>=xorigin) && (x<(xorigin+xdim))) {
1506 hb_entry[i].f();
1507 return;
1512 void bx_sdl_gui_c::exit(void)
1514 if(sdl_screen)
1515 SDL_FreeSurface(sdl_screen);
1516 if(sdl_fullscreen)
1517 SDL_FreeSurface(sdl_fullscreen);
1518 while(n_sdl_bitmaps)
1520 SDL_FreeSurface(sdl_bitmaps[n_sdl_bitmaps-1]->surface);
1521 n_sdl_bitmaps--;
1525 /// key mapping for SDL
1526 typedef struct keyTableEntry {
1527 const char *name;
1528 Bit32u value;
1531 #define DEF_SDL_KEY(key) \
1532 { #key, key },
1534 keyTableEntry keytable[] = {
1535 // this include provides all the entries.
1536 #include "sdlkeys.h"
1537 // one final entry to mark the end
1538 { NULL, 0 }
1541 // function to convert key names into SDLKey values.
1542 // This first try will be horribly inefficient, but it only has
1543 // to be done while loading a keymap. Once the simulation starts,
1544 // this function won't be called.
1545 static Bit32u convertStringToSDLKey (const char *string)
1547 keyTableEntry *ptr;
1548 for (ptr = &keytable[0]; ptr->name != NULL; ptr++) {
1549 //BX_DEBUG (("comparing string '%s' to SDL key '%s'", string, ptr->name));
1550 if (!strcmp(string, ptr->name))
1551 return ptr->value;
1553 return BX_KEYMAP_UNKNOWN;
1556 void bx_sdl_gui_c::set_display_mode(disp_mode_t newmode)
1558 // if no mode change, do nothing.
1559 if (disp_mode == newmode) return;
1560 // remember the display mode for next time
1561 disp_mode = newmode;
1562 // If fullscreen mode is on, we must switch back to windowed mode if
1563 // the user needs to see the text console.
1564 if (sdl_fullscreen_toggle) {
1565 switch (newmode) {
1566 case DISP_MODE_CONFIG:
1567 BX_DEBUG(("switch to configuration mode (windowed)"));
1568 switch_to_windowed();
1569 break;
1570 case DISP_MODE_SIM:
1571 BX_DEBUG(("switch to simulation mode (fullscreen)"));
1572 switch_to_fullscreen();
1573 break;
1578 #if BX_SHOW_IPS
1579 void bx_sdl_gui_c::show_ips(Bit32u ips_count)
1581 if (!sdl_ips_update) {
1582 sprintf(sdl_ips_text, "IPS: %9u", ips_count);
1583 sdl_ips_update = 1;
1586 #endif
1588 #endif /* if BX_WITH_SDL */