2002-04-18 00:22:20 +00:00
/////////////////////////////////////////////////////////////////
//
// gui/wx.cc
2002-04-18 18:36:02 +00:00
// $Id: wx.cc,v 1.3 2002-04-18 18:36:02 vruppert Exp $
2002-04-18 00:22:20 +00:00
//
// wxWindows VGA display for Bochs. wx.cc implements a custom
// wxPanel called a MyPanel, which has methods to display
// text and VGA graphics on the panel. Normally, a MyPanel
// is instantiated within a MyFrame created by wxmain.cc, but
// this is not a requirement.
//
// The separation between wxmain.cc and wx.cc is as follows:
// - wx.cc implements a VGA display screen using wxWindows. It is
// is the wxWindows equivalent of x.cc, win32.cc, macos.cc, etc.
// wx.cc includes bochs.h and has access to all Bochs devices.
// The VGA panel accepts only paint, key, and mouse events. As it
// receives events, it builds BxEvents and places them into a
// thread-safe BxEvent queue. The simulation thread periodically
// processes events from the BxEvent queue (bx_gui_c::handle_events)
// and notifies the appropriate emulated I/O device.
// - wxmain.cc implements a Bochs configuration interface, which is
// the wxWindows equivalent of control.cc. wxmain creates a
// frame with several menus and a toolbar, and allows the user to
// choose the machine configuration and start the simulation.
//
/////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
// includes
//////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx/wx.h".
# include "wx/wxprec.h"
# ifdef __BORLANDC__
# pragma hdrstop
# endif
# ifndef WX_PRECOMP
# include "wx/wx.h"
# endif
# include "wx/image.h"
# include "bochs.h"
# include "gui/icon_bochs.h"
# include "osdep.h"
# include "font/vga.bitmap.h"
// shared elements between wxmain.cc and this file
# include "wxmain.h"
//////////////////////////////////////////////////////////////
// constants
//////////////////////////////////////////////////////////////
# define LOG_THIS bx_gui.
//////////////////////////////////////////////////////////////
// data for wx gui
//////////////////////////////////////////////////////////////
static char * wxScreen = NULL ;
wxCriticalSection wxScreen_lock ;
static long wxScreenX = 0 ;
static long wxScreenY = 0 ;
static long wxTileX = 0 ;
static long wxTileY = 0 ;
static unsigned long wxCursorX = 0 ;
static unsigned long wxCursorY = 0 ;
static unsigned long wxMouseCaptured = 0 ;
struct {
unsigned char red ;
unsigned char green ;
unsigned char blue ;
} wxBochsPalette [ 256 ] ;
wxCriticalSection event_thread_lock ;
BxEvent event_queue [ MAX_EVENTS ] ;
unsigned long num_events = 0 ;
//////////////////////////////////////////////////////////////
// and now, the code
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
// define the MyPanel which implements the VGA screen
//////////////////////////////////////////////////////////////
BEGIN_EVENT_TABLE ( MyPanel , wxPanel )
EVT_KEY_DOWN ( MyPanel : : OnKeyDown )
EVT_KEY_UP ( MyPanel : : OnKeyUp )
EVT_PAINT ( MyPanel : : OnPaint )
END_EVENT_TABLE ( )
void MyPanel : : OnPaint ( wxPaintEvent & WXUNUSED ( event ) )
{
wxPaintDC dc ( this ) ;
//PrepareDC(dc);
wxCriticalSectionLocker lock ( wxScreen_lock ) ;
IFDBG_VGA ( wxLogDebug ( " MyPanel::OnPaint called with wxScreen = %p " , wxScreen ) ) ;
if ( wxScreen ! = NULL ) {
wxPoint pt = GetClientAreaOrigin ( ) ;
wxImage screenImage ( wxScreenX , wxScreenY , ( unsigned char * ) wxScreen , TRUE ) ;
dc . DrawBitmap ( screenImage . ConvertToBitmap ( ) , pt . x , pt . y , FALSE ) ;
}
}
void
MyPanel : : MyRefresh ( )
{
# if defined(__WXMSW__)
// For some reason, on windows the postevent trick does not
// cause a paint event.
Refresh ( FALSE ) ;
# else
wxPaintEvent event ;
wxPostEvent ( this , event ) ;
# endif
}
void MyPanel : : OnKeyDown ( wxKeyEvent & event )
{
if ( event . GetKeyCode ( ) = = WXK_F12 ) {
if ( wxMouseCaptured ) {
ReleaseMouse ( ) ;
wxMouseCaptured = FALSE ;
} else {
CaptureMouse ( ) ;
wxMouseCaptured = TRUE ;
}
return ;
}
wxCriticalSectionLocker lock ( event_thread_lock ) ;
if ( num_events < MAX_EVENTS ) {
event_queue [ num_events ] . type = BX_ASYNC_EVT_KEY ;
fillBxKeyEvent ( event , event_queue [ num_events ] . u . key , false ) ;
num_events + + ;
}
}
void MyPanel : : OnKeyUp ( wxKeyEvent & event )
{
wxCriticalSectionLocker lock ( event_thread_lock ) ;
if ( num_events < MAX_EVENTS ) {
event_queue [ num_events ] . type = BX_ASYNC_EVT_KEY ;
fillBxKeyEvent ( event , event_queue [ num_events ] . u . key , true ) ;
num_events + + ;
}
}
/// copied right out of gui/x.cc
static char
wxAsciiKey [ 0x5f ] = {
// !"#$%&'
BX_KEY_SPACE ,
BX_KEY_1 ,
BX_KEY_SINGLE_QUOTE ,
BX_KEY_3 ,
BX_KEY_4 ,
BX_KEY_5 ,
BX_KEY_7 ,
BX_KEY_SINGLE_QUOTE ,
// ()*+,-./
BX_KEY_9 ,
BX_KEY_0 ,
BX_KEY_8 ,
BX_KEY_EQUALS ,
BX_KEY_COMMA ,
BX_KEY_MINUS ,
BX_KEY_PERIOD ,
BX_KEY_SLASH ,
// 01234567
BX_KEY_0 ,
BX_KEY_1 ,
BX_KEY_2 ,
BX_KEY_3 ,
BX_KEY_4 ,
BX_KEY_5 ,
BX_KEY_6 ,
BX_KEY_7 ,
// 89:;<=>?
BX_KEY_8 ,
BX_KEY_9 ,
BX_KEY_SEMICOLON ,
BX_KEY_SEMICOLON ,
BX_KEY_COMMA ,
BX_KEY_EQUALS ,
BX_KEY_PERIOD ,
BX_KEY_SLASH ,
// @ABCDEFG
BX_KEY_2 ,
BX_KEY_A ,
BX_KEY_B ,
BX_KEY_C ,
BX_KEY_D ,
BX_KEY_E ,
BX_KEY_F ,
BX_KEY_G ,
// HIJKLMNO
BX_KEY_H ,
BX_KEY_I ,
BX_KEY_J ,
BX_KEY_K ,
BX_KEY_L ,
BX_KEY_M ,
BX_KEY_N ,
BX_KEY_O ,
// PQRSTUVW
BX_KEY_P ,
BX_KEY_Q ,
BX_KEY_R ,
BX_KEY_S ,
BX_KEY_T ,
BX_KEY_U ,
BX_KEY_V ,
BX_KEY_W ,
// XYZ[\]^_
BX_KEY_X ,
BX_KEY_Y ,
BX_KEY_Z ,
BX_KEY_LEFT_BRACKET ,
BX_KEY_BACKSLASH ,
BX_KEY_RIGHT_BRACKET ,
BX_KEY_6 ,
BX_KEY_MINUS ,
// `abcdefg
BX_KEY_GRAVE ,
BX_KEY_A ,
BX_KEY_B ,
BX_KEY_C ,
BX_KEY_D ,
BX_KEY_E ,
BX_KEY_F ,
BX_KEY_G ,
// hijklmno
BX_KEY_H ,
BX_KEY_I ,
BX_KEY_J ,
BX_KEY_K ,
BX_KEY_L ,
BX_KEY_M ,
BX_KEY_N ,
BX_KEY_O ,
// pqrstuvw
BX_KEY_P ,
BX_KEY_Q ,
BX_KEY_R ,
BX_KEY_S ,
BX_KEY_T ,
BX_KEY_U ,
BX_KEY_V ,
BX_KEY_W ,
// xyz{|}~
BX_KEY_X ,
BX_KEY_Y ,
BX_KEY_Z ,
BX_KEY_LEFT_BRACKET ,
BX_KEY_BACKSLASH ,
BX_KEY_RIGHT_BRACKET ,
BX_KEY_GRAVE
} ;
// MS Windows specific key mapping, which uses wxKeyEvent::m_rawCode & 2.
Boolean
MyPanel : : fillBxKeyEvent_MSW ( wxKeyEvent & wxev , BxKeyEvent & bxev , Boolean release )
{
# if defined(wxHAS_RAW_KEY_CODES) && defined(__WXMSW__)
IFDBG_KEY ( wxLogDebug ( " fillBxKeyEvent_MSW. key code %d, raw codes %d %d " , wxev . m_keyCode , wxev . m_rawCode , wxev . m_rawFlags ) ) ;
// this code was grabbed from gui/win32.cpp
Bit32u lParam = wxev . m_rawFlags ;
Bit32u key = HIWORD ( lParam ) & 0x01FF ;
bxev . bx_key = 0x0000 ;
if ( ( ( key & 0x0100 ) & & ( ( key & 0x01ff ) ! = 0x0145 ) ) | ( ( key & 0x01ff ) = = 0x45 ) ) {
// Its an extended key
bxev . bx_key = 0xE000 ;
}
// Its a key
bxev . bx_key | = ( key & 0x00FF ) | ( release ? 0x80 : 0x00 ) ;
bxev . raw_scancode = true ;
return true ;
# else
return false ;
# endif
}
# if defined (wxHAS_RAW_KEY_CODES) && defined(__WXGTK__)
// get those keysym definitions
# include <gdk/gdkkeysyms.h>
# endif
// GTK specific key mapping, which uses wxKeyEvent::m_rawCode.
Boolean
MyPanel : : fillBxKeyEvent_GTK ( wxKeyEvent & wxev , BxKeyEvent & bxev , Boolean release )
{
# if defined (wxHAS_RAW_KEY_CODES) && defined(__WXGTK__)
IFDBG_KEY ( wxLogDebug ( " fillBxKeyEvent_GTK. key code %d, raw codes %d %d " , wxev . m_keyCode , wxev . m_rawCode , wxev . m_rawFlags ) ) ;
// GTK has only 16bit key codes
Bit16u keysym = ( Bit32u ) wxev . m_rawCode ;
Bit32u bx_key = 0 ;
// since the GDK_* symbols are very much like the X11 symbols (possibly
// identical), I'm using code that is copied from gui/x.cc.
if ( keysym > = GDK_space & & keysym < GDK_asciitilde ) {
// use nice ASCII conversion table, based on x.cc
bx_key = wxAsciiKey [ keysym - GDK_space ] ;
} else switch ( keysym ) {
case GDK_KP_1 :
# ifdef GDK_KP_End
case GDK_KP_End :
# endif
bx_key = BX_KEY_KP_END ; break ;
case GDK_KP_2 :
# ifdef GDK_KP_Down
case GDK_KP_Down :
# endif
bx_key = BX_KEY_KP_DOWN ; break ;
case GDK_KP_3 :
# ifdef GDK_KP_Page_Down
case GDK_KP_Page_Down :
# endif
bx_key = BX_KEY_KP_PAGE_DOWN ; break ;
case GDK_KP_4 :
# ifdef GDK_KP_Left
case GDK_KP_Left :
# endif
bx_key = BX_KEY_KP_LEFT ; break ;
case GDK_KP_5 :
bx_key = BX_KEY_KP_5 ; break ;
case GDK_KP_6 :
# ifdef GDK_KP_Right
case GDK_KP_Right :
# endif
bx_key = BX_KEY_KP_RIGHT ; break ;
case GDK_KP_7 :
# ifdef GDK_KP_Home
case GDK_KP_Home :
# endif
bx_key = BX_KEY_KP_HOME ; break ;
case GDK_KP_8 :
# ifdef GDK_KP_Up
case GDK_KP_Up :
# endif
bx_key = BX_KEY_KP_UP ; break ;
case GDK_KP_9 :
# ifdef GDK_KP_Page_Up
case GDK_KP_Page_Up :
# endif
bx_key = BX_KEY_KP_PAGE_UP ; break ;
case GDK_KP_0 :
# ifdef GDK_KP_Insert
case GDK_KP_Insert :
# endif
bx_key = BX_KEY_KP_INSERT ; break ;
case GDK_KP_Decimal :
# ifdef GDK_KP_Delete
case GDK_KP_Delete :
# endif
bx_key = BX_KEY_KP_DELETE ; break ;
# ifdef GDK_KP_Enter
case GDK_KP_Enter :
bx_key = BX_KEY_KP_ENTER ; break ;
# endif
case GDK_KP_Subtract : bx_key = BX_KEY_KP_SUBTRACT ; break ;
case GDK_KP_Add : bx_key = BX_KEY_KP_ADD ; break ;
case GDK_KP_Multiply : bx_key = BX_KEY_KP_MULTIPLY ; break ;
case GDK_KP_Divide : bx_key = BX_KEY_KP_DIVIDE ; break ;
case GDK_Up : bx_key = BX_KEY_UP ; break ;
case GDK_Down : bx_key = BX_KEY_DOWN ; break ;
case GDK_Left : bx_key = BX_KEY_LEFT ; break ;
case GDK_Right : bx_key = BX_KEY_RIGHT ; break ;
case GDK_Delete : bx_key = BX_KEY_DELETE ; break ;
case GDK_BackSpace : bx_key = BX_KEY_BACKSPACE ; break ;
case GDK_Tab : bx_key = BX_KEY_TAB ; break ;
case GDK_Return : bx_key = BX_KEY_ENTER ; break ;
case GDK_Escape : bx_key = BX_KEY_ESC ; break ;
case GDK_F1 : bx_key = BX_KEY_F1 ; break ;
case GDK_F2 : bx_key = BX_KEY_F2 ; break ;
case GDK_F3 : bx_key = BX_KEY_F3 ; break ;
case GDK_F4 : bx_key = BX_KEY_F4 ; break ;
case GDK_F5 : bx_key = BX_KEY_F5 ; break ;
case GDK_F6 : bx_key = BX_KEY_F6 ; break ;
case GDK_F7 : bx_key = BX_KEY_F7 ; break ;
case GDK_F8 : bx_key = BX_KEY_F8 ; break ;
case GDK_F9 : bx_key = BX_KEY_F9 ; break ;
case GDK_F10 : bx_key = BX_KEY_F10 ; break ;
case GDK_F11 : bx_key = BX_KEY_F11 ; break ;
case GDK_F12 : bx_key = BX_KEY_F12 ; break ;
case GDK_Control_L : bx_key = BX_KEY_CTRL_L ; break ;
case GDK_Shift_L : bx_key = BX_KEY_SHIFT_L ; break ;
case GDK_Shift_R : bx_key = BX_KEY_SHIFT_R ; break ;
case GDK_Caps_Lock : bx_key = BX_KEY_CAPS_LOCK ; break ;
case GDK_Num_Lock : bx_key = BX_KEY_NUM_LOCK ; break ;
case GDK_Alt_L : bx_key = BX_KEY_ALT_L ; break ;
case GDK_Insert : bx_key = BX_KEY_INSERT ; break ;
case GDK_Home : bx_key = BX_KEY_HOME ; break ;
case GDK_End : bx_key = BX_KEY_END ; break ;
case GDK_Page_Up : bx_key = BX_KEY_PAGE_UP ; break ;
case GDK_Page_Down : bx_key = BX_KEY_PAGE_DOWN ; break ;
default :
wxLogError ( " fillBxKeyEvent_GTK(): keysym %x unhandled! " , ( unsigned ) keysym ) ;
return BX_KEY_UNHANDLED ;
}
bxev . bx_key = bx_key | ( release ? BX_KEY_RELEASED : BX_KEY_PRESSED ) ;
bxev . raw_scancode = false ;
return true ;
# else // if GTK toolkit
return false ;
# endif
}
Boolean
MyPanel : : fillBxKeyEvent ( wxKeyEvent & wxev , BxKeyEvent & bxev , Boolean release )
{
// Use raw codes if they are available. Raw codes are a nonstandard addition
// to the wxWindows library. At present, the only way to use the "RAW_CODES"
// mode is to apply Bryce's "patch.wx-raw-keycodes" patch to the wxWindows
// sources and recompile. This patch, or something like it, should appear in
// future wxWindows versions.
# if defined (wxHAS_RAW_KEY_CODES) && defined(__WXMSW__)
return fillBxKeyEvent_MSW ( wxev , bxev , release ) ;
# endif
# if defined (wxHAS_RAW_KEY_CODES) && defined(__WXGTK__)
return fillBxKeyEvent_GTK ( wxev , bxev , release ) ;
# endif
// otherwise fall back to using portable WXK_* keycodes. Not all keys
// can be mapped correctly using WXK_* codes but it should be usable.
IFDBG_KEY ( wxLogDebug ( " fillBxKeyEvent. key code %d " , wxev . m_keyCode ) ) ;
Bit32u key = wxev . m_keyCode ;
Bit32u bx_key ;
if ( key > = WXK_SPACE & & key < WXK_DELETE ) {
bx_key = wxAsciiKey [ key - WXK_SPACE ] ;
} else {
// handle extended keys here
switch ( key ) {
case WXK_BACK : bx_key = BX_KEY_BACKSPACE ; break ;
case WXK_TAB : bx_key = BX_KEY_TAB ; break ;
case WXK_RETURN : bx_key = BX_KEY_ENTER ; break ;
case WXK_ESCAPE : bx_key = BX_KEY_ESC ; break ;
case WXK_DELETE : bx_key = BX_KEY_DELETE ; break ;
case WXK_SHIFT : bx_key = BX_KEY_SHIFT_L ; break ;
case WXK_CONTROL : bx_key = BX_KEY_CTRL_L ; break ;
case WXK_ALT : bx_key = BX_KEY_ALT_L ; break ;
case WXK_MENU : bx_key = BX_KEY_MENU ; break ;
case WXK_PAUSE : bx_key = BX_KEY_PAUSE ; break ;
case WXK_PRIOR : bx_key = BX_KEY_PAGE_UP ; break ;
case WXK_NEXT : bx_key = BX_KEY_PAGE_DOWN ; break ;
case WXK_END : bx_key = BX_KEY_END ; break ;
case WXK_HOME : bx_key = BX_KEY_HOME ; break ;
case WXK_LEFT : bx_key = BX_KEY_LEFT ; break ;
case WXK_UP : bx_key = BX_KEY_UP ; break ;
case WXK_RIGHT : bx_key = BX_KEY_RIGHT ; break ;
case WXK_DOWN : bx_key = BX_KEY_DOWN ; break ;
case WXK_INSERT : bx_key = BX_KEY_INSERT ; break ;
case WXK_NUMPAD0 : bx_key = BX_KEY_KP_INSERT ; break ;
case WXK_NUMPAD1 : bx_key = BX_KEY_KP_END ; break ;
case WXK_NUMPAD2 : bx_key = BX_KEY_KP_DOWN ; break ;
case WXK_NUMPAD3 : bx_key = BX_KEY_KP_PAGE_DOWN ; break ;
case WXK_NUMPAD4 : bx_key = BX_KEY_KP_LEFT ; break ;
case WXK_NUMPAD5 : bx_key = BX_KEY_KP_5 ; break ;
case WXK_NUMPAD6 : bx_key = BX_KEY_KP_RIGHT ; break ;
case WXK_NUMPAD7 : bx_key = BX_KEY_KP_HOME ; break ;
case WXK_NUMPAD8 : bx_key = BX_KEY_KP_UP ; break ;
case WXK_NUMPAD9 : bx_key = BX_KEY_KP_PAGE_UP ; break ;
case WXK_F1 : bx_key = BX_KEY_F1 ; break ;
case WXK_F2 : bx_key = BX_KEY_F2 ; break ;
case WXK_F3 : bx_key = BX_KEY_F3 ; break ;
case WXK_F4 : bx_key = BX_KEY_F4 ; break ;
case WXK_F5 : bx_key = BX_KEY_F5 ; break ;
case WXK_F6 : bx_key = BX_KEY_F6 ; break ;
case WXK_F7 : bx_key = BX_KEY_F7 ; break ;
case WXK_F8 : bx_key = BX_KEY_F8 ; break ;
case WXK_F9 : bx_key = BX_KEY_F9 ; break ;
case WXK_F10 : bx_key = BX_KEY_F10 ; break ;
case WXK_F11 : bx_key = BX_KEY_F11 ; break ;
case WXK_F12 : bx_key = BX_KEY_F12 ; break ;
case WXK_NUMLOCK : bx_key = BX_KEY_NUM_LOCK ; break ;
case WXK_SCROLL : bx_key = BX_KEY_SCRL_LOCK ; break ;
case WXK_DECIMAL : bx_key = BX_KEY_PERIOD ; break ;
case WXK_SUBTRACT : bx_key = BX_KEY_MINUS ; break ;
case WXK_ADD : bx_key = BX_KEY_EQUALS ; break ;
case WXK_MULTIPLY : bx_key = BX_KEY_KP_MULTIPLY ; break ;
case WXK_DIVIDE : bx_key = BX_KEY_KP_DIVIDE ; break ;
case WXK_NUMPAD_ENTER : bx_key = BX_KEY_KP_ENTER ; break ;
case WXK_NUMPAD_HOME : bx_key = BX_KEY_KP_HOME ; break ;
case WXK_NUMPAD_LEFT : bx_key = BX_KEY_KP_LEFT ; break ;
case WXK_NUMPAD_UP : bx_key = BX_KEY_KP_UP ; break ;
case WXK_NUMPAD_RIGHT : bx_key = BX_KEY_KP_RIGHT ; break ;
case WXK_NUMPAD_DOWN : bx_key = BX_KEY_KP_DOWN ; break ;
case WXK_NUMPAD_PRIOR : bx_key = BX_KEY_KP_PAGE_UP ; break ;
case WXK_NUMPAD_PAGEUP : bx_key = BX_KEY_KP_PAGE_UP ; break ;
case WXK_NUMPAD_NEXT : bx_key = BX_KEY_KP_PAGE_DOWN ; break ;
case WXK_NUMPAD_PAGEDOWN : bx_key = BX_KEY_KP_PAGE_DOWN ; break ;
case WXK_NUMPAD_END : bx_key = BX_KEY_KP_END ; break ;
case WXK_NUMPAD_BEGIN : bx_key = BX_KEY_KP_HOME ; break ;
case WXK_NUMPAD_INSERT : bx_key = BX_KEY_KP_INSERT ; break ;
case WXK_NUMPAD_DELETE : bx_key = BX_KEY_KP_DELETE ; break ;
case WXK_NUMPAD_EQUAL : bx_key = BX_KEY_KP_ENTER ; break ;
case WXK_NUMPAD_MULTIPLY : bx_key = BX_KEY_KP_MULTIPLY ; break ;
case WXK_NUMPAD_SUBTRACT : bx_key = BX_KEY_KP_SUBTRACT ; break ;
case WXK_NUMPAD_DECIMAL : bx_key = BX_KEY_KP_DELETE ; break ;
case WXK_NUMPAD_DIVIDE : bx_key = BX_KEY_KP_DIVIDE ; break ;
// Keys not handled by wxMSW
case 192 : bx_key = BX_KEY_GRAVE ; break ; // `~
case 219 : bx_key = BX_KEY_LEFT_BRACKET ; break ; // [{
case 221 : bx_key = BX_KEY_RIGHT_BRACKET ; break ; // ]}
case 220 : bx_key = BX_KEY_BACKSLASH ; break ; // \|
case 186 : bx_key = BX_KEY_SEMICOLON ; break ; // ;:
case 222 : bx_key = BX_KEY_SINGLE_QUOTE ; break ; // '"
case 188 : bx_key = BX_KEY_COMMA ; break ; // ,<
case 191 : bx_key = BX_KEY_SLASH ; break ; // /?
default :
wxLogMessage ( " Unhandled key event: %i (0x%x) " , key , key ) ;
return 0 ;
}
}
IFDBG_KEY ( wxLogDebug ( " fillBxKeyEvent: after remapping, key=%d " , bx_key ) ) ;
bxev . bx_key = bx_key | ( release ? BX_KEY_RELEASED : BX_KEY_PRESSED ) ;
bxev . raw_scancode = false ;
return true ;
}
//////////////////////////////////////////////////////////////
// fill in methods of bx_gui
//////////////////////////////////////////////////////////////
void
bx_gui_c : : specific_init ( bx_gui_c * th , int argc , char * * argv , unsigned tilewidth , unsigned tileheight ,
unsigned headerbar_y )
{
th - > put ( " NGUI " ) ;
if ( bx_options . Oprivate_colormap - > get ( ) ) {
BX_INFO ( ( " private_colormap option ignored. " ) ) ;
}
for ( int i = 0 ; i < 256 ; i + + ) {
wxBochsPalette [ i ] . red = 0 ;
wxBochsPalette [ i ] . green = 0 ;
wxBochsPalette [ i ] . blue = 0 ;
}
wxScreenX = 640 ;
wxScreenY = 480 ;
wxCriticalSectionLocker lock ( wxScreen_lock ) ;
wxScreen = ( char * ) malloc ( wxScreenX * wxScreenY * 3 ) ;
memset ( wxScreen , 0 , wxScreenX * wxScreenY * 3 ) ;
wxTileX = tilewidth ;
wxTileY = tileheight ;
}
// ::HANDLE_EVENTS()
//
// Called periodically (vga_update_interval in .bochsrc) so the
// the gui code can poll for keyboard, mouse, and other
// relevant events.
void bx_gui_c : : handle_events ( void )
{
wxCriticalSectionLocker lock ( event_thread_lock ) ;
Bit32u bx_key = 0 ;
for ( unsigned int i = 0 ; i < num_events ; i + + ) {
switch ( event_queue [ i ] . type ) {
case BX_ASYNC_EVT_TOOLBAR :
switch ( event_queue [ i ] . u . toolbar . button ) {
case BX_TOOLBAR_FLOPPYA : floppyA_handler ( ) ; break ;
case BX_TOOLBAR_FLOPPYB : floppyB_handler ( ) ; break ;
case BX_TOOLBAR_CDROMD : cdromD_handler ( ) ; break ;
case BX_TOOLBAR_RESET : reset_handler ( ) ; break ;
case BX_TOOLBAR_POWER : power_handler ( ) ; break ;
case BX_TOOLBAR_COPY : copy_handler ( ) ; break ;
case BX_TOOLBAR_PASTE : paste_handler ( ) ; break ;
case BX_TOOLBAR_SNAPSHOT : snapshot_handler ( ) ; break ;
case BX_TOOLBAR_CONFIG : config_handler ( ) ; break ;
case BX_TOOLBAR_MOUSE_EN : toggle_mouse_enable ( ) ; break ;
default :
wxLogDebug ( " unknown toolbar id %d " , event_queue [ i ] . u . toolbar . button ) ;
}
break ;
case BX_ASYNC_EVT_KEY :
bx_key = event_queue [ i ] . u . key . bx_key ;
if ( event_queue [ i ] . u . key . raw_scancode ) {
// event contains raw scancodes: use put_scancode
Bit8u scancode ;
if ( bx_key & 0xFF00 ) { // for extended keys
scancode = 0xFF & ( bx_key > > 8 ) ;
IFDBG_KEY ( wxLogDebug ( " sending raw scancode 0x%02x (extended key) " , ( int ) scancode ) ) ;
bx_devices . keyboard - > put_scancode ( & scancode , 1 ) ;
}
scancode = 0xFF & bx_key ;
IFDBG_KEY ( wxLogDebug ( " sending raw scancode 0x%02x " , ( int ) scancode ) ) ;
bx_devices . keyboard - > put_scancode ( & scancode , 1 ) ;
} else {
// event contains BX_KEY_* codes: use gen_scancode
IFDBG_KEY ( wxLogDebug ( " sending key event 0x%02x " , bx_key ) ) ;
bx_devices . keyboard - > gen_scancode ( bx_key ) ;
}
break ;
default :
wxLogError ( " handle_events received unhandled event type %d in queue " , ( int ) event_queue [ i ] . type ) ;
}
}
num_events = 0 ;
}
// ::FLUSH()
//
// Called periodically, requesting that the gui code flush all pending
// screen update requests.
void
bx_gui_c : : flush ( void )
{
}
// ::CLEAR_SCREEN()
//
// Called to request that the VGA region is cleared. Don't
// clear the area that defines the headerbar.
void
bx_gui_c : : clear_screen ( void )
{
wxCriticalSectionLocker lock ( wxScreen_lock ) ;
memset ( wxScreen , 0 , wxScreenX * wxScreenY * 3 ) ;
}
static void
UpdateScreen ( char * newBits , int x , int y , int width , int height )
{
wxCriticalSectionLocker lock ( wxScreen_lock ) ;
if ( wxScreen ! = NULL ) {
for ( int i = 0 ; i < height ; i + + ) {
for ( int c = 0 ; c < width ; c + + ) {
wxScreen [ ( y * wxScreenX * 3 ) + ( ( x + c ) * 3 ) ] = wxBochsPalette [ newBits [ ( i * width ) + c ] ] . red ;
wxScreen [ ( y * wxScreenX * 3 ) + ( ( x + c ) * 3 ) + 1 ] = wxBochsPalette [ newBits [ ( i * width ) + c ] ] . green ;
wxScreen [ ( y * wxScreenX * 3 ) + ( ( x + c ) * 3 ) + 2 ] = wxBochsPalette [ newBits [ ( i * width ) + c ] ] . blue ;
}
y + + ;
}
}
}
static void
DrawBochsBitmap ( int x , int y , int width , int height , char * bmap , char color )
{
char vgaPallet [ ] = { ( char ) 0x00 , //Black
( char ) 0x01 , //Dark Blue
( char ) 0x02 , //Dark Green
( char ) 0x03 , //Dark Cyan
( char ) 0x04 , //Dark Red
( char ) 0x05 , //Dark Magenta
( char ) 0x06 , //Brown
( char ) 0x07 , //Light Gray
( char ) 0x38 , //Dark Gray
( char ) 0x09 , //Light Blue
( char ) 0x12 , //Green
( char ) 0x1B , //Cyan
( char ) 0x24 , //Light Red
( char ) 0x2D , //Magenta
( char ) 0x36 , //Yellow
( char ) 0x3F //White
} ;
char bgcolor = vgaPallet [ ( color > > 4 ) & 0xF ] ;
char fgcolor = vgaPallet [ color & 0xF ] ;
char * newBits = ( char * ) malloc ( width * height ) ;
memset ( newBits , 0 , ( width * height ) ) ;
for ( int i = 0 ; i < ( width * height ) / 8 ; i + + ) {
newBits [ i * 8 + 0 ] = ( bmap [ i ] & 0x01 ) ? fgcolor : bgcolor ;
newBits [ i * 8 + 1 ] = ( bmap [ i ] & 0x02 ) ? fgcolor : bgcolor ;
newBits [ i * 8 + 2 ] = ( bmap [ i ] & 0x04 ) ? fgcolor : bgcolor ;
newBits [ i * 8 + 3 ] = ( bmap [ i ] & 0x08 ) ? fgcolor : bgcolor ;
newBits [ i * 8 + 4 ] = ( bmap [ i ] & 0x10 ) ? fgcolor : bgcolor ;
newBits [ i * 8 + 5 ] = ( bmap [ i ] & 0x20 ) ? fgcolor : bgcolor ;
newBits [ i * 8 + 6 ] = ( bmap [ i ] & 0x40 ) ? fgcolor : bgcolor ;
newBits [ i * 8 + 7 ] = ( bmap [ i ] & 0x80 ) ? fgcolor : bgcolor ;
}
UpdateScreen ( newBits , x , y , width , height ) ;
free ( newBits ) ;
}
// ::TEXT_UPDATE()
//
// Called in a VGA text mode, to update the screen with
// new content.
//
// old_text: array of character/attributes making up the contents
// of the screen from the last call. See below
// new_text: array of character/attributes making up the current
// contents, which should now be displayed. See below
//
// format of old_text & new_text: each is 4000 bytes long.
// This represents 80 characters wide by 25 high, with
// each character being 2 bytes. The first by is the
// character value, the second is the attribute byte.
// I currently don't handle the attribute byte.
//
// cursor_x: new x location of cursor
// cursor_y: new y location of cursor
void bx_gui_c : : text_update ( Bit8u * old_text , Bit8u * new_text ,
unsigned long cursor_x , unsigned long cursor_y ,
Bit16u cursor_state , unsigned nrows )
{
IFDBG_VGA ( wxLogDebug ( " text_update " ) ) ;
2002-04-18 18:36:02 +00:00
Bit8u cs_start = ( cursor_state > > 8 ) & 0x3f ;
Bit8u cs_end = cursor_state & 0x1f ;
2002-04-18 00:22:20 +00:00
unsigned char cChar ;
unsigned int nchars = 80 * nrows ;
if ( ( wxCursorY * 80 + wxCursorX ) < nchars ) {
cChar = new_text [ ( wxCursorY * 80 + wxCursorX ) * 2 ] ;
DrawBochsBitmap ( wxCursorX * 8 , wxCursorY * 16 , 8 , 16 , ( char * ) & bx_vgafont [ cChar ] . data , new_text [ ( ( wxCursorY * 80 + wxCursorX ) * 2 ) + 1 ] ) ;
}
for ( int i = 0 ; i < nchars * 2 ; i + = 2 ) {
if ( ( old_text [ i ] ! = new_text [ i ] ) | | ( old_text [ i + 1 ] ! = new_text [ i + 1 ] ) ) {
cChar = new_text [ i ] ;
int x = ( i / 2 ) % 80 ;
int y = ( i / 2 ) / 80 ;
DrawBochsBitmap ( x * 8 , y * 16 , 8 , 16 , ( char * ) & bx_vgafont [ cChar ] . data , new_text [ i + 1 ] ) ;
}
}
wxCursorX = cursor_x ;
wxCursorY = cursor_y ;
2002-04-18 18:36:02 +00:00
if ( ( ( cursor_y * 80 + cursor_x ) < nchars ) & & ( cs_start < = cs_end ) ) {
2002-04-18 00:22:20 +00:00
cChar = new_text [ ( cursor_y * 80 + cursor_x ) * 2 ] ;
char cAttr = new_text [ ( ( cursor_y * 80 + cursor_x ) * 2 ) + 1 ] ;
cAttr = ( ( cAttr > > 4 ) & 0xF ) + ( ( cAttr & 0xF ) < < 4 ) ;
DrawBochsBitmap ( wxCursorX * 8 , wxCursorY * 16 , 8 , 16 , ( char * ) & bx_vgafont [ cChar ] . data , cAttr ) ;
}
thePanel - > MyRefresh ( ) ;
}
// ::PALETTE_CHANGE()
//
// Allocate a color in the native GUI, for this color, and put
// it in the colormap location 'index'.
// returns: 0=no screen update needed (color map change has direct effect)
// 1=screen updated needed (redraw using current colormap)
Boolean
bx_gui_c : : palette_change ( unsigned index , unsigned red , unsigned green , unsigned blue )
{
IFDBG_VGA ( wxLogDebug ( " palette_change " ) ) ;
wxBochsPalette [ index ] . red = red ;
wxBochsPalette [ index ] . green = green ;
wxBochsPalette [ index ] . blue = blue ;
return ( 0 ) ;
}
// ::GRAPHICS_TILE_UPDATE()
//
// Called to request that a tile of graphics be drawn to the
// screen, since info in this region has changed.
//
// tile: array of 8bit values representing a block of pixels with
// dimension equal to the 'tilewidth' & 'tileheight' parameters to
// ::specific_init(). Each value specifies an index into the
// array of colors you allocated for ::palette_change()
// x0: x origin of tile
// y0: y origin of tile
//
// note: origin of tile and of window based on (0,0) being in the upper
// left of the window.
void bx_gui_c : : graphics_tile_update ( Bit8u * tile , unsigned x0 , unsigned y0 )
{
IFDBG_VGA ( wxLogDebug ( " graphics_tile_update " ) ) ;
UpdateScreen ( ( char * ) tile , x0 , y0 , wxTileX , wxTileY ) ;
//thePanel->MyRefresh ();
}
// ::DIMENSION_UPDATE()
//
// Called when the VGA mode changes it's X,Y dimensions.
// Resize the window to this size, but you need to add on
// the height of the headerbar to the Y value.
//
// x: new VGA x size
// y: new VGA y size (add headerbar_y parameter from ::specific_init().
void bx_gui_c : : dimension_update ( unsigned x , unsigned y )
{
IFDBG_VGA ( wxLogDebug ( " dimension_update " ) ) ;
wxCriticalSectionLocker lock ( wxScreen_lock ) ;
wxScreenX = x ;
wxScreenY = y ;
wxScreen = ( char * ) realloc ( wxScreen , wxScreenX * wxScreenY * 3 ) ;
wxASSERT ( wxScreen ! = NULL ) ;
//theFrame->SetSize(-1, -1, wxScreenX + 6, wxScreenY + 100, 0);
//wxSize size = theFrame->GetToolBar()->GetToolSize();
theFrame - > SetClientSize ( wxScreenX , wxScreenY ) ; // + size.GetHeight());
//thePanel->MyRefresh ();
}
// ::CREATE_BITMAP()
//
// Create a monochrome bitmap of size 'xdim' by 'ydim', which will
// be drawn in the headerbar. Return an integer ID to the bitmap,
// with which the bitmap can be referenced later.
//
// bmap: packed 8 pixels-per-byte bitmap. The pixel order is:
// bit0 is the left most pixel, bit7 is the right most pixel.
// xdim: x dimension of bitmap
// ydim: y dimension of bitmap
unsigned
bx_gui_c : : create_bitmap ( const unsigned char * bmap , unsigned xdim , unsigned ydim )
{
UNUSED ( bmap ) ;
UNUSED ( xdim ) ;
UNUSED ( ydim ) ;
return ( 0 ) ;
}
// ::HEADERBAR_BITMAP()
//
// Called to install a bitmap in the bochs headerbar (toolbar).
//
// bmap_id: will correspond to an ID returned from
// ::create_bitmap(). 'alignment' is either BX_GRAVITY_LEFT
// or BX_GRAVITY_RIGHT, meaning install the bitmap in the next
// available leftmost or rightmost space.
// alignment: is either BX_GRAVITY_LEFT or BX_GRAVITY_RIGHT,
// meaning install the bitmap in the next
// available leftmost or rightmost space.
// f: a 'C' function pointer to callback when the mouse is clicked in
// the boundaries of this bitmap.
unsigned
bx_gui_c : : headerbar_bitmap ( unsigned bmap_id , unsigned alignment , void ( * f ) ( void ) )
{
UNUSED ( bmap_id ) ;
UNUSED ( alignment ) ;
UNUSED ( f ) ;
return ( 0 ) ;
}
// ::SHOW_HEADERBAR()
//
// Show (redraw) the current headerbar, which is composed of
// currently installed bitmaps.
void
bx_gui_c : : show_headerbar ( void )
{
}
// ::REPLACE_BITMAP()
//
// Replace the bitmap installed in the headerbar ID slot 'hbar_id',
// with the one specified by 'bmap_id'. 'bmap_id' will have
// been generated by ::create_bitmap(). The old and new bitmap
// must be of the same size. This allows the bitmap the user
// sees to change, when some action occurs. For example when
// the user presses on the floppy icon, it then displays
// the ejected status.
//
// hbar_id: headerbar slot ID
// bmap_id: bitmap ID
void
bx_gui_c : : replace_bitmap ( unsigned hbar_id , unsigned bmap_id )
{
UNUSED ( hbar_id ) ;
UNUSED ( bmap_id ) ;
}
// ::EXIT()
//
// Called before bochs terminates, to allow for a graceful
// exit from the native GUI mechanism.
void
bx_gui_c : : exit ( void )
{
BX_INFO ( ( " bx_gui_c::exit() not implemented yet. " ) ) ;
}
void
bx_gui_c : : mouse_enabled_changed_specific ( Boolean val )
{
}
int
bx_gui_c : : get_clipboard_text ( Bit8u * * bytes , Bit32s * nbytes )
{
UNUSED ( bytes ) ;
UNUSED ( nbytes ) ;
return 0 ;
}
int
bx_gui_c : : set_clipboard_text ( char * text_snapshot , Bit32u len )
{
UNUSED ( text_snapshot ) ;
UNUSED ( len ) ;
return 0 ;
}
#if 0
//////////////
/*
This is basically the old wx . cc from June 2001.
In March 2002 , when Psyon and I started working on wxWindows again ,
the wx . cc was crashing and I didn ' t understand why . So I started
over again in wxmain . cc , and we hacked it until it worked .
*/
// For compilers that support precompilation, includes "wx/wx.h".
# include "wx/wxprec.h"
# include <wx/scrolwin.h>
# ifdef __BORLANDC__
# pragma hdrstop
# endif
# ifndef WX_PRECOMP
# include "wx/wx.h"
# endif
# include "config.h"
extern " C " {
// siminterface needs stdio.h
# include <stdio.h>
}
# include "osdep.h"
# include "control.h"
# include "siminterface.h"
# include "gui/wx.h"
// I wanted to make this a static member of ParamEditor, but it gave me
// link errors so I just put it outside for now.
wxHashTable paramEditorsById ;
// event table for ParamEditor and subclasses
BEGIN_EVENT_TABLE ( ParamEditor , wxPanel )
//EVT_CHECKBOX (-1, ParamEditor::OnEvent)
//EVT_CHOICE (-1, ParamEditor::OnEvent)
//EVT_TEXT(-1, ParamEditor::OnEvent)
//EVT_TEXT_ENTER(-1, ParamEditor::OnEvent)
END_EVENT_TABLE ( )
// event table for wxFrame
BEGIN_EVENT_TABLE ( MyFrame , wxFrame )
EVT_MENU ( ID_Quit , MyFrame : : OnQuit )
EVT_MENU ( ID_StartBochs , MyFrame : : HandleEvent )
EVT_MENU ( ID_ApplyAction , MyFrame : : HandleEvent )
EVT_MENU ( ID_RevertAction , MyFrame : : HandleEvent )
EVT_MENU ( ID_ReadConfig , MyFrame : : HandleEvent )
EVT_MENU ( ID_WriteConfig , MyFrame : : HandleEvent )
EVT_MENU ( ID_WriteConfigAs , MyFrame : : HandleEvent )
END_EVENT_TABLE ( )
// event table for MyPanel
BEGIN_EVENT_TABLE ( MyPanel , wxScrolledWindow )
EVT_BUTTON ( ID_StartBochs , MyPanel : : HandleEvent )
EVT_BUTTON ( ID_ApplyAction , MyPanel : : HandleEvent )
EVT_BUTTON ( ID_RevertAction , MyPanel : : HandleEvent )
// do not call event handlers for the ParamEditors
//EVT_CHECKBOX (ID_Check1, MyPanel::HandleEvent)
//EVT_CHOICE (ID_Choice1, MyPanel::HandleEvent)
//EVT_COMBOBOX (ID_Combo1, MyPanel::HandleEvent)
//EVT_TEXT (ID_Combo1, MyPanel::HandleEvent)
END_EVENT_TABLE ( )
// event table for BochsEventHandler and subclasses
BEGIN_EVENT_TABLE ( BochsEventHandler , wxEvtHandler )
EVT_MENU ( - 1 , BochsEventHandler : : OnEvent )
END_EVENT_TABLE ( )
MyFrame : : MyFrame ( const wxString & title , const wxPoint & pos , const wxSize & size )
: wxFrame ( ( wxFrame * ) NULL , - 1 , title , pos , size )
{
bochsThread = NULL ;
wxMenu * menuFile = new wxMenu ;
menuFile - > Append ( ID_StartBochs , " &Start Bochs... " ) ;
menuFile - > AppendSeparator ( ) ;
menuFile - > Append ( ID_ReadConfig , " Read Configuration File " ) ;
menuFile - > Append ( ID_WriteConfig , " Write Configuration " ) ;
menuFile - > Append ( ID_WriteConfigAs , " Write Configuration As... " ) ;
menuFile - > AppendSeparator ( ) ;
menuFile - > Append ( ID_Quit , " E&xit " ) ;
wxMenuBar * menuBar = new wxMenuBar ;
menuBar - > Append ( menuFile , " &File " ) ;
SetMenuBar ( menuBar ) ;
CreateStatusBar ( ) ;
SetStatusText ( " Bochs Controls " ) ;
int width = 500 , height = 3000 ;
panel = new MyPanel ( this , this , - 1 , wxPoint ( 0 , 0 ) , wxSize ( width , height ) ) ;
panel - > SetScrollbars ( 10 , 10 , width / 10 , height / 10 ) ;
}
void
MyFrame : : HandleEvent ( wxCommandEvent & event )
{
panel - > HandleEvent ( event ) ;
}
void
MyFrame : : StartBochsThread ( )
{
if ( bochsThread = = NULL )
{
printf ( " Starting bochs thread \n " ) ;
bochsThread = new BochsThread ( ) ;
bochsThread - > Create ( ) ;
bochsThread - > Run ( ) ;
} else {
wxMessageBox (
" Can't start Bochs simulator, because it is already running " ,
" Already Running " , wxOK | wxICON_ERROR ) ;
}
}
int
MyFrame : : ReadConfiguration ( int ask_name )
{
char oldrc_cstr [ CPANEL_PATH_LEN ] ;
int found_default = 1 ;
if ( SIM - > get_default_rc ( oldrc_cstr , CPANEL_PATH_LEN ) < 0 ) {
found_default = 0 ;
oldrc_cstr [ 0 ] = 0 ;
}
wxString oldrc ( oldrc_cstr ) , newrc = oldrc ;
if ( ! found_default ) {
if ( ! ask_name ) return - 1 ;
newrc = : : wxFileSelector ( " Load which configuration file? " ,
" " , oldrc , " " , " " , wxOPEN ) ;
}
if ( newrc . IsEmpty ( ) | | ( newrc = = " none " ) ) return 0 ;
if ( SIM - > read_rc ( ( char * ) newrc . c_str ( ) ) < 0 ) {
wxMessageBox ( " Error loading configuration file " ) ;
return - 1 ;
}
panel - > forAllEditors ( ID_RevertAction , paramEditorsById ) ;
return 0 ;
}
int
MyFrame : : WriteConfiguration ( int ask_name )
{
char oldrc_cstr [ CPANEL_PATH_LEN ] ;
int found_default = 1 ;
if ( SIM - > get_default_rc ( oldrc_cstr , CPANEL_PATH_LEN ) < 0 ) {
found_default = 0 ;
oldrc_cstr [ 0 ] = 0 ;
}
wxString oldrc ( oldrc_cstr ) , newrc = oldrc ;
if ( ask_name | | ! found_default ) {
newrc = : : wxFileSelector ( " Save Configuration As " ,
" " , oldrc , " " , " " , wxSAVE | wxOVERWRITE_PROMPT ) ;
}
if ( newrc . IsEmpty ( ) | | ( newrc = = " none " ) ) return 0 ;
if ( SIM - > write_rc ( ( char * ) newrc . c_str ( ) , 1 ) < 0 ) {
wxMessageBox ( " Error while saving configuration file " ) ;
return - 1 ;
}
return 0 ;
}
// static function version that can be referred to by function pointer
int
MyFrame : : ProcessBochsEvent ( void * class_ptr , int id )
{
printf ( " MyFrame::ProcessBochsEvent \n " ) ;
MyFrame * f = ( MyFrame * ) class_ptr ;
f - > ProcessBochsEvent2 ( id ) ;
return 0 ;
}
int
MyFrame : : ProcessBochsEvent2 ( int code )
{
printf ( " MyFrame::ProcessBochsEvent2 \n " ) ;
switch ( code )
{
case NOTIFY_CODE_LOGMSG :
if ( 0 ) {
// dumb static choices for now, I'll fix it once I get it to work
//
// this code works if the gui thread calls it, but it's doing bad
// things when it gets called from the bochs thread.
// I know it's legal for a non-GUI thread to enter a mutex, update
// an object like "m_frame->WriteText(msg)" and then leave the mutex.
// But this code puts up a modal dialog and waits for user input.
// If you comment out the mutex code, you get:
// GLib-WARNING **: g_main_run(): called recursively from within a source's check() or prepare() member or from a second thread, iteration not possible
// And if you uncomment the mutex, it displays the dialog correctly
// but then clicking on it does nothing...deadlock.
// Maybe this must be resolved by posting a message between threads
// instead.
wxMutexGuiEnter ( ) ;
static wxString choices [ ] = { " Die " , " Continue " , " Continue and Disable " } ;
char prefix [ 512 ] , msg [ 512 ] ;
int level ;
assert ( SIM - > log_msg_2 ( prefix , & level , msg , sizeof ( msg ) ) > = 0 ) ;
wxString string ;
string . Printf ( " %s " , msg ) ;
int choice = : : wxGetSingleChoiceIndex (
string ,
wxString ( SIM - > get_log_level_name ( level ) ) , 3 , choices ) ;
wxMutexGuiLeave ( ) ;
printf ( " you chose %d \n " , choice ) ;
} else {
//////////// temporary! still implement this with stdin/stdout ///////////
int level ;
char prefix [ 512 ] , msg [ 512 ] ;
assert ( SIM - > log_msg_2 ( prefix , & level , msg , sizeof ( msg ) ) > = 0 ) ;
fprintf ( stderr , " ========================================================================\n " ) ;
fprintf ( stderr , " Event type: %s \n " , SIM - > get_log_level_name ( level ) ) ;
fprintf ( stderr , " Device: %s \n " , prefix ) ;
fprintf ( stderr , " Message: %s \n \n " , msg ) ;
fprintf ( stderr , " A %s has occurred. Do you want to: \n " , SIM - > get_log_level_name ( level ) ) ;
fprintf ( stderr , " cont - continue execution \n " ) ;
fprintf ( stderr , " alwayscont - continue execution, and don't ask again. \n " ) ;
fprintf ( stderr , " This affects only %s events from device %s \n " , SIM - > get_log_level_name ( level ) , prefix ) ;
fprintf ( stderr , " die - stop execution now \n " ) ;
int choice ;
extern int ask_menu ( char * prompt , int n_choices , char * choice [ ] , int the_default , int * out ) ;
char * log_action_ask_choices [ ] = { " cont " , " alwayscont " , " die " } ;
int log_action_n_choices = 3 ;
if ( ask_menu ( " Choose cont, alwayscont, or die. [%s] " , 3 ,
log_action_ask_choices , 2 , & choice ) < 0 )
return SIM - > notify_return ( - 1 ) ;
// return 0 for continue, 1 for alwayscontinue, 2 for die.
SIM - > notify_return ( choice ) ;
}
break ;
default :
fprintf ( stderr , " Control panel: notify callback called with unknown code %04x \n " , code ) ;
}
}
void MyFrame : : OnQuit ( wxCommandEvent & WXUNUSED ( event ) )
{
Close ( TRUE ) ;
if ( bochsThread ! = NULL )
bochsThread - > Delete ( ) ;
}
BochsEventHandler * bochsEventHandler ;
BochsEventHandler : : BochsEventHandler ( )
{
printf ( " BochsEventHandler::BochsEventHandler \n " ) ;
}
void
BochsEventHandler : : OnEvent ( wxCommandEvent & evt )
{
printf ( " BochsEventHandler::OnEvent called with event id=%d \n " , evt . GetId ( ) ) ;
}
int wxid_count = ID_LAST_STATIC_ASSIGNED_ID ;
IMPLEMENT_APP ( BochsApp )
bool BochsApp : : OnInit ( )
{
// do bochs initialization first
siminterface_init ( ) ;
MyFrame * frame = new MyFrame ( " Bochs Control Panel " , wxPoint ( 50 , 50 ) , wxSize ( 450 , 340 ) ) ;
SIM - > set_notify_callback ( frame - > ProcessBochsEvent , frame ) ;
bochsEventHandler = new BochsEventHandler ( ) ;
frame - > Show ( TRUE ) ;
SetTopWindow ( frame ) ;
return TRUE ;
}
void MyPanel : : HandleEvent ( wxCommandEvent & evt )
{
int id = evt . GetId ( ) ;
printf ( " Handle event with event id %d \n " , id ) ;
switch ( id )
{
case ID_StartBochs :
frame - > StartBochsThread ( ) ;
break ;
case ID_ApplyAction :
case ID_RevertAction :
forAllEditors ( id , paramEditorsById ) ;
break ;
case ID_ReadConfig :
frame - > ReadConfiguration ( 1 ) ;
break ;
case ID_WriteConfig :
frame - > WriteConfiguration ( 0 ) ;
break ;
case ID_WriteConfigAs :
frame - > WriteConfiguration ( 1 ) ;
break ;
default :
printf ( " HandleEvent called with id=%d \n " , id ) ;
}
}
void
MyPanel : : forAllEditors ( int evt_id , wxHashTable & hash )
{
printf ( " MyPanel::forAllEditors " ) ;
// iterate over editors in the editors hashtable
hash . BeginFind ( ) ;
wxNode * node ;
while ( node = hash . Next ( ) )
{
ParamEditor * editor = ( ParamEditor * ) node - > Data ( ) ;
editor - > Action ( evt_id ) ;
}
}
void *
BochsThread : : Entry ( void )
{
int argc = 1 ;
char * argv [ ] = { " bochs " } ;
bx_continue_after_control_panel ( argc , argv ) ;
return NULL ;
}
MyPanel : : MyPanel ( MyFrame * frame , wxWindow * parent , wxWindowID id , const wxPoint & pos , const wxSize & size )
: wxScrolledWindow ( parent , id , pos , size , wxSUNKEN_BORDER | wxTAB_TRAVERSAL , " Bochs Controls " )
{
this - > frame = frame ;
// the parent constructor makes this panel a child of frame, with
// proper size.
( void ) new wxButton ( this , ID_StartBochs , " Start Bochs " , wxPoint ( 10 , 10 ) ) ;
( void ) new wxButton ( this , ID_ApplyAction , " Apply " , wxPoint ( 110 , 10 ) ) ;
( void ) new wxButton ( this , ID_RevertAction , " Revert " , wxPoint ( 210 , 10 ) ) ;
//wxCheckBox *check1 = new wxCheckBox (this, ID_Check1, "Checkbox", wxPoint (10, 50));
//wxString choices[] = { "apple", "orange", "banana" };
//wxChoice *choice1 = new wxChoice (this, ID_Choice1, wxPoint (10, 80), wxSize (80, 30), 3, choices);
//wxComboBox *combo1 = new wxComboBox (this, ID_Combo1, "Default Combo String", wxPoint (10, 130), wxSize (180, 80), 3, choices);
//text1 = new wxStaticText (this, ID_Text1, "no text yet", wxPoint (0, 160));
frame - > ReadConfiguration ( 0 ) ;
buildParamList ( 10 , 40 ) ;
// grab all the settings from siminterface into the GUI
forAllEditors ( ID_RevertAction , paramEditorsById ) ;
}
MyPanel : : ~ MyPanel ( )
{
}
void MyPanel : : buildParamList ( int x , int y )
{
// get a list of parameters
int min , max ;
SIM - > get_param_id_range ( & min , & max ) ;
for ( int i = min ; i < = max ; i + + ) {
bx_param_c * param = SIM - > get_param ( ( bx_id ) i ) ;
if ( param ! = NULL ) {
printf ( " param %d is called %s \n " , i , param - > get_name ( ) ) ;
new wxStaticText ( this , i , param - > get_name ( ) , wxPoint ( x , y ) ) ;
int wxid = wxid_count + + ;
ParamEditor * editor = ParamEditor : : createEditor ( param , this , wxid , x + 120 , y ) ;
y + = 30 ;
}
}
}
/////////////////////////////////////////////////////////////////////////
// Parameter editor classes
/////////////////////////////////////////////////////////////////////////
ParamEditor : : ParamEditor ( bx_param_c * param , wxWindow * parent , wxWindowID id , int x , int y )
: wxPanel ( parent , id , wxPoint ( x , y ) , wxSize ( 300 , 30 ) )
{
printf ( " ParamEditor::ParamEditor \n " ) ;
this - > param = param ;
//wxString text = wxString (param->get_name ());
//new wxStaticText (parent, id, text, wxPoint (x, y));
}
ParamEditor *
ParamEditor : : createEditor ( bx_param_c * param , wxWindow * parent , wxWindowID id , int x , int y )
{
printf ( " ParamEditor::createEditor \n " ) ;
Bit8u type = param - > get_type ( ) ;
ParamEditor * it = NULL ;
switch ( type ) {
case BXT_PARAM_BOOL :
it = new ParamEditorBool ( param , parent , id , x , y ) ;
break ;
case BXT_PARAM_NUM :
it = new ParamEditorNum ( param , parent , id , x , y ) ;
break ;
case BXT_PARAM_STRING :
it = new ParamEditorString ( param , parent , id , x , y ) ;
break ;
case BXT_PARAM_ENUM :
it = new ParamEditorEnum ( param , parent , id , x , y ) ;
break ;
case BXT_LIST :
it = new ParamEditorList ( param , parent , id , x , y ) ;
break ;
default :
printf ( " ParamEditor::createEditor with unknown type %d \n " , type ) ;
it = NULL ;
}
paramEditorsById . Put ( id , it ) ;
return it ;
}
ParamEditorBool : : ParamEditorBool ( bx_param_c * param , wxWindow * parent , wxWindowID id , int x , int y )
: ParamEditor ( param , parent , id , x , y )
{
component = new wxCheckBox ( this , id , " " , wxPoint ( 0 , 0 ) ) ;
}
void
ParamEditorBool : : Action ( int evt_id )
{
printf ( " ParamEditorBool::Action \n " ) ;
bx_param_bool_c * param = ( bx_param_bool_c * ) get_param ( ) ;
switch ( evt_id ) {
case ID_ApplyAction :
param - > set ( component - > GetValue ( ) ) ;
break ;
case ID_RevertAction :
component - > SetValue ( param - > get ( ) ) ;
break ;
default :
wxASSERT ( 0 ) ;
}
}
ParamEditorNum : : ParamEditorNum ( bx_param_c * param , wxWindow * parent , wxWindowID id , int x , int y )
: ParamEditor ( param , parent , id , x , y )
{
// background color helps to visualize the borders of the panel
//SetBackgroundColour (wxColour ("red"));
bx_param_num_c * num = ( bx_param_num_c * ) param ;
wxString text ;
text . Printf ( " %d " , num - > get ( ) ) ;
component = new wxTextCtrl ( this , id , text , wxPoint ( - 1 , - 1 ) , wxSize ( - 1 , - 1 ) , wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB ) ;
}
void
ParamEditorNum : : Action ( int evt_id )
{
printf ( " ParamEditorNum::Action \n " ) ;
bx_param_num_c * param = ( bx_param_num_c * ) get_param ( ) ;
int base = param - > get_base ( ) ;
wxASSERT ( base = = 10 | | base = = 16 ) ;
switch ( evt_id ) {
case ID_ApplyAction :
{
const char * string = component - > GetValue ( ) . c_str ( ) ;
int n , status ;
if ( base = = 10 ) status = wxSscanf ( string , " %d " , & n ) ;
else status = wxSscanf ( string , " %x " , & n ) ;
if ( status ! = 1 ) {
printf ( " Invalid number in %s, value = '%s' \n " , param - > get_name ( ) , string ) ;
return ;
}
param - > set ( n ) ;
}
break ;
case ID_RevertAction :
{
int n = param - > get ( ) ;
wxString string ;
if ( base = = 10 ) string . Printf ( " %d " , n ) ;
else string . Printf ( " %x " , n ) ;
component - > SetValue ( string ) ;
}
break ;
default :
wxASSERT ( 0 ) ;
}
}
ParamEditorString : : ParamEditorString ( bx_param_c * param , wxWindow * parent , wxWindowID id , int x , int y )
: ParamEditor ( param , parent , id , x , y )
{
//SetBackgroundColour (wxColour ("red"));
bx_param_string_c * string = ( bx_param_string_c * ) param ;
wxString text = wxString ( string - > getptr ( ) ) ;
component = new wxTextCtrl ( this , id , text , wxPoint ( - 1 , - 1 ) , wxSize ( - 1 , - 1 ) , wxTE_PROCESS_ENTER ) ;
}
void
ParamEditorString : : Action ( int evt_id )
{
bx_param_string_c * param = ( bx_param_string_c * ) get_param ( ) ;
const char * string ;
switch ( evt_id ) {
case ID_ApplyAction :
string = component - > GetValue ( ) . c_str ( ) ;
param - > set ( ( char * ) string ) ;
break ;
case ID_RevertAction :
component - > SetValue ( wxString ( param - > getptr ( ) ) ) ;
break ;
default :
wxASSERT ( 0 ) ;
}
}
ParamEditorEnum : : ParamEditorEnum ( bx_param_c * genericparam , wxWindow * parent , wxWindowID id , int x , int y )
: ParamEditor ( genericparam , parent , id , x , y )
{
//SetBackgroundColour (wxColour ("red"));
// build the array of choices
bx_param_enum_c * param = ( bx_param_enum_c * ) genericparam ;
n_choices = param - > get_max ( ) - param - > get_min ( ) + 1 ;
choices = new wxString [ n_choices ] ;
for ( int i = 0 ; i < n_choices ; i + + )
choices [ i ] = param - > get_choice ( i ) ;
component = new wxChoice ( this , id , wxPoint ( - 1 , - 1 ) , wxSize ( - 1 , - 1 ) , n_choices , choices ) ;
}
void
ParamEditorEnum : : Action ( int evt_id )
{
printf ( " ParamEditorEnum::Action \n " ) ;
bx_param_enum_c * param = ( bx_param_enum_c * ) get_param ( ) ;
int min = param - > get_min ( ) ;
switch ( evt_id ) {
case ID_ApplyAction :
param - > set ( min + component - > GetSelection ( ) ) ;
break ;
case ID_RevertAction :
component - > SetSelection ( param - > get ( ) - min ) ;
break ;
default :
wxASSERT ( 0 ) ;
}
}
ParamEditorList : : ParamEditorList ( bx_param_c * genericparam , wxWindow * parent , wxWindowID id , int x , int y )
: ParamEditor ( genericparam , parent , id , x , y )
{
//SetBackgroundColour (wxColour ("red"));
bx_list_c * param = ( bx_list_c * ) genericparam ;
component = new wxStaticText ( this , id , " list param not implemented " , wxPoint ( - 1 , - 1 ) ) ;
}
void
ParamEditorList : : Action ( int evt_id )
{
printf ( " ParamEditorList::Action \n " ) ;
}
bx_param_c *
ParamEditor : : get_param ( )
{
printf ( " You called get_param on ParamEditor %p \n " , this ) ;
printf ( " My param value is %p \n " , this - > param ) ;
return this - > param ;
}
void
ParamEditor : : OnEvent ( wxCommandEvent & evt )
{
// if you want to run some action on the object that sent this event,
// see the code below.
#if 0
int id = evt . GetId ( ) ;
wxObject * object = evt . GetEventObject ( ) ;
printf ( " ParamEditor::OnEvent, id=%d, object=%p \n " , id , object ) ;
ParamEditor * genericeditor = ( ParamEditor * ) paramEditorsById . Get ( id ) ;
if ( genericeditor = = NULL ) {
printf ( " I couldn't find the parameter editor for id=%d \n " , id ) ;
return ;
}
bx_param_c * genericparam = genericeditor - > get_param ( ) ;
wxASSERT ( genericparam ! = NULL ) ;
printf ( " This event will be sent to %s \n " , genericparam - > get_name ( ) ) ;
genericeditor - > Action ( evt ) ;
# endif
}
# endif