721f89b77b
set_text_charbyte() - vga: store the address of the active charmap in the new variable charmap_address - vga: text mode hack removed. The write modes, operations and masks must be used in text mode too. - sdl: clear_screen() is not necessary when the charmap has changed - win32: update only the changed font bitmaps before drawing the text
889 lines
20 KiB
C++
889 lines
20 KiB
C++
/////////////////////////////////////////////////////////////////////////
|
|
// $Id: sdl.cc,v 1.20 2002-09-19 18:59:49 vruppert Exp $
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2002 MandrakeSoft S.A.
|
|
//
|
|
// MandrakeSoft S.A.
|
|
// 43, rue d'Aboukir
|
|
// 75002 Paris - France
|
|
// http://www.linux-mandrake.com/
|
|
// http://www.mandrakesoft.com/
|
|
//
|
|
// 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
|
|
|
|
#include <stdlib.h>
|
|
#include <SDL/SDL.h>
|
|
#include <SDL/SDL_endian.h>
|
|
#include <SDL/SDL_thread.h>
|
|
|
|
#include "bochs.h"
|
|
#include "icon_bochs.h"
|
|
#include "sdl.h"
|
|
|
|
#define LOG_THIS bx_gui.
|
|
|
|
#define _SDL_DEBUG_ME_
|
|
|
|
#ifdef _SDL_DEBUG_ME_
|
|
void we_are_here(void)
|
|
{
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
static unsigned prev_cursor_x=0;
|
|
static unsigned prev_cursor_y=0;
|
|
|
|
#ifdef linux
|
|
#define FIX_SDL_SCANCODE(x) ((x)-8)
|
|
#else
|
|
#define FIX_SDL_SCANCODE(x) ((x))
|
|
#endif
|
|
|
|
#define MAX_SDL_BITMAPS 32
|
|
struct bitmaps {
|
|
SDL_Surface *surface;
|
|
SDL_Rect src,dst;
|
|
void (*cb)(void);
|
|
};
|
|
|
|
static struct {
|
|
unsigned bmp_id;
|
|
unsigned alignment;
|
|
void (*f)(void);
|
|
} hb_entry[BX_MAX_HEADERBAR_ENTRIES];
|
|
|
|
unsigned bx_headerbar_entries = 0;
|
|
|
|
SDL_Thread *sdl_thread;
|
|
SDL_Surface *sdl_screen, *sdl_fullscreen;
|
|
SDL_Event sdl_event;
|
|
int sdl_fullscreen_toggle;
|
|
int sdl_grab;
|
|
unsigned res_x, res_y;
|
|
int headerbar_height;
|
|
static unsigned bx_bitmap_left_xorigin = 0; // pixels from left
|
|
static unsigned bx_bitmap_right_xorigin = 0; // pixels from right
|
|
int textres_x, textres_y;
|
|
int fontwidth = 8, fontheight = 16;
|
|
unsigned tilewidth, tileheight;
|
|
unsigned char menufont[256][8];
|
|
Uint32 palette[256];
|
|
Uint32 headerbar_fg, headerbar_bg;
|
|
Bit8u old_mousebuttons=0, new_mousebuttons=0;
|
|
int old_mousex=0, new_mousex=0;
|
|
int old_mousey=0, new_mousey=0;
|
|
bitmaps *sdl_bitmaps[MAX_SDL_BITMAPS];
|
|
int n_sdl_bitmaps = 0;
|
|
|
|
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
|
#define SWAP16(X) (X)
|
|
#define SWAP32(X) (X)
|
|
#else
|
|
#define SWAP16(X) SDL_Swap16(X)
|
|
#define SWAP32(X) SDL_Swap32(X)
|
|
#endif
|
|
|
|
static void headerbar_click(int x);
|
|
|
|
|
|
void switch_to_windowed(void)
|
|
{
|
|
SDL_Surface *tmp;
|
|
SDL_Rect src, dst;
|
|
src.x = 0; src.y = 0;
|
|
src.w = res_x; src.h = res_y;
|
|
dst.x = 0; dst.y = 0;
|
|
|
|
tmp = SDL_CreateRGBSurface(
|
|
SDL_SWSURFACE,
|
|
res_x,
|
|
res_y,
|
|
32,
|
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
|
0xff000000,
|
|
0x00ff0000,
|
|
0x0000ff00,
|
|
0x000000ff
|
|
#else
|
|
0x000000ff,
|
|
0x0000ff00,
|
|
0x00ff0000,
|
|
0xff000000
|
|
#endif
|
|
);
|
|
|
|
SDL_BlitSurface(sdl_fullscreen,&src,tmp,&dst);
|
|
SDL_UpdateRect(tmp,0,0,res_x,res_y);
|
|
SDL_FreeSurface(sdl_fullscreen);
|
|
sdl_fullscreen = NULL;
|
|
|
|
sdl_screen = SDL_SetVideoMode(res_x,res_y+headerbar_height,32, SDL_SWSURFACE);
|
|
dst.y = headerbar_height;
|
|
SDL_BlitSurface(tmp,&src,sdl_screen,&dst);
|
|
SDL_UpdateRect(tmp,0,0,res_x,res_y+headerbar_height);
|
|
SDL_FreeSurface(tmp);
|
|
|
|
SDL_ShowCursor(1);
|
|
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
|
bx_gui.show_headerbar();
|
|
sdl_grab = 0;
|
|
}
|
|
|
|
void switch_to_fullscreen(void)
|
|
{
|
|
SDL_Surface *tmp;
|
|
SDL_Rect src, dst;
|
|
src.x = 0; src.y = headerbar_height;
|
|
src.w = res_x; src.h = res_y;
|
|
dst.x = 0; dst.y = 0;
|
|
|
|
tmp = SDL_CreateRGBSurface(
|
|
SDL_SWSURFACE,
|
|
res_x,
|
|
res_y,
|
|
32,
|
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
|
0xff000000,
|
|
0x00ff0000,
|
|
0x0000ff00,
|
|
0x000000ff
|
|
#else
|
|
0x000000ff,
|
|
0x0000ff00,
|
|
0x00ff0000,
|
|
0xff000000
|
|
#endif
|
|
);
|
|
SDL_BlitSurface(sdl_screen,&src,tmp,&dst);
|
|
SDL_UpdateRect(tmp,0,0,res_x,res_y);
|
|
SDL_FreeSurface(sdl_screen);
|
|
sdl_screen = NULL;
|
|
|
|
sdl_fullscreen = SDL_SetVideoMode(res_x,res_y,32, SDL_HWSURFACE|SDL_FULLSCREEN);
|
|
src.y = 0;
|
|
SDL_BlitSurface(tmp,&src,sdl_fullscreen,&dst);
|
|
SDL_UpdateRect(tmp,0,0,res_x,res_y);
|
|
SDL_FreeSurface(tmp);
|
|
|
|
SDL_ShowCursor(0);
|
|
SDL_WM_GrabInput(SDL_GRAB_ON);
|
|
sdl_grab = 1;
|
|
}
|
|
|
|
|
|
void bx_gui_c::specific_init(
|
|
bx_gui_c *th,
|
|
int argc,
|
|
char **argv,
|
|
unsigned x_tilesize,
|
|
unsigned y_tilesize,
|
|
unsigned header_bar_y)
|
|
{
|
|
int i,j;
|
|
|
|
th->put("SDL");
|
|
|
|
tilewidth = x_tilesize;
|
|
tileheight = y_tilesize;
|
|
headerbar_height = header_bar_y;
|
|
|
|
for(i=0;i<256;i++)
|
|
for(j=0;j<16;j++)
|
|
bx_gui.vga_charmap[i*32+j] = sdl_font8x16[i][j];
|
|
|
|
for(i=0;i<256;i++)
|
|
for(j=0;j<8;j++)
|
|
menufont[i][j] = sdl_font8x8[i][j];
|
|
|
|
if( SDL_Init(SDL_INIT_VIDEO) < 0 )
|
|
{
|
|
LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
|
|
BX_PANIC (("Unable to initialize SDL libraries"));
|
|
return;
|
|
}
|
|
atexit(SDL_Quit);
|
|
|
|
sdl_screen = NULL;
|
|
th->dimension_update(640,480);
|
|
|
|
sdl_fullscreen_toggle = 0;
|
|
|
|
SDL_EnableKeyRepeat(250,50);
|
|
SDL_WM_SetCaption(
|
|
#if BX_CPU_LEVEL < 2
|
|
"Bochs 8086 emulator, http://bochs.sourceforge.net/",
|
|
#elif BX_CPU_LEVEL == 2
|
|
"Bochs 80286 emulator, http://bochs.sourceforge.net/",
|
|
#elif BX_CPU_LEVEL == 3
|
|
"Bochs 80386 emulator, http://bochs.sourceforge.net/",
|
|
#elif BX_CPU_LEVEL == 4
|
|
"Bochs 80486 emulator, http://bochs.sourceforge.net/",
|
|
#else
|
|
"Bochs Pentium emulator, http://bochs.sourceforge.net/",
|
|
#endif
|
|
"Bochs" );
|
|
SDL_WarpMouse(res_x/2, res_y/2);
|
|
}
|
|
|
|
void bx_gui_c::text_update(
|
|
Bit8u *old_text,
|
|
Bit8u *new_text,
|
|
unsigned long cursor_x,
|
|
unsigned long cursor_y,
|
|
Bit16u cursor_state,
|
|
unsigned rows)
|
|
{
|
|
unsigned char font_row, *pfont_row;
|
|
unsigned long x,y;
|
|
int hchars,fontrows,fontpixels;
|
|
int fgcolor_ndx;
|
|
int bgcolor_ndx;
|
|
Uint32 fgcolor;
|
|
Uint32 bgcolor;
|
|
Uint32 *buf, *buf_row, *buf_char;
|
|
Uint32 disp;
|
|
Bit8u cs_start, cs_end, cs_line, mask;
|
|
Boolean invert;
|
|
|
|
cs_start = (cursor_state >> 8) & 0x3f;
|
|
cs_end = cursor_state & 0x1f;
|
|
|
|
if( sdl_screen )
|
|
{
|
|
disp = sdl_screen->pitch/4;
|
|
buf_row = (Uint32 *)sdl_screen->pixels + headerbar_height*disp;
|
|
}
|
|
else
|
|
{
|
|
disp = sdl_fullscreen->pitch/4;
|
|
buf_row = (Uint32 *)sdl_fullscreen->pixels;
|
|
}
|
|
|
|
do
|
|
{
|
|
buf = buf_row;
|
|
hchars = textres_x;
|
|
x = 0;
|
|
y = textres_y - rows;
|
|
do
|
|
{
|
|
// check if char needs to be updated
|
|
if( (old_text[0] != new_text[0])
|
|
|| (old_text[1] != new_text[1])
|
|
|| ((y == cursor_y) && (x == cursor_x))
|
|
|| ((y == prev_cursor_y) && (x == prev_cursor_x)) )
|
|
{
|
|
|
|
// Get Foreground/Background pixel colors
|
|
fgcolor_ndx = new_text[1] & 0x0F;
|
|
bgcolor_ndx = (new_text[1] >> 4) & 0x07;
|
|
fgcolor = palette[fgcolor_ndx];
|
|
bgcolor = palette[bgcolor_ndx];
|
|
invert = ( (y == cursor_y) && (x == cursor_x) && (cs_start < cs_end) );
|
|
|
|
// Display this one char
|
|
fontrows = fontheight;
|
|
pfont_row = &bx_gui.vga_charmap[(new_text[0] << 5)];
|
|
buf_char = buf;
|
|
do
|
|
{
|
|
font_row = *pfont_row++;
|
|
fontpixels = fontwidth;
|
|
cs_line = (fontheight - fontrows);
|
|
if( (invert) && (cs_line >= cs_start) && (cs_line <= cs_end) )
|
|
mask = 0x80;
|
|
else
|
|
mask = 0x00;
|
|
do
|
|
{
|
|
if( (font_row & 0x80) == mask )
|
|
*buf = bgcolor;
|
|
else
|
|
*buf = fgcolor;
|
|
buf++;
|
|
font_row = font_row << 1;
|
|
} while( --fontpixels );
|
|
buf -= fontwidth;
|
|
buf += disp;
|
|
} while( --fontrows );
|
|
|
|
// restore output buffer ptr to start of this char
|
|
buf = buf_char;
|
|
}
|
|
// move to next char location on screen
|
|
buf += fontwidth;
|
|
|
|
// select next char in old/new text
|
|
new_text+=2;
|
|
old_text+=2;
|
|
x++;
|
|
|
|
// process one entire horizontal row
|
|
} while( --hchars );
|
|
|
|
// go to next character row location
|
|
buf_row += disp * fontheight;
|
|
} while( --rows );
|
|
prev_cursor_x = cursor_x;
|
|
prev_cursor_y = cursor_y;
|
|
}
|
|
|
|
int
|
|
bx_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
bx_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
void bx_gui_c::graphics_tile_update(
|
|
Bit8u *snapshot,
|
|
unsigned x,
|
|
unsigned y)
|
|
{
|
|
Uint32 *buf, disp;
|
|
Uint32 *buf_row;
|
|
int i,j;
|
|
|
|
if( sdl_screen )
|
|
{
|
|
disp = sdl_screen->pitch/4;
|
|
buf = (Uint32 *)sdl_screen->pixels + (headerbar_height+y)*disp + x;
|
|
}
|
|
else
|
|
{
|
|
disp = sdl_fullscreen->pitch/4;
|
|
buf = (Uint32 *)sdl_fullscreen->pixels + y*disp + x;
|
|
}
|
|
|
|
i = tileheight;
|
|
if( i + y > res_y ) i = res_y - y;
|
|
|
|
// FIXME
|
|
if( i<=0 ) return;
|
|
|
|
do
|
|
{
|
|
buf_row = buf;
|
|
j = tilewidth;
|
|
do
|
|
{
|
|
*buf++ = palette[*snapshot++];
|
|
} while( --j );
|
|
buf = buf_row + disp;
|
|
} while( --i);
|
|
}
|
|
|
|
|
|
void bx_gui_c::handle_events(void)
|
|
{
|
|
Bit32u key_event;
|
|
Bit8u mouse_state;
|
|
|
|
while( SDL_PollEvent(&sdl_event) )
|
|
{
|
|
switch( sdl_event.type )
|
|
{
|
|
case SDL_VIDEOEXPOSE:
|
|
if( sdl_fullscreen_toggle == 0 )
|
|
SDL_UpdateRect( sdl_screen, 0,0, res_x, res_y+headerbar_height );
|
|
else
|
|
SDL_UpdateRect( sdl_screen, 0,headerbar_height, res_x, res_y );
|
|
break;
|
|
|
|
case SDL_MOUSEMOTION:
|
|
new_mousebuttons = ((sdl_event.motion.state & 0x01)|((sdl_event.motion.state>>1)&0x02));
|
|
bx_devices.keyboard->mouse_motion(
|
|
sdl_event.motion.xrel,
|
|
-sdl_event.motion.yrel,
|
|
new_mousebuttons );
|
|
old_mousebuttons = new_mousebuttons;
|
|
old_mousex = (int)(sdl_event.motion.x);
|
|
old_mousey = (int)(sdl_event.motion.y);
|
|
break;
|
|
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
if( (sdl_event.button.button == SDL_BUTTON_MIDDLE)
|
|
&& (sdl_fullscreen_toggle == 0) )
|
|
{
|
|
if( sdl_grab == 0 )
|
|
{
|
|
SDL_ShowCursor(0);
|
|
SDL_WM_GrabInput(SDL_GRAB_ON);
|
|
}
|
|
else
|
|
{
|
|
SDL_ShowCursor(1);
|
|
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
|
}
|
|
sdl_grab = ~sdl_grab;
|
|
toggle_mouse_enable();
|
|
break;
|
|
} else if (sdl_event.button.y < headerbar_height) {
|
|
headerbar_click(sdl_event.button.x);
|
|
break;
|
|
}
|
|
case SDL_MOUSEBUTTONUP:
|
|
// figure out mouse state
|
|
new_mousex = (int)(sdl_event.button.x);
|
|
new_mousey = (int)(sdl_event.button.y);
|
|
// SDL_GetMouseState() returns the state of all buttons
|
|
mouse_state = SDL_GetMouseState(NULL, NULL);
|
|
new_mousebuttons =
|
|
(mouse_state & 0x01) |
|
|
((mouse_state>>1)&0x02) |
|
|
((mouse_state<<1)&0x04) ;
|
|
// filter out middle button if not fullscreen
|
|
if( sdl_fullscreen_toggle == 0 )
|
|
new_mousebuttons &= 0x03;
|
|
// send motion information
|
|
bx_devices.keyboard->mouse_motion(
|
|
new_mousex - old_mousex,
|
|
-(new_mousey - old_mousey),
|
|
new_mousebuttons );
|
|
// mark current state to diff with next packet
|
|
old_mousebuttons = new_mousebuttons;
|
|
old_mousex = new_mousex;
|
|
old_mousey = new_mousey;
|
|
break;
|
|
|
|
case SDL_KEYDOWN:
|
|
|
|
// Windows/Fullscreen toggle-check
|
|
if( sdl_event.key.keysym.sym == SDLK_SCROLLOCK )
|
|
{
|
|
// SDL_WM_ToggleFullScreen( sdl_screen );
|
|
sdl_fullscreen_toggle = ~sdl_fullscreen_toggle;
|
|
if( sdl_fullscreen_toggle == 0 )
|
|
switch_to_windowed();
|
|
else
|
|
switch_to_fullscreen();
|
|
bx_gui.show_headerbar();
|
|
bx_gui.flush();
|
|
break;
|
|
}
|
|
|
|
// convert scancode->bochs code
|
|
if( sdl_event.key.keysym.scancode > _SCN2BX_LAST_ ) break;
|
|
key_event = scancodes2bx[ FIX_SDL_SCANCODE(sdl_event.key.keysym.scancode) ][1];
|
|
if( key_event == 0 ) break;
|
|
bx_devices.keyboard->gen_scancode( key_event );
|
|
break;
|
|
|
|
case SDL_KEYUP:
|
|
|
|
// filter out release of Windows/Fullscreen toggle and unsupported keys
|
|
if( (sdl_event.key.keysym.sym != SDLK_SCROLLOCK)
|
|
&& (sdl_event.key.keysym.scancode < _SCN2BX_LAST_ ))
|
|
{
|
|
// convert scancode->bochs code
|
|
key_event = scancodes2bx[ FIX_SDL_SCANCODE(sdl_event.key.keysym.scancode) ][1];
|
|
if( key_event == 0 ) break;
|
|
bx_devices.keyboard->gen_scancode( key_event | BX_KEY_RELEASED );
|
|
}
|
|
break;
|
|
|
|
case SDL_QUIT:
|
|
LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
|
|
BX_PANIC (("User requested shutdown."));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void bx_gui_c::flush(void)
|
|
{
|
|
if( sdl_screen )
|
|
SDL_UpdateRect( sdl_screen,0,0,res_x,res_y+headerbar_height );
|
|
else
|
|
SDL_UpdateRect( sdl_fullscreen,0,0,res_x,res_y);
|
|
}
|
|
|
|
|
|
void bx_gui_c::clear_screen(void)
|
|
{
|
|
int i = res_y, j;
|
|
Uint32 color;
|
|
Uint32 *buf, *buf_row;
|
|
Uint32 disp;
|
|
|
|
if( sdl_screen )
|
|
{
|
|
color = SDL_MapRGB( sdl_screen->format, 0,0,0 );
|
|
disp = sdl_screen->pitch/4;
|
|
buf = (Uint32 *)sdl_screen->pixels + headerbar_height*disp;
|
|
}
|
|
else if( sdl_fullscreen )
|
|
{
|
|
color = SDL_MapRGB( sdl_fullscreen->format, 0,0,0 );
|
|
disp = sdl_fullscreen->pitch/4;
|
|
buf = (Uint32 *)sdl_fullscreen->pixels;
|
|
}
|
|
else return;
|
|
|
|
do
|
|
{
|
|
buf_row = buf;
|
|
j = res_x;
|
|
while( j-- ) *buf++ = color;
|
|
buf = buf_row + disp;
|
|
} while( --i );
|
|
|
|
if( sdl_screen )
|
|
SDL_UpdateRect(sdl_screen,0,0,res_x,res_y+headerbar_height);
|
|
else
|
|
SDL_UpdateRect(sdl_fullscreen,0,0,res_x,res_y);
|
|
}
|
|
|
|
|
|
|
|
Boolean bx_gui_c::palette_change(
|
|
unsigned index,
|
|
unsigned red,
|
|
unsigned green,
|
|
unsigned blue)
|
|
{
|
|
unsigned char palred = red & 0xFF;
|
|
unsigned char palgreen = green & 0xFF;
|
|
unsigned char palblue = blue & 0xFF;
|
|
|
|
if( index > 255 ) return 0;
|
|
|
|
if( sdl_screen )
|
|
palette[index] = SDL_MapRGB( sdl_screen->format, palred, palgreen, palblue );
|
|
else if( sdl_fullscreen )
|
|
palette[index] = SDL_MapRGB( sdl_fullscreen->format, palred, palgreen, palblue );
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
void bx_gui_c::dimension_update(
|
|
unsigned x,
|
|
unsigned y,
|
|
unsigned fheight)
|
|
{
|
|
// TODO: remove this stupid check whenever the vga driver is fixed
|
|
if( y == 208 ) y = 200;
|
|
|
|
if( fheight > 0 )
|
|
{
|
|
fontheight = fheight;
|
|
fontwidth = 8;
|
|
}
|
|
|
|
if( (x == res_x) && (y == res_y )) return;
|
|
|
|
if( sdl_screen )
|
|
{
|
|
SDL_FreeSurface( sdl_screen );
|
|
sdl_screen = NULL;
|
|
}
|
|
if( sdl_fullscreen )
|
|
{
|
|
SDL_FreeSurface( sdl_fullscreen );
|
|
sdl_fullscreen = NULL;
|
|
}
|
|
|
|
if( sdl_fullscreen_toggle == 0 )
|
|
{
|
|
sdl_screen = SDL_SetVideoMode( x, y+headerbar_height, 32, SDL_SWSURFACE );
|
|
if( !sdl_screen )
|
|
{
|
|
LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
|
|
BX_PANIC (("Unable to set requested videomode: %ix%i: %s",x,y,SDL_GetError()));
|
|
}
|
|
headerbar_fg = SDL_MapRGB(
|
|
sdl_screen->format,
|
|
BX_HEADERBAR_FG_RED,
|
|
BX_HEADERBAR_FG_GREEN,
|
|
BX_HEADERBAR_FG_BLUE );
|
|
headerbar_bg = SDL_MapRGB(
|
|
sdl_screen->format,
|
|
BX_HEADERBAR_BG_RED,
|
|
BX_HEADERBAR_BG_GREEN,
|
|
BX_HEADERBAR_BG_BLUE );
|
|
}
|
|
else
|
|
{
|
|
sdl_fullscreen = SDL_SetVideoMode( x, y, 32, SDL_HWSURFACE|SDL_FULLSCREEN );
|
|
if( !sdl_fullscreen )
|
|
{
|
|
LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
|
|
BX_PANIC (("Unable to set requested videomode: %ix%i: %s",x,y,SDL_GetError()));
|
|
}
|
|
}
|
|
res_x = x;
|
|
res_y = y;
|
|
if( fheight > 0 )
|
|
{
|
|
textres_x = x / fontwidth;
|
|
textres_y = y / fontheight;
|
|
}
|
|
bx_gui.show_headerbar();
|
|
}
|
|
|
|
|
|
unsigned bx_gui_c::create_bitmap(
|
|
const unsigned char *bmap,
|
|
unsigned xdim,
|
|
unsigned ydim)
|
|
{
|
|
bitmaps *tmp = new bitmaps;
|
|
Uint32 *buf, *buf_row;
|
|
Uint32 disp;
|
|
unsigned char pixels;
|
|
|
|
if (n_sdl_bitmaps >= MAX_SDL_BITMAPS) {
|
|
BX_PANIC (("too many SDL bitmaps. To fix, increase MAX_SDL_BITMAPS"));
|
|
return 0;
|
|
}
|
|
|
|
tmp->surface = SDL_CreateRGBSurface(
|
|
SDL_SWSURFACE,
|
|
xdim,
|
|
ydim,
|
|
32,
|
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
|
0xff000000,
|
|
0x00ff0000,
|
|
0x0000ff00,
|
|
0x00000000
|
|
#else
|
|
0x000000ff,
|
|
0x0000ff00,
|
|
0x00ff0000,
|
|
0x00000000
|
|
#endif
|
|
);
|
|
if( !tmp->surface )
|
|
{
|
|
delete tmp;
|
|
bx_gui.exit();
|
|
LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
|
|
BX_PANIC (("Unable to create requested bitmap"));
|
|
}
|
|
tmp->src.w = xdim;
|
|
tmp->src.h = ydim;
|
|
tmp->src.x = 0;
|
|
tmp->src.y = 0;
|
|
tmp->dst.x = -1;
|
|
tmp->dst.y = 0;
|
|
tmp->dst.w = xdim;
|
|
tmp->dst.h = ydim;
|
|
tmp->cb = NULL;
|
|
buf = (Uint32 *)tmp->surface->pixels;
|
|
disp = tmp->surface->pitch/4;
|
|
do
|
|
{
|
|
buf_row = buf;
|
|
xdim = tmp->src.w / 8;
|
|
do
|
|
{
|
|
pixels = *bmap++;
|
|
for(unsigned i=0;i<8;i++)
|
|
{
|
|
if( (pixels & 0x01) == 0 )
|
|
*buf++ = headerbar_bg;
|
|
else
|
|
*buf++ = headerbar_fg;
|
|
pixels = pixels >> 1;
|
|
}
|
|
} while( --xdim );
|
|
buf = buf_row + disp;
|
|
} while( --ydim );
|
|
SDL_UpdateRect(
|
|
tmp->surface,
|
|
0, 0,
|
|
tmp->src.w,
|
|
tmp->src.h );
|
|
sdl_bitmaps[n_sdl_bitmaps] = tmp;
|
|
return n_sdl_bitmaps++;
|
|
}
|
|
|
|
|
|
unsigned bx_gui_c::headerbar_bitmap(
|
|
unsigned bmap_id,
|
|
unsigned alignment,
|
|
void (*f)(void))
|
|
{
|
|
unsigned hb_index;
|
|
|
|
if( bmap_id >= (unsigned)n_sdl_bitmaps ) return 0;
|
|
|
|
if ( (bx_headerbar_entries+1) > BX_MAX_HEADERBAR_ENTRIES )
|
|
BX_PANIC(("too many headerbar entries, increase BX_MAX_HEADERBAR_ENTRIES"));
|
|
|
|
bx_headerbar_entries++;
|
|
hb_index = bx_headerbar_entries - 1;
|
|
|
|
hb_entry[hb_index].bmp_id = bmap_id;
|
|
hb_entry[hb_index].alignment = alignment;
|
|
hb_entry[hb_index].f = f;
|
|
if (alignment == BX_GRAVITY_LEFT) {
|
|
sdl_bitmaps[bmap_id]->dst.x = bx_bitmap_left_xorigin;
|
|
bx_bitmap_left_xorigin += sdl_bitmaps[bmap_id]->src.w;
|
|
} else {
|
|
bx_bitmap_right_xorigin += sdl_bitmaps[bmap_id]->src.w;
|
|
sdl_bitmaps[bmap_id]->dst.x = bx_bitmap_right_xorigin;
|
|
}
|
|
return hb_index;
|
|
}
|
|
|
|
|
|
void bx_gui_c::replace_bitmap(
|
|
unsigned hbar_id,
|
|
unsigned bmap_id)
|
|
{
|
|
SDL_Rect hb_dst;
|
|
unsigned old_id;
|
|
|
|
old_id = hb_entry[hbar_id].bmp_id;
|
|
hb_dst = sdl_bitmaps[old_id]->dst;
|
|
sdl_bitmaps[old_id]->dst.x = -1;
|
|
hb_entry[hbar_id].bmp_id = bmap_id;
|
|
sdl_bitmaps[bmap_id]->dst.x = hb_dst.x;
|
|
if( sdl_bitmaps[bmap_id]->dst.x != -1 )
|
|
{
|
|
if (hb_entry[hbar_id].alignment == BX_GRAVITY_RIGHT) {
|
|
hb_dst.x = res_x - hb_dst.x;
|
|
}
|
|
SDL_BlitSurface(
|
|
sdl_bitmaps[bmap_id]->surface,
|
|
&sdl_bitmaps[bmap_id]->src,
|
|
sdl_screen,
|
|
&hb_dst);
|
|
SDL_UpdateRect(
|
|
sdl_screen,
|
|
hb_dst.x,
|
|
sdl_bitmaps[bmap_id]->dst.y,
|
|
sdl_bitmaps[bmap_id]->src.w,
|
|
sdl_bitmaps[bmap_id]->src.h );
|
|
}
|
|
}
|
|
|
|
|
|
void bx_gui_c::show_headerbar(void)
|
|
{
|
|
Uint32 *buf;
|
|
Uint32 *buf_row;
|
|
Uint32 disp;
|
|
int rowsleft = headerbar_height;
|
|
int colsleft;
|
|
int bitmapscount = bx_headerbar_entries;
|
|
unsigned current_bmp;
|
|
SDL_Rect hb_dst;
|
|
|
|
if( !sdl_screen ) return;
|
|
disp = sdl_screen->pitch/4;
|
|
buf = (Uint32 *)sdl_screen->pixels;
|
|
|
|
// draw headerbar background
|
|
do
|
|
{
|
|
colsleft = res_x;
|
|
buf_row = buf;
|
|
do
|
|
{
|
|
*buf++ = headerbar_bg;
|
|
} while( --colsleft );
|
|
buf = buf_row + disp;
|
|
} while( --rowsleft );
|
|
SDL_UpdateRect( sdl_screen, 0,0,res_x,headerbar_height);
|
|
|
|
we_are_here();
|
|
// go thru the bitmaps and display the active ones
|
|
while( bitmapscount-- )
|
|
{
|
|
current_bmp = hb_entry[bitmapscount].bmp_id;
|
|
if( sdl_bitmaps[current_bmp]->dst.x != -1 )
|
|
{
|
|
hb_dst = sdl_bitmaps[current_bmp]->dst;
|
|
if (hb_entry[bitmapscount].alignment == BX_GRAVITY_RIGHT) {
|
|
hb_dst.x = res_x - hb_dst.x;
|
|
}
|
|
SDL_BlitSurface(
|
|
sdl_bitmaps[current_bmp]->surface,
|
|
&sdl_bitmaps[current_bmp]->src,
|
|
sdl_screen,
|
|
&hb_dst);
|
|
SDL_UpdateRect(
|
|
sdl_screen,
|
|
hb_dst.x,
|
|
sdl_bitmaps[current_bmp]->dst.y,
|
|
sdl_bitmaps[current_bmp]->src.w,
|
|
sdl_bitmaps[current_bmp]->src.h );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void bx_gui_c::mouse_enabled_changed_specific (Boolean val)
|
|
{
|
|
if( val == 1 )
|
|
{
|
|
SDL_ShowCursor(0);
|
|
SDL_WM_GrabInput(SDL_GRAB_ON);
|
|
}
|
|
else
|
|
{
|
|
SDL_ShowCursor(1);
|
|
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
|
}
|
|
sdl_grab = val;
|
|
}
|
|
|
|
|
|
void headerbar_click(int x)
|
|
{
|
|
int xdim,xorigin;
|
|
|
|
for (unsigned i=0; i<bx_headerbar_entries; i++) {
|
|
xdim = sdl_bitmaps[hb_entry[i].bmp_id]->src.w;
|
|
if (hb_entry[i].alignment == BX_GRAVITY_LEFT)
|
|
xorigin = sdl_bitmaps[hb_entry[i].bmp_id]->dst.x;
|
|
else
|
|
xorigin = res_x - sdl_bitmaps[hb_entry[i].bmp_id]->dst.x;
|
|
if ( (x>=xorigin) && (x<(xorigin+xdim)) ) {
|
|
hb_entry[i].f();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void bx_gui_c::exit(void)
|
|
{
|
|
if( sdl_screen )
|
|
SDL_FreeSurface(sdl_screen);
|
|
if( sdl_fullscreen )
|
|
SDL_FreeSurface(sdl_fullscreen);
|
|
while( n_sdl_bitmaps )
|
|
{
|
|
SDL_FreeSurface( sdl_bitmaps[n_sdl_bitmaps-1]->surface );
|
|
n_sdl_bitmaps--;
|
|
}
|
|
}
|
|
|