X-Git-Url: http://gitweb.hugovil.com/?a=blobdiff_plain;f=src%2Femugtk.c;h=774278880a5f4d37eea5033231a5af9375b01545;hb=ba7ff1a7a78b3aa7c2cad9bfce117256638938b1;hp=2224ee2fbddd389d94c6ded6d41ca1665d7fe8b0;hpb=6a65dca9d597772744524b909f2d89b479b8bf77;p=emu8051.git diff --git a/src/emugtk.c b/src/emugtk.c index 2224ee2..7742788 100644 --- a/src/emugtk.c +++ b/src/emugtk.c @@ -16,425 +16,460 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "config.h" +#include +#include + #include -#include "emugtk.h" -#include "reset.xpm" -#include "run.xpm" -#include "stop.xpm" -#include "step.xpm" #include "common.h" #include "cpu8051.h" #include "options.h" #include "hexfile.h" + +#include "emugtk.h" +#include "reset.xpm" +#include "run.xpm" +#include "stop.xpm" +#include "step.xpm" #include "filemenu.h" #include "viewmenu.h" #include "helpmenu.h" #include "regwin.h" #include "pgmwin.h" #include "memwin.h" +#include "app-config.h" +#define BUTTONS_BORDER 2 -static int RunningState; -static int RunFuncTag; - - +static int running; +static int running_function_tag; static GtkWidget *mainwin; - -/* In options.c */ -extern char *hex_file; - +extern struct app_config_t *cfg; /* Signal DestroyEvent */ static void -WindowDestroyEvent( GtkWidget *widget, gpointer data ) +WindowDestroyEvent(GtkWidget *widget, gpointer data) { #ifdef EMU8051_DEBUG - g_print( "emugtk_DestroyEvent(...)\n" ); + g_print("emugtk_DestroyEvent(...)\n"); #endif - gtk_main_quit(); + gtk_main_quit(); } - -/* Taken from the Gxine source code. */ -static GtkWidget * -AddPixButton( GtkWidget *box, gchar **pixmap_array ) +/* Step out of running state */ +static void +emugtk_stop_running() { - GtkWidget *button, *icon; - GdkPixmap *image; - GdkBitmap *transparent; - - button = gtk_button_new(); - gtk_button_set_relief (GTK_BUTTON(button), GTK_RELIEF_NORMAL ); - image = gdk_pixmap_colormap_create_from_xpm_d(NULL, gdk_colormap_get_system(), - &transparent, NULL, pixmap_array); - icon = gtk_pixmap_new( image, transparent ); - gtk_container_add( GTK_CONTAINER(button), icon ); + if (running) { +#ifdef EMU8051_DEBUG + printf("emugtk_StopRunning()\n"); +#endif + g_source_remove(running_function_tag); + running = 0; + regwin_Show(); + pgmwin_Disasm(); + memwin_DumpD("00"); + } +} - gtk_box_pack_start( GTK_BOX(box), button, FALSE, FALSE, 0 ); +/* Running function called when idle from gtk_main */ +static gboolean +emugtk_running(gpointer data) +{ + cpu8051_Exec(); + if (IsBreakpoint(cpu8051.pc)) { +#ifdef EMU8051_DEBUG + g_print("Breakpoint Hit, stopping!\n"); +#endif + emugtk_stop_running(); + } - return button; + return TRUE; } - -/* Creates the Reset, Run, Stop and Step buttons. */ -static GtkWidget * -AddButtons( void ) +/* Get in the running state */ +static void +emugtk_start_running(void) { - GtkWidget *button_hbox; - GtkWidget *button; - - /* The buttons of the hbox are NOT given equal space in the box. */ - button_hbox = gtk_hbox_new( FALSE, 0 ); - - /* Creating the RESET button. */ - button = AddPixButton( button_hbox, reset_xpm ); - gtk_signal_connect( GTK_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC(emugtk_ResetEvent), - NULL ); - - /* Creating the RUN button. */ - button = AddPixButton( button_hbox, run_xpm ); - gtk_signal_connect( GTK_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC(emugtk_RunEvent), - NULL ); - - /* Creating STOP button. */ - button = AddPixButton( button_hbox, stop_xpm ); - gtk_signal_connect( GTK_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC(emugtk_StopEvent), - NULL ); - - /* Creating STEP button. */ - button = AddPixButton( button_hbox, step_xpm ); - gtk_signal_connect( GTK_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC(emugtk_StepEvent), - NULL ); - - return button_hbox; + if (!running) { +#ifdef EMU8051_DEBUG + printf("emugtk_StartRunning()\n"); +#endif + running_function_tag = g_idle_add(emugtk_running, 0); + running = 1; + } } - -GtkWidget * -AddMenu( void ) +/* Taken from the Gxine source code. */ +static GtkWidget * +button_add_pix(GtkWidget *box, char **xpm) { - GtkWidget *menu_bar; + GtkWidget *button, *icon; - /* Creating menu item. */ - menu_bar = gtk_menu_bar_new(); + button = gtk_button_new(); + gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NORMAL); - /* Adding the 'File' submenu */ - FileAddMenu( menu_bar ); + icon = gtk_image_new_from_pixbuf( + gdk_pixbuf_new_from_xpm_data((const char **) xpm)); + gtk_container_add(GTK_CONTAINER(button), icon); - /* Adding the 'View' submenu */ - ViewAddMenu( menu_bar ); - - /* Adding the 'Help' submenu */ - HelpAddMenu( menu_bar ); + gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, BUTTONS_BORDER); - gtk_widget_show_all( GTK_WIDGET( menu_bar ) ); - - return menu_bar; + return button; } - +/* CPU reset and Gtk UI update */ static void -emugtk_window_init( void ) +emugtk_Reset(void) { - GtkWidget *main_vbox; - GtkWidget *menu_bar; - GtkWidget *buttons_bar; - GtkWidget *emufixed; - GtkWidget *fixed_frame; - - mainwin = gtk_window_new( GTK_WINDOW_TOPLEVEL ); - gtk_window_set_title( GTK_WINDOW(mainwin), PACKAGE ); - gtk_widget_set_usize( GTK_WIDGET(mainwin), MAIN_WIN_WIDTH, MAIN_WIN_HEIGHT ); - gtk_container_set_border_width( GTK_CONTAINER(mainwin), 0 ); - - /* Window DESTROY event. */ - gtk_signal_connect( GTK_OBJECT(mainwin), "destroy", GTK_SIGNAL_FUNC(WindowDestroyEvent), - NULL ); - - /* Setting main window geometry based on command line options (if specified). */ - /*MainWindowSetGeometry();*/ - - /* main_vbox contains the menu bar and body_vbox (for all remaining items). */ - main_vbox = gtk_vbox_new( FALSE, 1 ); - - /* Creating the menu bar. */ - menu_bar = AddMenu(); - /* Adding menu bar to main_vbox */ - gtk_box_pack_start( GTK_BOX(main_vbox), menu_bar, FALSE, FALSE, 1 ); - - /* Creating the buttons bar. */ - buttons_bar = AddButtons(); - /* Adding buttons bar to main_vbox */ - gtk_box_pack_start( GTK_BOX(main_vbox), buttons_bar, FALSE, FALSE, 1 ); - - /* Emulator fixed window. */ - emufixed = gtk_fixed_new(); - gtk_widget_set_usize( GTK_WIDGET( emufixed ), MAIN_WIN_WIDTH, - REG_WIN_HEIGHT + MEM_WIN_HEIGHT + 10 ); - - /* 8051 registers frame. */ - fixed_frame = regwin_init( REG_WIN_WIDTH, REG_WIN_HEIGHT ); - gtk_fixed_put( GTK_FIXED( emufixed ), fixed_frame, 0, 0 ); - - /* Program disassembly frame. */ - fixed_frame = pgmwin_init( PGM_WIN_WIDTH, PGM_WIN_HEIGHT ); - gtk_fixed_put( GTK_FIXED( emufixed ), fixed_frame, REG_WIN_WIDTH + 10, 0 ); - - /* Memory dump frame. */ - fixed_frame = memwin_init( MEM_WIN_WIDTH, MEM_WIN_HEIGHT ); - gtk_fixed_put( GTK_FIXED( emufixed ), fixed_frame, 0, REG_WIN_HEIGHT ); - - /* Adding fixed window to main_vbox */ - gtk_box_pack_start( GTK_BOX(main_vbox), emufixed, FALSE, FALSE, 1 ); - - /* Adding the main_vbox to the main window. */ - gtk_container_add( GTK_CONTAINER(mainwin), main_vbox ); - - gtk_widget_show_all( mainwin ); + cpu8051_Reset(); + regwin_Show(); + pgmwin_Disasm(); + memwin_DumpD("00"); } - -int -main( int argc, char **argv ) +/* Signal ResetEvent (ResetButton) */ +static void +emugtk_ResetEvent(GtkWidget *widget, GdkEvent *event, gpointer data) { - ParseCommandLineOptions( argc, argv ); - - cpu8051_init(); - - RunningState = 0; - - gtk_init( &argc, &argv ); - - emugtk_window_init(); - - if( hex_file != NULL ) { - emugtk_new_file( hex_file ); - } - - /*emugtk_Reset();*/ - - gtk_main(); - - printf( "End of program.\n" ); - - return EXIT_SUCCESS; +#ifdef EMU8051_DEBUG + g_print("emugtk_ResetEvent(...)\n"); +#endif + emugtk_stop_running(); + emugtk_Reset(); } - -void -emugtk_new_file( char *file ) +/* CPU Step and Gtk UI update */ +static void +emugtk_Step(void) { - emugtk_StopRunning(); - - LoadHexFile( file ); - - emugtk_Reset(); - emugtk_UpdateDisplay(); + cpu8051_Exec(); + regwin_Show(); + pgmwin_Disasm(); + memwin_DumpD("00"); } - - - -void -AddMenuSeparator( GtkWidget *menu ) +/* Signal RunEvent (RunButton) */ +static void +emugtk_RunEvent(GtkWidget *widget, GdkEvent *event, gpointer data) { - GtkWidget *item; - - item = gtk_menu_item_new(); - gtk_menu_append( GTK_MENU(menu), item ); +#ifdef EMU8051_DEBUG + g_print("emugtk_RunEvent(...)\n"); +#endif + if (running) + emugtk_stop_running(); + else + emugtk_start_running(); } - -void -emugtk_UpdateDisplay( void ) +/* Signal StopEvent (StopButton) */ +static void +emugtk_StopEvent(GtkWidget *widget, GdkEvent *event, gpointer data) { #ifdef EMU8051_DEBUG - g_print( "emugtk_UpdateDisplay()\n" ); + g_print("emugtk_StopEvent(...)\n"); #endif - - regwin_Show(); - pgmwin_Disasm(); - memwin_DumpD( 0 ); + emugtk_stop_running(); } +/* Signal StepEvent (StepButton) */ +static void +emugtk_StepEvent(GtkWidget *widget, GdkEvent *event, gpointer data) +{ +#ifdef EMU8051_DEBUG + g_print("emugtk_StepEvent(...)\n"); +#endif + emugtk_stop_running(); + emugtk_Step(); +} +/* Creates the Reset, Run, Stop and Step buttons. */ +static GtkWidget * +AddButtons(void) +{ + GtkWidget *button_hbox; + GtkWidget *button; + + /* The buttons of the hbox are NOT given equal space in the box. */ + button_hbox = gtk_hbox_new(FALSE, 0); + + /* Creating the RESET button. */ + button = button_add_pix(button_hbox, reset_xpm); + g_signal_connect(button, "clicked", + G_CALLBACK(emugtk_ResetEvent), + NULL); + + /* Creating the RUN button. */ + button = button_add_pix(button_hbox, run_xpm); + g_signal_connect(button, "clicked", + G_CALLBACK(emugtk_RunEvent), + NULL); + + /* Creating STOP button. */ + button = button_add_pix(button_hbox, stop_xpm); + g_signal_connect(GTK_OBJECT(button), "clicked", + G_CALLBACK(emugtk_StopEvent), + NULL); + + /* Creating STEP button. */ + button = button_add_pix(button_hbox, step_xpm); + g_signal_connect(GTK_OBJECT(button), "clicked", + G_CALLBACK(emugtk_StepEvent), + NULL); + + return button_hbox; +} +static GtkWidget * +AddMenu(void) +{ + GtkWidget *menu_bar; + /* Creating menu item. */ + menu_bar = gtk_menu_bar_new(); + /* Adding the 'File' submenu */ + FileAddMenu(menu_bar); + /* Adding the 'View' submenu */ + ViewAddMenu(menu_bar); + /* Adding the 'Help' submenu */ + HelpAddMenu(menu_bar); + gtk_widget_show_all(GTK_WIDGET(menu_bar)); + return menu_bar; +} +static int +mainwin_configure_event(GtkWindow *window, GdkEvent *event, gpointer data) +{ + //event->configure.x; + //event->configure.y; + cfg->win_width = event->configure.width; + cfg->win_height = event->configure.height; + + /* + * Important: + * Returning false allows event to propagate to children. If not, they + * will not be resized when we resize the main window. + */ + return FALSE; +} +static void +hpaned_notify_event(GtkWindow *window, GdkEvent *event, gpointer data) +{ + GtkWidget *hpaned = data; + cfg->hpane_pos = gtk_paned_get_position(GTK_PANED(hpaned)); +} -////////////////////////////////////////////////////////////////////////////// -// CPU reset and Gtk UI update -////////////////////////////////////////////////////////////////////////////// -void -emugtk_Reset( void ) +static void +vpaned_notify_event(GtkWindow *window, GdkEvent *event, gpointer data) { - cpu8051_Reset( ); - regwin_Show(); - pgmwin_Disasm(); - memwin_DumpD( 0 ); -} + GtkWidget *vpaned = data; + cfg->vpane_pos = gtk_paned_get_position(GTK_PANED(vpaned)); +} -////////////////////////////////////////////////////////////////////////////// -// CPU Step and Gtk UI update -////////////////////////////////////////////////////////////////////////////// -void -emugtk_Step( void ) +/* + * mainwin + * +---------------------------------------------------------------------+ + * | | + * | vbox | + * | +---------------------------------------------------------------+ | + * | | | | + * | | menu_bar | | + * | | +----------------------+ | | + * | | | File View Help | | | + * | | +----------------------+ | | + * | | | | + * | |---------------------------------------------------------------| | + * | | | | + * | | buttons_bar | | + * | | +-----------------------+ | | + * | | | RST RUN STOP STEP | | | + * | | +-----------------------+ | | + * | | | | + * | |---------------------------------------------------------------| | + * | | | | + * | | vpaned | | + * | | +---------------------------------------------------------+ | | + * | | | | | | + * | | | hpaned | | | + * | | | +---------------------------------------------------+ | | | + * | | | | | | | | | + * | | | | scrollwin | scrollwin | | | | + * | | | | +------------------+ * +--------------------+ | | | | + * | | | | | REGISTERS window | * | Disassembly window | | | | | + * | | | | +------------------+ | +--------------------+ | | | | + * | | | | | | | | | + * | | | +---------------------------------------------------+ | | | + * | | | | | | + * | | |--------------------------***----------------------------- | | + * | | | | | | + * | | | scrollwin | | | + * | | | +---------------------------------------------------+ | | | + * | | | | Memory window | | | | + * | | | +---------------------------------------------------+ | | | + * | | | | | | + * | | +---------------------------------------------------------+ | | + * | | | | + * | | | | + * | +---------------------------------------------------------------+ | + * | | + * | | + * +---------------------------------------------------------------------+ + */ +static void +emugtk_window_init(void) { - cpu8051_Exec(); - regwin_Show(); - pgmwin_Disasm(); - memwin_DumpD( 0 ); + GtkWidget *vbox; + GtkWidget *menu_bar; + GtkWidget *buttons_bar; + GtkWidget *scrollwin; + GtkWidget *hpaned; + GtkWidget *vpaned; + + mainwin = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(mainwin), PACKAGE); + gtk_window_set_default_size(GTK_WINDOW(mainwin), + cfg->win_width, cfg->win_height); + gtk_container_set_border_width(GTK_CONTAINER(mainwin), 0); + + /* Window DESTROY event. */ + g_signal_connect(mainwin, "destroy", + G_CALLBACK(WindowDestroyEvent), NULL); + + g_signal_connect(G_OBJECT(mainwin), "configure-event", + G_CALLBACK(mainwin_configure_event), NULL); + + /* + * vbox contains the menu bar and body_vbox (for all remaining + * items). + */ + vbox = gtk_vbox_new(FALSE, 1); + + /* Creating the menu bar. */ + menu_bar = AddMenu(); + /* Adding menu bar to vbox */ + gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 1); + + /* Creating the buttons bar. */ + buttons_bar = AddButtons(); + /* Adding buttons bar to vbox */ + gtk_box_pack_start(GTK_BOX(vbox), buttons_bar, FALSE, FALSE, 1); + + /* + * vpaned will contain: + * Top: registers and disassembly windows. + * Bottom: memory window + */ + vpaned = gtk_vpaned_new(); + gtk_paned_set_position(GTK_PANED(vpaned), cfg->vpane_pos); + g_signal_connect(G_OBJECT(vpaned), "notify::position", + G_CALLBACK(vpaned_notify_event), vpaned); + + /* hpaned will contain registers and disassembly windows. */ + hpaned = gtk_hpaned_new(); + gtk_paned_set_position(GTK_PANED(hpaned), cfg->hpane_pos); + g_signal_connect(G_OBJECT(hpaned), "notify::position", + G_CALLBACK(hpaned_notify_event), hpaned); + + /* 8051 registers frame. */ + scrollwin = regwin_init(); + gtk_paned_pack1(GTK_PANED(hpaned), scrollwin, FALSE, FALSE); + + /* Program disassembly frame. */ + scrollwin = pgmwin_init(); + gtk_paned_pack2(GTK_PANED(hpaned), scrollwin, TRUE, FALSE); + + gtk_paned_pack1(GTK_PANED(vpaned), hpaned, FALSE, FALSE); + + /* Memory dump frame. */ + scrollwin = memwin_init(); + gtk_paned_pack2(GTK_PANED(vpaned), scrollwin, TRUE, FALSE); + + /* Adding vpaned window to vbox */ + gtk_box_pack_start(GTK_BOX(vbox), vpaned, true, true, 1); + + /* Adding the vbox to the main window. */ + gtk_container_add(GTK_CONTAINER(mainwin), vbox); + + gtk_widget_show_all(mainwin); } - -////////////////////////////////////////////////////////////////////////////// -// Signal ResetEvent ( ResetButton ) -////////////////////////////////////////////////////////////////////////////// -void -emugtk_ResetEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) +static void +emugtk_UpdateDisplay(void) { #ifdef EMU8051_DEBUG - g_print( "emugtk_ResetEvent(...)\n" ); + g_print("emugtk_UpdateDisplay()\n"); #endif - emugtk_StopRunning( ); - emugtk_Reset( ); -} + regwin_Show(); + pgmwin_Disasm(); + memwin_DumpD("00"); +} -////////////////////////////////////////////////////////////////////////////// -// Signal RunEvent ( RunButton ) -////////////////////////////////////////////////////////////////////////////// void -emugtk_RunEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) +AddMenuSeparator(GtkWidget *menu) { -#ifdef EMU8051_DEBUG - g_print( "emugtk_RunEvent(...)\n" ); -#endif - if ( RunningState ) { - // g_print( "Getting out of RunningState! \n" ); - emugtk_StopRunning( ); - } - else { - // g_print( "Going In RunningState! \n" ); - emugtk_StartRunning( ); - } -} + GtkWidget *item; + item = gtk_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); +} -////////////////////////////////////////////////////////////////////////////// -// Signal StopEvent ( StopButton ) -////////////////////////////////////////////////////////////////////////////// void -emugtk_StopEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) +emugtk_new_file(char *file) { -#ifdef EMU8051_DEBUG - g_print( "emugtk_StopEvent(...)\n" ); -#endif - emugtk_StopRunning( ); -} + emugtk_stop_running(); + LoadHexFile(file); -////////////////////////////////////////////////////////////////////////////// -// Signal StepEvent ( StepButton ) -////////////////////////////////////////////////////////////////////////////// -void -emugtk_StepEvent( GtkWidget *widget, GdkEvent *event, gpointer data ) -{ -#ifdef EMU8051_DEBUG - g_print( "emugtk_StepEvent(...)\n" ); -#endif - emugtk_StopRunning( ); - emugtk_Step(); + emugtk_Reset(); + emugtk_UpdateDisplay(); } - -////////////////////////////////////////////////////////////////////////////// -// Running called by RunningFunction( ) -////////////////////////////////////////////////////////////////////////////// -void -emugtk_Running( ) +int +main(int argc, char **argv) { - cpu8051_Exec( ); - if( pgmwin_IsBreakpoint( cpu8051.pc ) ) { -#ifdef EMU8051_DEBUG - g_print( "Breakpoint Hit, stopping!\n" ); -#endif - emugtk_StopRunning( ); - } -} + char *hex_file; + ParseCommandLineOptions(argc, argv); -////////////////////////////////////////////////////////////////////////////// -// RunningFunction called when idle from gtk_main -////////////////////////////////////////////////////////////////////////////// -gboolean -RunningFunction( gpointer data ) -{ - emugtk_Running( ); - return TRUE; -} + app_config_load(); + cpu8051_init(); -////////////////////////////////////////////////////////////////////////////// -// Get in the RunningState -////////////////////////////////////////////////////////////////////////////// -void -emugtk_StartRunning( void ) -{ - if ( !RunningState ) { -#ifdef EMU8051_DEBUG - printf( "emugtk_StartRunning( )\n" ); -#endif - /*RunFuncTag = gtk_idle_add( GtkFunction( RunningFunction ), 0 );*/ - RunFuncTag = gtk_idle_add( RunningFunction, 0 ); + running = 0; - RunningState = 1; + gtk_init(&argc, &argv); - // gtk_widget_hide( GTK_WIDGET( ButtonRun ) ); - // gtk_widget_show_now( GTK_WIDGET( ButtonStop ) ); - // gtk_table_attach_defaults( GTK_TABLE( ButtonTable ), ButtonStop, 3, 4, 0, 1); - } -} + emugtk_window_init(); + hex_file = get_hex_filename(); + + if (hex_file != NULL) + emugtk_new_file(hex_file); + + gtk_main(); -////////////////////////////////////////////////////////////////////////////// -// Step out of RunningState -////////////////////////////////////////////////////////////////////////////// -void -emugtk_StopRunning( ) -{ - if (RunningState) { #ifdef EMU8051_DEBUG - printf( "emugtk_StopRunning( )\n" ); + printf("End of program.\n"); #endif - gtk_idle_remove( RunFuncTag ); - RunningState = 0; - //gtk_widget_hide( GTK_WIDGET( ButtonStop ) ); - //gtk_widget_show( GTK_WIDGET( ButtonRun ) ); - // gtk_table_attach_defaults( GTK_TABLE( ButtonTable ), ButtonRun, 3, 4, 0, 1); - regwin_Show(); - pgmwin_Disasm(); - memwin_DumpD( 0 ); - } + + app_config_save(); + + return EXIT_SUCCESS; }