sdl.cpp

Go to the documentation of this file.
00001 /* ES40 emulator.
00002  * Copyright (C) 2007-2008 by the ES40 Emulator Project
00003  *
00004  * WWW    : http://es40.org
00005  * E-mail : camiel@camicom.com
00006  * 
00007  *  This file is based upon Bochs.
00008  *
00009  *  Copyright (C) 2002  MandrakeSoft S.A.
00010  *
00011  *    MandrakeSoft S.A.
00012  *    43, rue d'Aboukir
00013  *    75002 Paris - France
00014  *    http://www.linux-mandrake.com/
00015  *    http://www.mandrakesoft.com/
00016  *
00017  *  This library is free software; you can redistribute it and/or
00018  *  modify it under the terms of the GNU Lesser General Public
00019  *  License as published by the Free Software Foundation; either
00020  *  version 2 of the License, or (at your option) any later version.
00021  *
00022  *  This library is distributed in the hope that it will be useful,
00023  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00024  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00025  *  Lesser General Public License for more details.
00026  *
00027  *  You should have received a copy of the GNU Lesser General Public
00028  *  License along with this library; if not, write to the Free Software
00029  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00030  */
00031 
00076 #include "../StdAfx.h"
00077 
00078 #if defined(HAVE_SDL)
00079 #include "gui.h"
00080 #include "keymap.h"
00081 #include "../VGA.h"
00082 #include "../System.h"
00083 
00084 //#include "../AliM1543C.h"
00085 #include "../Keyboard.h"
00086 #include "../Configurator.h"
00087 
00088 #define _MULTI_THREAD
00089 
00090 // Define BX_PLUGGABLE in files that can be compiled into plugins.  For
00091 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
00092 // is used to know when we are exporting symbols and when we are importing.
00093 #define BX_PLUGGABLE
00094 
00095 #include <stdlib.h>
00096 #include <SDL.h>
00097 #include <SDL_endian.h>
00098 #include <SDL_thread.h>
00099 
00100 #include "sdl_fonts.h"
00101 
00105 class bx_sdl_gui_c : public bx_gui_c
00106 {
00107   public:
00108     bx_sdl_gui_c(CConfigurator* cfg);
00109     virtual void                  specific_init(unsigned x_tilesize,
00110                                                 unsigned y_tilesize);
00111     virtual void                  text_update(u8*  old_text, u8*  new_text,
00112                                               unsigned long cursor_x,
00113                                               unsigned long cursor_y,
00114                                               bx_vga_tminfo_t tm_info,
00115                                               unsigned rows);
00116     virtual void                  graphics_tile_update(u8*  snapshot, unsigned x,
00117                                                        unsigned y);
00118     virtual void                  handle_events(void);
00119     virtual void                  flush(void);
00120     virtual void                  clear_screen(void);
00121     virtual bool                  palette_change(unsigned index, unsigned red,
00122                                                  unsigned green, unsigned blue);
00123     virtual void                  dimension_update(unsigned x, unsigned y,
00124                                                    unsigned fheight = 0,
00125                                                    unsigned fwidth = 0,
00126                                                    unsigned bpp = 8);
00127     virtual void                  mouse_enabled_changed_specific(bool val);
00128     virtual void                  exit(void);
00129     virtual bx_svga_tileinfo_t*   graphics_tile_info(bx_svga_tileinfo_t* info);
00130     virtual u8*                   graphics_tile_get(unsigned x, unsigned y,
00131                                                     unsigned*  w, unsigned*  h);
00132     virtual void                  graphics_tile_update_in_place(unsigned x,
00133                                                                 unsigned y,
00134                                                                 unsigned w,
00135                                                                 unsigned h);
00136   private:
00137     CConfigurator*  myCfg;
00138 };
00139 
00140 // declare one instance of the gui object and call macro to insert the
00141 // plugin code
00142 static bx_sdl_gui_c*  theGui = NULL;
00143 IMPLEMENT_GUI_PLUGIN_CODE(sdl)
00144 static unsigned     prev_cursor_x = 0;
00145 static unsigned     prev_cursor_y = 0;
00146 static u32          convertStringToSDLKey(const char* string);
00147 
00148 SDL_Thread*         sdl_thread;
00149 SDL_Surface*        sdl_screen;
00150 SDL_Event           sdl_event;
00151 int                 sdl_grab;
00152 unsigned            res_x, res_y;
00153 unsigned            half_res_x, half_res_y;
00154 static unsigned int text_cols = 80, text_rows = 25;
00155 u8                  h_panning = 0, v_panning = 0;
00156 u16                 line_compare = 1023;
00157 int                 fontwidth = 8, fontheight = 16;
00158 static unsigned     vga_bpp = 8;
00159 unsigned            tilewidth, tileheight;
00160 u32                 palette[256];
00161 u8                  old_mousebuttons = 0, new_mousebuttons = 0;
00162 int                 old_mousex = 0, new_mousex = 0;
00163 int                 old_mousey = 0, new_mousey = 0;
00164 bool                just_warped = false;
00165 
00166 bx_sdl_gui_c::bx_sdl_gui_c(CConfigurator* cfg)
00167 {
00168   myCfg = cfg;
00169   bx_keymap = new bx_keymap_c(cfg);
00170 }
00171 
00172 #ifdef __MORPHOS__
00173 void bx_sdl_morphos_exit(void)
00174 {
00175   SDL_Quit();
00176   if(PowerSDLBase)
00177     CloseLibrary(PowerSDLBase);
00178 }
00179 #endif
00180 void bx_sdl_gui_c::specific_init(unsigned x_tilesize, unsigned y_tilesize)
00181 {
00182   int i;
00183 
00184   int j;
00185   u32 flags;
00186 
00187   tilewidth = x_tilesize;
00188   tileheight = y_tilesize;
00189 
00190   for(i = 0; i < 256; i++)
00191     for(j = 0; j < 16; j++)
00192       vga_charmap[i * 32 + j] = sdl_font8x16[i][j];
00193 
00194 #ifdef __MORPHOS__
00195   if(!(PowerSDLBase = OpenLibrary("powersdl.library", 0)))
00196   {
00197     BX_PANIC(("Unable to open SDL libraries"));
00198     return;
00199   }
00200 #endif
00201   flags = SDL_INIT_VIDEO;
00202   if(SDL_Init(flags) < 0)
00203   {
00204     FAILURE(SDL, "Unable to initialize SDL libraries");
00205   }
00206 
00207 #ifdef __MORPHOS__
00208   atexit(bx_sdl_morphos_exit);
00209 #else
00210   atexit(SDL_Quit);
00211 #endif
00212   sdl_screen = NULL;
00213 
00214   //  sdl_fullscreen_toggle = 0;
00215   dimension_update(640, 480);
00216 
00217   SDL_EnableKeyRepeat(250, 50);
00218   SDL_WarpMouse(half_res_x, half_res_y);
00219 
00220   // load keymap for sdl
00221   if(myCfg->get_bool_value("keyboard.use_mapping", false))
00222   {
00223     bx_keymap->loadKeymap(convertStringToSDLKey);
00224   }
00225 
00226   new_gfx_api = 1;
00227 }
00228 
00229 void bx_sdl_gui_c::text_update(u8*  old_text, u8*  new_text,
00230                                unsigned long cursor_x, unsigned long cursor_y,
00231                                bx_vga_tminfo_t tm_info, unsigned nrows)
00232 {
00233   u8*           pfont_row;
00234 
00235   u8 *old_line;
00236 
00237   u8 *new_line;
00238 
00239   u8 *text_base;
00240   unsigned int  cs_y;
00241   unsigned int  i;
00242   unsigned int  x;
00243   unsigned int  y;
00244   unsigned int  curs;
00245   unsigned int  hchars;
00246   unsigned int  offset;
00247   u8            fontline;
00248   u8            fontpixels;
00249   u8            fontrows;
00250   int           rows;
00251   u32           fgcolor;
00252   u32           bgcolor;
00253   u32*          buf;
00254   u32 *buf_row;
00255   u32 *buf_char;
00256   u32           disp;
00257   u16           font_row;
00258   u16           mask;
00259   u8            cfstart;
00260   u8            cfwidth;
00261   u8            cfheight;
00262   u8            split_fontrows;
00263   u8            split_textrow;
00264   bool          cursor_visible;
00265   bool          gfxcharw9;
00266   bool          invert;
00267   bool          forceUpdate;
00268   bool          split_screen;
00269   u32           text_palette[16];
00270 
00271   //  UNUSED(nrows);
00272   forceUpdate = 0;
00273   if(charmap_updated)
00274   {
00275     forceUpdate = 1;
00276     charmap_updated = 0;
00277   }
00278 
00279   for(i = 0; i < 16; i++)
00280   {
00281     text_palette[i] = palette[theVGA->get_actl_palette_idx(i)];
00282   }
00283 
00284   if((tm_info.h_panning != h_panning) || (tm_info.v_panning != v_panning))
00285   {
00286     forceUpdate = 1;
00287     h_panning = tm_info.h_panning;
00288     v_panning = tm_info.v_panning;
00289   }
00290 
00291   if(tm_info.line_compare != line_compare)
00292   {
00293     forceUpdate = 1;
00294     line_compare = tm_info.line_compare;
00295   }
00296 
00297   disp = sdl_screen->pitch / 4;
00298   buf_row = (u32*) sdl_screen->pixels;
00299 
00300   // first invalidate character at previous and new cursor location
00301   if((prev_cursor_y < text_rows) && (prev_cursor_x < text_cols))
00302   {
00303     curs = prev_cursor_y * tm_info.line_offset + prev_cursor_x * 2;
00304     old_text[curs] = ~new_text[curs];
00305   }
00306 
00307   cursor_visible =
00308     (
00309       (tm_info.cs_start <= tm_info.cs_end)
00310     && (tm_info.cs_start < fontheight)
00311     );
00312   if((cursor_visible) && (cursor_y < text_rows) && (cursor_x < text_cols))
00313   {
00314     curs = cursor_y * tm_info.line_offset + cursor_x * 2;
00315     old_text[curs] = ~new_text[curs];
00316   }
00317   else
00318   {
00319     curs = 0xffff;
00320   }
00321 
00322   rows = text_rows;
00323   if(v_panning)
00324     rows++;
00325   y = 0;
00326   cs_y = 0;
00327   text_base = new_text - tm_info.start_address;
00328   split_textrow = (line_compare + v_panning) / fontheight;
00329   split_fontrows = ((line_compare + v_panning) % fontheight) + 1;
00330   split_screen = 0;
00331 
00332   do
00333   {
00334     buf = buf_row;
00335     hchars = text_cols;
00336     if(h_panning)
00337       hchars++;
00338     cfheight = fontheight;
00339     cfstart = 0;
00340     if(split_screen)
00341     {
00342       if(rows == 1)
00343       {
00344         cfheight = (res_y - line_compare - 1) % fontheight;
00345         if(cfheight == 0)
00346           cfheight = fontheight;
00347       }
00348     }
00349     else if(v_panning)
00350     {
00351       if(y == 0)
00352       {
00353         cfheight -= v_panning;
00354         cfstart = v_panning;
00355       }
00356       else if(rows == 1)
00357       {
00358         cfheight = v_panning;
00359       }
00360     }
00361 
00362     if(!split_screen && (y == split_textrow))
00363     {
00364       if((split_fontrows - cfstart) < cfheight)
00365       {
00366         cfheight = split_fontrows - cfstart;
00367       }
00368     }
00369 
00370     new_line = new_text;
00371     old_line = old_text;
00372     x = 0;
00373     offset = cs_y * tm_info.line_offset;
00374     do
00375     {
00376       cfwidth = fontwidth;
00377       if(h_panning)
00378       {
00379         if(hchars > text_cols)
00380         {
00381           cfwidth -= h_panning;
00382         }
00383         else if(hchars == 1)
00384         {
00385           cfwidth = h_panning;
00386         }
00387       }
00388 
00389       // check if char needs to be updated
00390       if(forceUpdate || (old_text[0] != new_text[0])
00391        || (old_text[1] != new_text[1]))
00392       {
00393 
00394         // Get Foreground/Background pixel colors
00395         fgcolor = text_palette[new_text[1] & 0x0F];
00396         bgcolor = text_palette[(new_text[1] >> 4) & 0x0F];
00397         invert = ((offset == curs) && (cursor_visible));
00398         gfxcharw9 = ((tm_info.line_graphics) && ((new_text[0] & 0xE0) == 0xC0));
00399 
00400         // Display this one char
00401         fontrows = cfheight;
00402         fontline = cfstart;
00403         if(y > 0)
00404         {
00405           pfont_row = (u8*) &vga_charmap[(new_text[0] << 5)];
00406         }
00407         else
00408         {
00409           pfont_row = (u8*) &vga_charmap[(new_text[0] << 5) + cfstart];
00410         }
00411 
00412         buf_char = buf;
00413         do
00414         {
00415           font_row = *pfont_row++;
00416           if(gfxcharw9)
00417           {
00418             font_row = (font_row << 1) | (font_row & 0x01);
00419           }
00420           else
00421           {
00422             font_row <<= 1;
00423           }
00424 
00425           if(hchars > text_cols)
00426           {
00427             font_row <<= h_panning;
00428           }
00429 
00430           fontpixels = cfwidth;
00431           if((invert) && (fontline >= tm_info.cs_start)
00432            && (fontline <= tm_info.cs_end)) mask = 0x100;
00433           else
00434             mask = 0x00;
00435           do
00436           {
00437             if((font_row & 0x100) == mask)
00438               *buf = bgcolor;
00439             else
00440               *buf = fgcolor;
00441             buf++;
00442             font_row <<= 1;
00443           } while(--fontpixels);
00444           buf -= cfwidth;
00445           buf += disp;
00446           fontline++;
00447         } while(--fontrows);
00448 
00449         // restore output buffer ptr to start of this char
00450         buf = buf_char;
00451       }
00452 
00453       // move to next char location on screen
00454       buf += cfwidth;
00455 
00456       // select next char in old/new text
00457       new_text += 2;
00458       old_text += 2;
00459       offset += 2;
00460       x++;
00461 
00462       // process one entire horizontal row
00463     } while(--hchars);
00464 
00465     // go to next character row location
00466     buf_row += disp * cfheight;
00467     if(!split_screen && (y == split_textrow))
00468     {
00469       new_text = text_base;
00470       forceUpdate = 1;
00471       cs_y = 0;
00472       if(tm_info.split_hpanning)
00473         h_panning = 0;
00474       rows = ((res_y - line_compare + fontheight - 2) / fontheight) + 1;
00475       split_screen = 1;
00476     }
00477     else
00478     {
00479       new_text = new_line + tm_info.line_offset;
00480       old_text = old_line + tm_info.line_offset;
00481       cs_y++;
00482       y++;
00483     }
00484   } while(--rows);
00485   h_panning = tm_info.h_panning;
00486   prev_cursor_x = cursor_x;
00487   prev_cursor_y = cursor_y;
00488 }
00489 
00490 void bx_sdl_gui_c::graphics_tile_update(u8* snapshot, unsigned x, unsigned y)
00491 {
00492   u32*  buf;
00493 
00494   u32 disp;
00495   u32*  buf_row;
00496   int   i;
00497   int   j;
00498 
00499   disp = sdl_screen->pitch / 4;
00500   buf = (u32*) sdl_screen->pixels + /*(headerbar_height+y)*disp +*/ x;
00501 
00502   i = tileheight;
00503   if(i + y > res_y)
00504     i = res_y - y;
00505 
00506   // FIXME
00507   if(i <= 0)
00508     return;
00509 
00510   switch(vga_bpp)
00511   {
00512   case 8: /* 8 bpp */
00513     do
00514     {
00515       buf_row = buf;
00516       j = tilewidth;
00517       do
00518       {
00519         *buf++ = palette[*snapshot++];
00520       } while(--j);
00521       buf = buf_row + disp;
00522     } while(--i);
00523     break;
00524 
00525   default:
00526     BX_PANIC(("%u bpp modes handled by new graphics API", vga_bpp));
00527     return;
00528   }
00529 }
00530 
00531 bx_svga_tileinfo_t* bx_sdl_gui_c::graphics_tile_info(bx_svga_tileinfo_t* info)
00532 {
00533   if(!info)
00534   {
00535     info = (bx_svga_tileinfo_t*) malloc(sizeof(bx_svga_tileinfo_t));
00536     if(!info)
00537     {
00538       return NULL;
00539     }
00540   }
00541 
00542   info->bpp = sdl_screen->format->BitsPerPixel;
00543   info->pitch = sdl_screen->pitch;
00544   info->red_shift = sdl_screen->format->Rshift + 8 - sdl_screen->format->Rloss;
00545   info->green_shift = sdl_screen->format->Gshift +
00546     8 -
00547     sdl_screen->format->Gloss;
00548   info->blue_shift = sdl_screen->format->Bshift + 8 - sdl_screen->format->Bloss;
00549   info->red_mask = sdl_screen->format->Rmask;
00550   info->green_mask = sdl_screen->format->Gmask;
00551   info->blue_mask = sdl_screen->format->Bmask;
00552   info->is_indexed = (sdl_screen->format->palette != NULL);
00553 
00554 #ifdef BX_LITTLE_ENDIAN
00555   info->is_little_endian = 1;
00556 #else
00557   info->is_little_endian = 0;
00558 #endif
00559   return info;
00560 }
00561 
00562 u8* bx_sdl_gui_c::graphics_tile_get(unsigned x0, unsigned y0, unsigned*  w,
00563                                     unsigned*  h)
00564 {
00565   if(x0 + tilewidth > res_x)
00566     *w = res_x - x0;
00567   else
00568     *w = tilewidth;
00569 
00570   if(y0 + tileheight > res_y)
00571     *h = res_y - y0;
00572   else
00573     *h = tileheight;
00574 
00575   return (u8*) sdl_screen->pixels +
00576     sdl_screen->pitch *
00577     y0 +
00578     sdl_screen->format->BytesPerPixel *
00579     x0;
00580 }
00581 
00582 void bx_sdl_gui_c::graphics_tile_update_in_place(unsigned x0, unsigned y0,
00583                                                  unsigned w, unsigned h)
00584 { }
00585 static u32 sdl_sym_to_bx_key(SDLKey sym)
00586 {
00587   switch(sym)
00588   {
00589 
00590   //  case SDLK_UNKNOWN:              return BX_KEY_UNKNOWN;
00591   //  case SDLK_FIRST:                return BX_KEY_FIRST;
00592   case SDLK_BACKSPACE:
00593     return BX_KEY_BACKSPACE;
00594 
00595   case SDLK_TAB:
00596     return BX_KEY_TAB;
00597 
00598   //  case SDLK_CLEAR:                return BX_KEY_CLEAR;
00599   case SDLK_RETURN:
00600     return BX_KEY_ENTER;
00601 
00602   case SDLK_PAUSE:
00603     return BX_KEY_PAUSE;
00604 
00605   case SDLK_ESCAPE:
00606     return BX_KEY_ESC;
00607 
00608   case SDLK_SPACE:
00609     return BX_KEY_SPACE;
00610 
00611   //  case SDLK_EXCLAIM:              return BX_KEY_EXCLAIM;
00612   //  case SDLK_QUOTEDBL:             return BX_KEY_QUOTEDBL;
00613   //  case SDLK_HASH:                 return BX_KEY_HASH;
00614   //  case SDLK_DOLLAR:               return BX_KEY_DOLLAR;
00615   //  case SDLK_AMPERSAND:            return BX_KEY_AMPERSAND;
00616   case SDLK_QUOTE:
00617     return BX_KEY_SINGLE_QUOTE;
00618 
00619   //  case SDLK_LEFTPAREN:            return BX_KEY_LEFTPAREN;
00620   //  case SDLK_RIGHTPAREN:           return BX_KEY_RIGHTPAREN;
00621   //  case SDLK_ASTERISK:             return BX_KEY_ASTERISK;
00622   //  case SDLK_PLUS:                 return BX_KEY_PLUS;
00623   case SDLK_COMMA:
00624     return BX_KEY_COMMA;
00625 
00626   case SDLK_MINUS:
00627     return BX_KEY_MINUS;
00628 
00629   case SDLK_PERIOD:
00630     return BX_KEY_PERIOD;
00631 
00632   case SDLK_SLASH:
00633     return BX_KEY_SLASH;
00634 
00635   case SDLK_0:
00636     return BX_KEY_0;
00637 
00638   case SDLK_1:
00639     return BX_KEY_1;
00640 
00641   case SDLK_2:
00642     return BX_KEY_2;
00643 
00644   case SDLK_3:
00645     return BX_KEY_3;
00646 
00647   case SDLK_4:
00648     return BX_KEY_4;
00649 
00650   case SDLK_5:
00651     return BX_KEY_5;
00652 
00653   case SDLK_6:
00654     return BX_KEY_6;
00655 
00656   case SDLK_7:
00657     return BX_KEY_7;
00658 
00659   case SDLK_8:
00660     return BX_KEY_8;
00661 
00662   case SDLK_9:
00663     return BX_KEY_9;
00664 
00665   //  case SDLK_COLON:                return BX_KEY_COLON;
00666   case SDLK_SEMICOLON:
00667     return BX_KEY_SEMICOLON;
00668 
00669   //  case SDLK_LESS:                 return BX_KEY_LESS;
00670   case SDLK_EQUALS:
00671     return BX_KEY_EQUALS;
00672 
00673   //  case SDLK_GREATER:              return BX_KEY_GREATER;
00674   //  case SDLK_QUESTION:             return BX_KEY_QUESTION;
00675   //  case SDLK_AT:                   return BX_KEY_AT;
00676 
00677   /*
00678  Skip uppercase letters
00679 */
00680   case SDLK_LEFTBRACKET:
00681     return BX_KEY_LEFT_BRACKET;
00682 
00683   case SDLK_BACKSLASH:
00684     return BX_KEY_BACKSLASH;
00685 
00686   case SDLK_RIGHTBRACKET:
00687     return BX_KEY_RIGHT_BRACKET;
00688 
00689   //  case SDLK_CARET:                return BX_KEY_CARET;
00690   //  case SDLK_UNDERSCORE:           return BX_KEY_UNDERSCORE;
00691   case SDLK_BACKQUOTE:
00692     return BX_KEY_GRAVE;
00693 
00694   case SDLK_a:
00695     return BX_KEY_A;
00696 
00697   case SDLK_b:
00698     return BX_KEY_B;
00699 
00700   case SDLK_c:
00701     return BX_KEY_C;
00702 
00703   case SDLK_d:
00704     return BX_KEY_D;
00705 
00706   case SDLK_e:
00707     return BX_KEY_E;
00708 
00709   case SDLK_f:
00710     return BX_KEY_F;
00711 
00712   case SDLK_g:
00713     return BX_KEY_G;
00714 
00715   case SDLK_h:
00716     return BX_KEY_H;
00717 
00718   case SDLK_i:
00719     return BX_KEY_I;
00720 
00721   case SDLK_j:
00722     return BX_KEY_J;
00723 
00724   case SDLK_k:
00725     return BX_KEY_K;
00726 
00727   case SDLK_l:
00728     return BX_KEY_L;
00729 
00730   case SDLK_m:
00731     return BX_KEY_M;
00732 
00733   case SDLK_n:
00734     return BX_KEY_N;
00735 
00736   case SDLK_o:
00737     return BX_KEY_O;
00738 
00739   case SDLK_p:
00740     return BX_KEY_P;
00741 
00742   case SDLK_q:
00743     return BX_KEY_Q;
00744 
00745   case SDLK_r:
00746     return BX_KEY_R;
00747 
00748   case SDLK_s:
00749     return BX_KEY_S;
00750 
00751   case SDLK_t:
00752     return BX_KEY_T;
00753 
00754   case SDLK_u:
00755     return BX_KEY_U;
00756 
00757   case SDLK_v:
00758     return BX_KEY_V;
00759 
00760   case SDLK_w:
00761     return BX_KEY_W;
00762 
00763   case SDLK_x:
00764     return BX_KEY_X;
00765 
00766   case SDLK_y:
00767     return BX_KEY_Y;
00768 
00769   case SDLK_z:
00770     return BX_KEY_Z;
00771 
00772   case SDLK_DELETE:
00773     return BX_KEY_DELETE;
00774 
00775   /* End of ASCII mapped keysyms */
00776 
00777   /* Numeric keypad */
00778   case SDLK_KP0:
00779     return BX_KEY_KP_INSERT;
00780 
00781   case SDLK_KP1:
00782     return BX_KEY_KP_END;
00783 
00784   case SDLK_KP2:
00785     return BX_KEY_KP_DOWN;
00786 
00787   case SDLK_KP3:
00788     return BX_KEY_KP_PAGE_DOWN;
00789 
00790   case SDLK_KP4:
00791     return BX_KEY_KP_LEFT;
00792 
00793   case SDLK_KP5:
00794     return BX_KEY_KP_5;
00795 
00796   case SDLK_KP6:
00797     return BX_KEY_KP_RIGHT;
00798 
00799   case SDLK_KP7:
00800     return BX_KEY_KP_HOME;
00801 
00802   case SDLK_KP8:
00803     return BX_KEY_KP_UP;
00804 
00805   case SDLK_KP9:
00806     return BX_KEY_KP_PAGE_UP;
00807 
00808   case SDLK_KP_PERIOD:
00809     return BX_KEY_KP_DELETE;
00810 
00811   case SDLK_KP_DIVIDE:
00812     return BX_KEY_KP_DIVIDE;
00813 
00814   case SDLK_KP_MULTIPLY:
00815     return BX_KEY_KP_MULTIPLY;
00816 
00817   case SDLK_KP_MINUS:
00818     return BX_KEY_KP_SUBTRACT;
00819 
00820   case SDLK_KP_PLUS:
00821     return BX_KEY_KP_ADD;
00822 
00823   case SDLK_KP_ENTER:
00824     return BX_KEY_KP_ENTER;
00825 
00826   //  case SDLK_KP_EQUALS:            return BX_KEY_KP_EQUALS;
00827 
00828   /* Arrows + Home/End pad */
00829   case SDLK_UP:
00830     return BX_KEY_UP;
00831 
00832   case SDLK_DOWN:
00833     return BX_KEY_DOWN;
00834 
00835   case SDLK_RIGHT:
00836     return BX_KEY_RIGHT;
00837 
00838   case SDLK_LEFT:
00839     return BX_KEY_LEFT;
00840 
00841   case SDLK_INSERT:
00842     return BX_KEY_INSERT;
00843 
00844   case SDLK_HOME:
00845     return BX_KEY_HOME;
00846 
00847   case SDLK_END:
00848     return BX_KEY_END;
00849 
00850   case SDLK_PAGEUP:
00851     return BX_KEY_PAGE_UP;
00852 
00853   case SDLK_PAGEDOWN:
00854     return BX_KEY_PAGE_DOWN;
00855 
00856   /* Function keys */
00857   case SDLK_F1:
00858     return BX_KEY_F1;
00859 
00860   case SDLK_F2:
00861     return BX_KEY_F2;
00862 
00863   case SDLK_F3:
00864     return BX_KEY_F3;
00865 
00866   case SDLK_F4:
00867     return BX_KEY_F4;
00868 
00869   case SDLK_F5:
00870     return BX_KEY_F5;
00871 
00872   case SDLK_F6:
00873     return BX_KEY_F6;
00874 
00875   case SDLK_F7:
00876     return BX_KEY_F7;
00877 
00878   case SDLK_F8:
00879     return BX_KEY_F8;
00880 
00881   case SDLK_F9:
00882     return BX_KEY_F9;
00883 
00884   case SDLK_F10:
00885     return BX_KEY_F10;
00886 
00887   case SDLK_F11:
00888     return BX_KEY_F11;
00889 
00890   case SDLK_F12:
00891     return BX_KEY_F12;
00892 
00893   //  case SDLK_F13:                  return BX_KEY_F13;
00894   //  case SDLK_F14:                  return BX_KEY_F14;
00895   //  case SDLK_F15:                  return BX_KEY_F15;
00896 
00897   /* Key state modifier keys */
00898   case SDLK_NUMLOCK:
00899     return BX_KEY_NUM_LOCK;
00900 
00901   case SDLK_CAPSLOCK:
00902     return BX_KEY_CAPS_LOCK;
00903 
00904   case SDLK_SCROLLOCK:
00905     return BX_KEY_SCRL_LOCK;
00906 
00907   case SDLK_RSHIFT:
00908     return BX_KEY_SHIFT_R;
00909 
00910   case SDLK_LSHIFT:
00911     return BX_KEY_SHIFT_L;
00912 
00913   case SDLK_RCTRL:
00914     return BX_KEY_CTRL_R;
00915 
00916   case SDLK_LCTRL:
00917     return BX_KEY_CTRL_L;
00918 
00919   case SDLK_RALT:
00920     return BX_KEY_ALT_R;
00921 
00922   case SDLK_LALT:
00923     return BX_KEY_ALT_L;
00924 
00925   case SDLK_RMETA:
00926     return BX_KEY_ALT_R;
00927 
00928   case SDLK_LMETA:
00929     return BX_KEY_WIN_L;
00930 
00931   case SDLK_LSUPER:
00932     return BX_KEY_WIN_L;
00933 
00934   case SDLK_RSUPER:
00935     return BX_KEY_WIN_R;
00936 
00937   //  case SDLK_MODE:                 return BX_KEY_MODE;
00938   //  case SDLK_COMPOSE:              return BX_KEY_COMPOSE;
00939 
00940   /* Miscellaneous function keys */
00941   case SDLK_PRINT:
00942     return BX_KEY_PRINT;
00943 
00944   case SDLK_BREAK:
00945     return BX_KEY_PAUSE;
00946 
00947   case SDLK_MENU:
00948     return BX_KEY_MENU;
00949 #if 0
00950 
00951   case SDLK_HELP:
00952     return BX_KEY_HELP;
00953 
00954   case SDLK_SYSREQ:
00955     return BX_KEY_SYSREQ;
00956 
00957   case SDLK_POWER:
00958     return BX_KEY_POWER;
00959 
00960   case SDLK_EURO:
00961     return BX_KEY_EURO;
00962 
00963   case SDLK_UNDO:
00964     return BX_KEY_UNDO;
00965 #endif
00966 
00967   default:
00968     BX_ERROR(("sdl keysym %d not mapped", (int) sym));
00969     return BX_KEY_UNHANDLED;
00970   }
00971 }
00972 
00973 void bx_sdl_gui_c::handle_events(void)
00974 {
00975   u32 key_event;
00976 
00977   //  u8 mouse_state;
00978   int wheel_status;
00979 
00980   while(SDL_PollEvent(&sdl_event))
00981   {
00982     wheel_status = 0;
00983     switch(sdl_event.type)
00984     {
00985     case SDL_VIDEOEXPOSE:
00986       SDL_UpdateRect(sdl_screen, 0, 0, res_x, res_y);
00987       break;
00988 
00989     case SDL_MOUSEMOTION:
00990 
00991     //  //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);
00992     //  if (!sdl_grab) {
00993     //    //fprintf (stderr, "ignore mouse event because sdl_grab is off\n");
00994     //    break;
00995     //  }
00996     //  if (just_warped
00997     //      && sdl_event.motion.x == half_res_x
00998     //      && sdl_event.motion.y == half_res_y) {
00999     //    // This event was generated as a side effect of the WarpMouse,
01000     //    // and it must be ignored.
01001     //    //fprintf (stderr, "ignore mouse event because it is a side effect of SDL_WarpMouse\n");
01002     //    just_warped = false;
01003     //    break;
01004     //  }
01005     //  //fprintf (stderr, "processing relative mouse event\n");
01006     //        new_mousebuttons = ((sdl_event.motion.state & 0x01)|((sdl_event.motion.state>>1)&0x02)
01007     //                            |((sdl_event.motion.state<<1)&0x04));
01008     //        DEV_mouse_motion_ext(
01009     //            sdl_event.motion.xrel,
01010     //            -sdl_event.motion.yrel,
01011     //            wheel_status,
01012     //            new_mousebuttons);
01013     //  old_mousebuttons = new_mousebuttons;
01014     //  old_mousex = (int)(sdl_event.motion.x);
01015     //  old_mousey = (int)(sdl_event.motion.y);
01016     //  //fprintf (stderr, "warping mouse to center\n");
01017     //  SDL_WarpMouse(half_res_x, half_res_y);
01018     //  just_warped = 1;
01019     //  break;
01020     //
01021     case SDL_MOUSEBUTTONDOWN:
01022 
01023     //        if( (sdl_event.button.button == SDL_BUTTON_MIDDLE)
01024     //            && ((SDL_GetModState() & KMOD_CTRL) > 0)
01025     //            && (sdl_fullscreen_toggle == 0) )
01026     //  {
01027     //    if( sdl_grab == 0 )
01028     //    {
01029     //      SDL_ShowCursor(0);
01030     //      SDL_WM_GrabInput(SDL_GRAB_ON);
01031     //    }
01032     //    else
01033     //    {
01034     //      SDL_ShowCursor(1);
01035     //      SDL_WM_GrabInput(SDL_GRAB_OFF);
01036     //    }
01037     //    sdl_grab = ~sdl_grab;
01038     //    toggle_mouse_enable();
01039     //    break;
01040     //  }
01041     //#ifdef SDL_BUTTON_WHEELUP
01042     //        // get the wheel status
01043     //        if (sdl_event.button.button == SDL_BUTTON_WHEELUP) {
01044     //          wheel_status = 1;
01045     //        }
01046     //        if (sdl_event.button.button == SDL_BUTTON_WHEELDOWN) {
01047     //          wheel_status = -1;
01048     //        }
01049     //#endif
01050     case SDL_MOUSEBUTTONUP:
01051 
01052       //        // figure out mouse state
01053       //        new_mousex = (int)(sdl_event.button.x);
01054       //        new_mousey = (int)(sdl_event.button.y);
01055       //        // SDL_GetMouseState() returns the state of all buttons
01056       //        mouse_state = SDL_GetMouseState(NULL, NULL);
01057       //        new_mousebuttons =
01058       //          (mouse_state & 0x01)    |
01059       //          ((mouse_state>>1)&0x02) |
01060       //          ((mouse_state<<1)&0x04) ;
01061       //        // filter out middle button if not fullscreen
01062       //        if( sdl_fullscreen_toggle == 0 )
01063       //          new_mousebuttons &= 0x07;
01064       //        // send motion information
01065       //        DEV_mouse_motion_ext(
01066       //            new_mousex - old_mousex,
01067       //            -(new_mousey - old_mousey),
01068       //            wheel_status,
01069       //            new_mousebuttons);
01070       //        // mark current state to diff with next packet
01071       //        old_mousebuttons = new_mousebuttons;
01072       //        old_mousex = new_mousex;
01073       //        old_mousey = new_mousey;
01074       break;
01075 
01076     //
01077     case SDL_KEYDOWN:
01078 
01079       // convert sym->bochs code
01080       if(sdl_event.key.keysym.sym > SDLK_LAST)
01081         break;
01082       if(!myCfg->get_bool_value("keyboard.use_mapping", false))
01083 
01084       //    if (!SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get())
01085       {
01086         key_event = sdl_sym_to_bx_key(sdl_event.key.keysym.sym);
01087 #if defined(DEBUG_KBD)
01088         BX_DEBUG((
01089                    "keypress scancode=%d, sym=%d, bx_key = %d", sdl_event.key.keysym.
01090                    scancode, sdl_event.key.keysym.sym, key_event));
01091 #endif
01092       }
01093       else
01094       {
01095 
01096         /* use mapping */
01097         BXKeyEntry*   entry = bx_keymap->findHostKey(sdl_event.key.keysym.sym);
01098         if(!entry)
01099         {
01100           BX_ERROR(("host key %d (0x%x) not mapped!",
01101                      (unsigned) sdl_event.key.keysym.sym,
01102                      (unsigned) sdl_event.key.keysym.sym));
01103           break;
01104         }
01105 
01106         key_event = entry->baseKey;
01107       }
01108 
01109       if(key_event == BX_KEY_UNHANDLED)
01110         break;
01111       theKeyboard->gen_scancode(key_event);
01112       if((key_event == BX_KEY_NUM_LOCK) || (key_event == BX_KEY_CAPS_LOCK))
01113       {
01114         theKeyboard->gen_scancode(key_event | BX_KEY_RELEASED);
01115       }
01116       break;
01117 
01118     case SDL_KEYUP:
01119 
01120       // filter out release of Windows/Fullscreen toggle and unsupported keys
01121       if((sdl_event.key.keysym.sym != SDLK_SCROLLOCK)
01122        && (sdl_event.key.keysym.sym < SDLK_LAST))
01123       {
01124 
01125         // convert sym->bochs code
01126         if(!myCfg->get_bool_value("keyboard.use_mapping", false))
01127         {
01128 
01129           //if (!SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get()) {
01130           key_event = sdl_sym_to_bx_key(sdl_event.key.keysym.sym);
01131         }
01132         else
01133         {
01134 
01135           /* use mapping */
01136           BXKeyEntry*   entry = bx_keymap->findHostKey(sdl_event.key.keysym.sym);
01137           if(!entry)
01138           {
01139             BX_ERROR(("host key %d (0x%x) not mapped!",
01140                        (unsigned) sdl_event.key.keysym.sym,
01141                        (unsigned) sdl_event.key.keysym.sym));
01142             break;
01143           }
01144 
01145           key_event = entry->baseKey;
01146         }
01147 
01148         if(key_event == BX_KEY_UNHANDLED)
01149           break;
01150         if((key_event == BX_KEY_NUM_LOCK) || (key_event == BX_KEY_CAPS_LOCK))
01151         {
01152           theKeyboard->gen_scancode(key_event);
01153         }
01154 
01155         theKeyboard->gen_scancode(key_event | BX_KEY_RELEASED);
01156       }
01157       break;
01158 
01159     case SDL_QUIT:
01160       FAILURE(Graceful, "User requested shutdown");
01161     }
01162   }
01163 }
01164 
01168 void bx_sdl_gui_c::flush(void)
01169 {
01170   SDL_UpdateRect(sdl_screen, 0, 0, res_x, res_y);
01171 }
01172 
01176 void bx_sdl_gui_c::clear_screen(void)
01177 {
01178   int   i = res_y;
01179 
01180   int   j;
01181   u32   color;
01182   u32*  buf;
01183   u32 *buf_row;
01184   u32   disp;
01185 
01186   if(!sdl_screen)
01187     return;
01188 
01189   color = SDL_MapRGB(sdl_screen->format, 0, 0, 0);
01190   disp = sdl_screen->pitch / 4;
01191   buf = (u32*) sdl_screen->pixels;
01192 
01193   do
01194   {
01195     buf_row = buf;
01196     j = res_x;
01197     while(j--)
01198       *buf++ = color;
01199     buf = buf_row + disp;
01200   } while(--i);
01201 
01202   flush();
01203 }
01204 
01210 bool bx_sdl_gui_c::palette_change(unsigned index, unsigned red, unsigned green,
01211                                   unsigned blue)
01212 {
01213   unsigned char palred = red & 0xFF;
01214   unsigned char palgreen = green & 0xFF;
01215   unsigned char palblue = blue & 0xFF;
01216 
01217   if(index > 255)
01218     return 0;
01219 
01220   palette[index] = SDL_MapRGB(sdl_screen->format, palred, palgreen, palblue);
01221 
01222   return 1;
01223 }
01224 
01225 void bx_sdl_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight,
01226                                     unsigned fwidth, unsigned bpp)
01227 {
01228   if((bpp == 8) || (bpp == 15) || (bpp == 16) || (bpp == 24) || (bpp == 32))
01229   {
01230     vga_bpp = bpp;
01231   }
01232   else
01233   {
01234     FAILURE_1(SDL, "%d bpp graphics mode not supported.", bpp);
01235   }
01236 
01237   if(fheight > 0)
01238   {
01239     fontheight = fheight;
01240     fontwidth = fwidth;
01241     text_cols = x / fontwidth;
01242     text_rows = y / fontheight;
01243   }
01244 
01245   if((x == res_x) && (y == res_y))
01246     return;
01247 
01248   if(sdl_screen)
01249   {
01250     SDL_FreeSurface(sdl_screen);
01251     sdl_screen = NULL;
01252   }
01253 
01254   sdl_screen = SDL_SetVideoMode(x, y /*+headerbar_height+statusbar_height*/, 32,
01255                                 SDL_SWSURFACE);
01256   if(!sdl_screen)
01257   {
01258     FAILURE_3(SDL, "Unable to set requested videomode: %ix%i: %s   \n", x, y,
01259               SDL_GetError());
01260   }
01261 
01262   res_x = x;
01263   res_y = y;
01264   half_res_x = x / 2;
01265   half_res_y = y / 2;
01266 }
01267 
01268 void bx_sdl_gui_c::mouse_enabled_changed_specific(bool val)
01269 {
01270   if(val == 1)
01271   {
01272     SDL_ShowCursor(0);
01273     SDL_WM_GrabInput(SDL_GRAB_ON);
01274   }
01275   else
01276   {
01277     SDL_ShowCursor(1);
01278     SDL_WM_GrabInput(SDL_GRAB_OFF);
01279   }
01280 
01281   sdl_grab = val;
01282 }
01283 
01284 void bx_sdl_gui_c::exit(void)
01285 {
01286   if(sdl_screen)
01287     SDL_FreeSurface(sdl_screen);
01288 }
01289 
01291 typedef struct
01292 {
01293   const char*   name;
01294   u32           value;
01295 } keyTableEntry;
01296 
01297 #define DEF_SDL_KEY(key) \
01298   {                      \
01299     #key, key            \
01300   },
01301 
01302 keyTableEntry keytable[] = {
01303   // this include provides all the entries.
01304 #include "sdlkeys.h"
01305   // one final entry to mark the end
01306   { NULL, 0}
01307 };
01308 
01309 // function to convert key names into SDLKey values.
01310 // This first try will be horribly inefficient, but it only has
01311 // to be done while loading a keymap.  Once the simulation starts,
01312 
01313 // this function won't be called.
01314 static u32 convertStringToSDLKey(const char* string)
01315 {
01316   keyTableEntry*  ptr;
01317   for(ptr = &keytable[0]; ptr->name != NULL; ptr++)
01318   {
01319 #if defined(DEBUG_SDL_KEY)
01320     printf("SDL: comparing string '%s' to SDL key '%s'   \n", string, ptr->name);
01321 #endif
01322     if(!strcmp(string, ptr->name))
01323       return ptr->value;
01324   }
01325 
01326   return BX_KEYMAP_UNKNOWN;
01327 }
01328 #endif //defined(HAVE_SDL)

SourceForge.net Logo
Project space on SourceForge.net