Implemented VGA console support in the common gui code and the X11 specific

code. Now the runtime configuration runs in the Bochs window instead of
console / xterm. The simulation screen is restored when the
simulation continues. This feature can be implemented for all guis
without gui dialog box support (e.g. sdl2/sdl2 on non-win32 platforms, rfb).
This commit is contained in:
Volker Ruppert 2017-01-01 17:45:06 +00:00
parent ab20fa1bc2
commit eff3664fec
8 changed files with 434 additions and 171 deletions

View File

@ -9,6 +9,10 @@ Changes after 2.6.8 release:
- Configure and compile
- Added Android host platform support.
- GUI and display libraries
- X11: Show the runtime configuration in the Bochs VGA window instead of
console / xterm.
- CPU / CPUDB
- Bugfixes for CPU emulation correctness (critical bugfix for x86-64 and AVX opcodes emulation,
fixed assertion failures in proc_ctrl.cc)

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002-2015 The Bochs Project
// Copyright (C) 2002-2017 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -36,6 +36,8 @@
#include "gui/bitmaps/userbutton.h"
#include "gui/bitmaps/saverestore.h"
#include "sdl.h"
#if BX_WITH_MACOS
# include <Disks.h>
#endif
@ -102,6 +104,7 @@ bx_gui_c::bx_gui_c(void): disp_mode(DISP_MODE_SIM)
led_timer_index = BX_NULL_TIMER_HANDLE;
framebuffer = NULL;
guest_textmode = 1;
guest_fsize = (16 << 4) | 8;
guest_xres = 640;
guest_yres = 480;
guest_bpp = 8;
@ -115,6 +118,11 @@ bx_gui_c::~bx_gui_c()
if (framebuffer != NULL) {
delete [] framebuffer;
}
#if BX_USE_TEXTCONFIG
if (console.running) {
console_cleanup();
}
#endif
}
void bx_gui_c::init(int argc, char **argv, unsigned max_xres, unsigned max_yres,
@ -129,7 +137,10 @@ void bx_gui_c::init(int argc, char **argv, unsigned max_xres, unsigned max_yres,
BX_GUI_THIS x_tilesize = tilewidth;
BX_GUI_THIS y_tilesize = tileheight;
BX_GUI_THIS dialog_caps = BX_GUI_DLG_RUNTIME | BX_GUI_DLG_SAVE_RESTORE;
#if BX_USE_TEXTCONFIG
BX_GUI_THIS console.present = 0;
BX_GUI_THIS console.running = 0;
#endif
BX_GUI_THIS toggle_method = SIM->get_param_enum(BXPN_MOUSE_TOGGLE)->get();
BX_GUI_THIS toggle_keystate = 0;
switch (toggle_method) {
@ -1053,3 +1064,147 @@ void bx_gui_c::close_debug_dialog()
CloseDebugDialog();
}
#endif
#if BX_USE_TEXTCONFIG
#define BX_CONSOLE_BUFSIZE 4000
void bx_gui_c::console_init(void)
{
int i;
console.screen = new Bit8u[BX_CONSOLE_BUFSIZE];
console.oldscreen = new Bit8u[BX_CONSOLE_BUFSIZE];
for (i = 0; i < BX_CONSOLE_BUFSIZE; i+=2) {
console.screen[i] = 0x20;
console.screen[i+1] = 0x07;
}
memset(console.oldscreen, 0xff, BX_CONSOLE_BUFSIZE);
console.saved_xres = guest_xres;
console.saved_yres = guest_yres;
console.saved_bpp = guest_bpp;
console.saved_fsize = guest_fsize;
for (i = 0; i < 256; i++) {
memcpy(&BX_GUI_THIS vga_charmap[0]+i*32, &sdl_font8x16[i], 16);
BX_GUI_THIS char_changed[i] = 1;
}
BX_GUI_THIS charmap_updated = 1;
console.cursor_x = 0;
console.cursor_y = 0;
memset(&console.tminfo, 0, sizeof(bx_vga_tminfo_t));
console.tminfo.line_offset = 160;
console.tminfo.line_compare = 1023;
console.tminfo.cs_start = 14;
console.tminfo.cs_end = 15;
console.tminfo.blink_flags = BX_TEXT_BLINK_MODE | BX_TEXT_BLINK_STATE;
console.tminfo.actl_palette[7] = 0x07;
dimension_update(720, 400, 16, 9, 8);
console.n_keys = 0;
console.running = 1;
}
void bx_gui_c::console_cleanup(void)
{
delete [] console.screen;
delete [] console.oldscreen;
unsigned fheight = (console.saved_fsize >> 4);
unsigned fwidth = (console.saved_fsize & 0x0f);
dimension_update(console.saved_xres, console.saved_yres, fheight, fwidth,
console.saved_bpp);
console.running = 0;
}
void bx_gui_c::console_refresh(bx_bool force)
{
if (force) memset(console.oldscreen, 0xff, BX_CONSOLE_BUFSIZE);
text_update(console.oldscreen, console.screen, console.cursor_x,
console.cursor_y, &console.tminfo);
memcpy(console.oldscreen, console.screen, BX_CONSOLE_BUFSIZE);
}
void bx_gui_c::console_key_enq(Bit8u key)
{
if (console.n_keys < 16) {
console.keys[console.n_keys++] = key;
}
}
int bx_gui_c::bx_printf(const char *s)
{
unsigned offset;
if (!console.running) {
console_init();
}
for (unsigned i = 0; i < strlen(s); i++) {
offset = console.cursor_y * 160 + console.cursor_x * 2;
if ((s[i] != 0x08) && (s[i] != 0x0a)) {
console.screen[offset] = s[i];
console.screen[offset+1] = 0x07;
console.cursor_x++;
}
if ((s[i] == 0x0a) || (console.cursor_x == 80)) {
console.cursor_x = 0;
console.cursor_y++;
}
if (s[i] == 0x08) {
if (offset > 0) {
console.screen[offset-2] = 0x20;
console.screen[offset-1] = 0x07;
if (console.cursor_x > 0) {
console.cursor_x--;
} else {
console.cursor_x = 79;
console.cursor_y--;
}
}
}
if (console.cursor_y == 25) {
memcpy(console.screen, console.screen+160, BX_CONSOLE_BUFSIZE-160);
console.cursor_y--;
offset = console.cursor_y * 160 + console.cursor_x * 2;
for (int j = 0; j < 160; j+=2) {
console.screen[offset+j] = 0x20;
console.screen[offset+j+1] = 0x07;
}
}
}
console_refresh(0);
return strlen(s);
}
char* bx_gui_c::bx_gets(char *s, int size)
{
char keystr[2];
int pos = 0, done = 0;
keystr[1] = 0;
do {
handle_events();
while ((console.n_keys > 0) && !done) {
if ((console.keys[0] >= 0x20) && (pos < (size-1))) {
s[pos++] = console.keys[0];
keystr[0] = console.keys[0];
bx_printf(keystr);
} else if (console.keys[0] == 0x0d) {
s[pos] = 0x00;
keystr[0] = 0x0a;
bx_printf(keystr);
done = 1;
} else if ((console.keys[0] == 0x08) && (pos > 0)) {
pos--;
keystr[0] = 0x08;
bx_printf(keystr);
}
memcpy(&console.keys[0], &console.keys[1], 15);
console.n_keys--;
}
#if BX_HAVE_USLEEP
usleep(25000);
#else
msleep(25);
#endif
} while (!done);
return s;
}
#endif

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002-2015 The Bochs Project
// Copyright (C) 2002-2017 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -162,6 +162,14 @@ public:
void init_debug_dialog(void);
void close_debug_dialog(void);
#endif
#if BX_USE_TEXTCONFIG
// gui console support
bx_bool has_gui_console(void) {return console.present;}
void console_refresh(bx_bool force);
void console_key_enq(Bit8u key);
int bx_printf(const char *s);
char* bx_gets(char *s, int size);
#endif
protected:
// And these are defined and used privately in gui.cc
@ -183,6 +191,11 @@ protected:
// status bar LED timer
static void led_timer_handler(void *);
void led_timer(void);
#if BX_USE_TEXTCONFIG
// gui console support
void console_init(void);
void console_cleanup(void);
#endif
// header bar buttons
bx_bool floppyA_status;
@ -231,6 +244,7 @@ protected:
unsigned y_tilesize;
// current guest display settings
bx_bool guest_textmode;
unsigned guest_fsize;
unsigned guest_xres;
unsigned guest_yres;
unsigned guest_bpp;
@ -252,6 +266,24 @@ protected:
int user_shortcut_len;
// gui dialog capabilities
Bit32u dialog_caps;
#if BX_USE_TEXTCONFIG
// gui console support
struct {
bx_bool present;
bx_bool running;
Bit8u *screen;
Bit8u *oldscreen;
unsigned saved_fsize;
unsigned saved_xres;
unsigned saved_yres;
unsigned saved_bpp;
unsigned cursor_x;
unsigned cursor_y;
bx_vga_tminfo_t tminfo;
Bit8u keys[16];
Bit8u n_keys;
} console;
#endif
};

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2010-2015 The Bochs Project
// Copyright (C) 2010-2017 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -167,8 +167,8 @@ public:
void *get_device_param() { return device; }
#if BX_USE_TEXTCONFIG
virtual void text_print(FILE *fp) {}
virtual int text_ask(FILE *fpin, FILE *fpout) { return -1; }
virtual void text_print() {}
virtual int text_ask() { return -1; }
#endif
virtual int parse_param(const char *value) { return -1; }
@ -230,8 +230,8 @@ public:
static Bit32u set_default_base(Bit32u val);
static Bit32u get_default_base() { return default_base; }
#if BX_USE_TEXTCONFIG
virtual void text_print(FILE *fp);
virtual int text_ask(FILE *fpin, FILE *fpout);
virtual void text_print();
virtual int text_ask();
#endif
virtual int parse_param(const char *value);
};
@ -314,8 +314,8 @@ public:
Bit64s initial_val,
bx_bool is_shadow = 0);
#if BX_USE_TEXTCONFIG
virtual void text_print(FILE *fp);
virtual int text_ask(FILE *fpin, FILE *fpout);
virtual void text_print();
virtual int text_ask();
#endif
virtual int parse_param(const char *value);
};
@ -363,8 +363,8 @@ public:
Bit64u get_dependent_bitmap(Bit64s value);
virtual void set_enabled(int enabled);
#if BX_USE_TEXTCONFIG
virtual void text_print(FILE *fp);
virtual int text_ask(FILE *fpin, FILE *fpout);
virtual void text_print();
virtual int text_ask();
#endif
virtual int parse_param(const char *value);
};
@ -412,8 +412,8 @@ public:
bx_bool isempty();
int sprint(char *buf, int buflen, bx_bool dquotes);
#if BX_USE_TEXTCONFIG
virtual void text_print(FILE *fp);
virtual int text_ask(FILE *fpin, FILE *fpout);
virtual void text_print();
virtual int text_ask();
#endif
virtual int parse_param(const char *value);
};
@ -541,8 +541,8 @@ public:
void set_restore_handler(void *devptr, list_restore_handler restore);
void restore();
#if BX_USE_TEXTCONFIG
virtual void text_print(FILE *);
virtual int text_ask(FILE *fpin, FILE *fpout);
virtual void text_print();
virtual int text_ask();
#endif
};

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002-2016 The Bochs Project
// Copyright (C) 2002-2017 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -218,6 +218,11 @@ public:
const char *param, int maxports, bx_list_c *base);
virtual int write_param_list(FILE *fp, bx_list_c *base, const char *optname, bx_bool multiline);
virtual int write_usb_options(FILE *fp, int maxports, bx_list_c *base);
#if BX_USE_TEXTCONFIG
// gui console support
virtual int bx_printf(const char *fmt, ...);
virtual char* bx_gets(char *s, int size, FILE *stream);
#endif
private:
bx_bool save_sr_param(FILE *fp, bx_param_c *node, const char *sr_path, int level);
@ -1571,3 +1576,31 @@ int bx_real_sim_c::write_usb_options(FILE *fp, int maxports, bx_list_c *base)
{
return bx_write_usb_options(fp, maxports, base);
}
#if BX_USE_TEXTCONFIG
int bx_real_sim_c::bx_printf(const char *fmt, ...)
{
va_list ap;
char buf[1025];
va_start(ap, fmt);
vsnprintf(buf, 1024, fmt, ap);
va_end(ap);
if (get_init_done()) {
if (bx_gui->has_gui_console()) {
return bx_gui->bx_printf(buf);
}
}
return printf(buf);
}
char* bx_real_sim_c::bx_gets(char *s, int size, FILE *stream)
{
if (get_init_done()) {
if (bx_gui->has_gui_console()) {
return bx_gui->bx_gets(s, size);
}
}
return fgets(s, size, stream);
}
#endif

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2016 The Bochs Project
// Copyright (C) 2001-2017 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -826,6 +826,12 @@ public:
const char *param, int maxports, bx_list_c *base) {return 0;}
virtual int write_param_list(FILE *fp, bx_list_c *base, const char *optname, bx_bool multiline) {return 0;}
virtual int write_usb_options(FILE *fp, int maxports, bx_list_c *base) {return 0;}
#if BX_USE_TEXTCONFIG
// gui console support
virtual int bx_printf(const char *fmt, ...) {return 0;}
virtual char* bx_gets(char *s, int size, FILE *stream) {return NULL;}
#endif
};
BOCHSAPI extern bx_simulator_interface_c *SIM;

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002-2016 The Bochs Project
// Copyright (C) 2002-2017 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -55,6 +55,9 @@ extern "C" {
#define CI_PATH_LENGTH 512
#define bx_printf SIM->bx_printf
#define bx_fgets SIM->bx_gets
/* functions for changing particular options */
void bx_config_interface_init();
int bx_read_rc(char *rc);
@ -94,9 +97,9 @@ int ask_uint(const char *prompt, const char *help, Bit32u min, Bit32u max, Bit32
int illegal;
assert(base==10 || base==16);
while (1) {
printf(prompt, the_default);
bx_printf(prompt, the_default);
fflush(stdout);
if (!fgets(buffer, sizeof(buffer), stdin))
if (!bx_fgets(buffer, sizeof(buffer), stdin))
return -1;
clean = clean_string(buffer);
if (strlen(clean) < 1) {
@ -105,11 +108,11 @@ int ask_uint(const char *prompt, const char *help, Bit32u min, Bit32u max, Bit32
return 0;
}
if ((clean[0] == '?') && (strlen(help) > 0)) {
printf("\n%s\n", help);
bx_printf("\n%s\n", help);
if (base == 10) {
printf("Your choice must be an integer between %u and %u.\n\n", min, max);
bx_printf("Your choice must be an integer between %u and %u.\n\n", min, max);
} else {
printf("Your choice must be an integer between 0x%x and 0x%x.\n\n", min, max);
bx_printf("Your choice must be an integer between 0x%x and 0x%x.\n\n", min, max);
}
continue;
}
@ -117,10 +120,10 @@ int ask_uint(const char *prompt, const char *help, Bit32u min, Bit32u max, Bit32
illegal = (1 != sscanf(buffer, format, &n));
if (illegal || n<min || n>max) {
if (base == 10) {
printf("Your choice (%s) was not an integer between %u and %u.\n\n",
bx_printf("Your choice (%s) was not an integer between %u and %u.\n\n",
clean, min, max);
} else {
printf("Your choice (%s) was not an integer between 0x%x and 0x%x.\n\n",
bx_printf("Your choice (%s) was not an integer between 0x%x and 0x%x.\n\n",
clean, min, max);
}
} else {
@ -139,9 +142,9 @@ int ask_int(const char *prompt, const char *help, Bit32s min, Bit32s max, Bit32s
char *clean;
int illegal;
while (1) {
printf(prompt, the_default);
bx_printf(prompt, the_default);
fflush(stdout);
if (!fgets(buffer, sizeof(buffer), stdin))
if (!bx_fgets(buffer, sizeof(buffer), stdin))
return -1;
clean = clean_string(buffer);
if (strlen(clean) < 1) {
@ -150,13 +153,13 @@ int ask_int(const char *prompt, const char *help, Bit32s min, Bit32s max, Bit32s
return 0;
}
if ((clean[0] == '?') && (strlen(help) > 0)) {
printf("\n%s\n", help);
printf("Your choice must be an integer between %u and %u.\n\n", min, max);
bx_printf("\n%s\n", help);
bx_printf("Your choice must be an integer between %u and %u.\n\n", min, max);
continue;
}
illegal = (1 != sscanf(buffer, "%d", &n));
if (illegal || n<min || n>max) {
printf("Your choice (%s) was not an integer between %d and %d.\n\n",
bx_printf("Your choice (%s) was not an integer between %d and %d.\n\n",
clean, min, max);
} else {
// choice is okay
@ -173,9 +176,9 @@ int ask_menu(const char *prompt, const char *help, int n_choices, const char *ch
int i;
*out = -1;
while (1) {
printf(prompt, choice[the_default]);
bx_printf(prompt, choice[the_default]);
fflush(stdout);
if (!fgets(buffer, sizeof(buffer), stdin))
if (!bx_fgets(buffer, sizeof(buffer), stdin))
return -1;
clean = clean_string(buffer);
if (strlen(clean) < 1) {
@ -191,15 +194,15 @@ int ask_menu(const char *prompt, const char *help, int n_choices, const char *ch
}
}
if (clean[0] != '?') {
printf("Your choice (%s) did not match any of the choices:\n", clean);
bx_printf("Your choice (%s) did not match any of the choices:\n", clean);
} else if (strlen(help) > 0) {
printf("\n%s\nValid values are: ", help);
bx_printf("\n%s\nValid values are: ", help);
}
for (i=0; i<n_choices; i++) {
if (i>0) printf(", ");
printf("%s", choice[i]);
if (i>0) bx_printf(", ");
bx_printf("%s", choice[i]);
}
printf("\n");
bx_printf("\n");
}
}
@ -210,9 +213,9 @@ int ask_yn(const char *prompt, const char *help, Bit32u the_default, Bit32u *out
*out = 1<<31;
while (1) {
// if there's a %s field, substitute in the default yes/no.
printf(prompt, the_default ? "yes" : "no");
bx_printf(prompt, the_default ? "yes" : "no");
fflush(stdout);
if (!fgets(buffer, sizeof(buffer), stdin))
if (!bx_fgets(buffer, sizeof(buffer), stdin))
return -1;
clean = clean_string(buffer);
if (strlen(clean) < 1) {
@ -225,11 +228,11 @@ int ask_yn(const char *prompt, const char *help, Bit32u the_default, Bit32u *out
case 'n': *out=0; return 0;
case '?':
if (strlen(help) > 0) {
printf("\n%s\n", help);
bx_printf("\n%s\n", help);
}
break;
}
printf("Please type either yes or no.\n");
bx_printf("Please type either yes or no.\n");
}
}
@ -243,9 +246,9 @@ int ask_string(const char *prompt, const char *the_default, char *out)
char *clean;
assert(the_default != out);
out[0] = 0;
printf(prompt, the_default);
bx_printf(prompt, the_default);
fflush(stdout);
if (fgets(buffer, sizeof(buffer), stdin) == NULL)
if (bx_fgets(buffer, sizeof(buffer), stdin) == NULL)
return -1;
clean = clean_string(buffer);
if (clean[0] == '?')
@ -339,10 +342,10 @@ static const char *plugin_ctrl_prompt =
"Please choose one: [0] ";
#define NOT_IMPLEMENTED(choice) \
fprintf(stderr, "ERROR: choice %d not implemented\n", choice);
bx_printf("ERROR: choice %d not implemented\n", choice);
#define BAD_OPTION(menu,choice) \
do {fprintf(stderr, "ERROR: menu %d has no choice %d\n", menu, choice); \
do {bx_printf("ERROR: menu %d has no choice %d\n", menu, choice); \
assert(0); } while (0)
void build_runtime_options_prompt(const char *format, char *buf, int size)
@ -372,7 +375,7 @@ int do_menu(const char *pname)
bx_list_c *menu = (bx_list_c *)SIM->get_param(pname, NULL);
while (1) {
menu->set_choice(0);
int status = menu->text_ask(stdin, stderr);
int status = menu->text_ask();
if (status < 0) return status;
if (menu->get_choice() < 1)
return menu->get_choice();
@ -382,25 +385,19 @@ int do_menu(const char *pname)
assert(chosen != NULL);
if (chosen->get_enabled()) {
if (SIM->get_init_done() && !chosen->get_runtime_param()) {
fprintf(stderr, "\nWARNING: parameter not available at runtime!\n");
bx_printf("\nWARNING: parameter not available at runtime!\n");
} else if (chosen->get_type() == BXT_LIST) {
char chosen_pname[80];
chosen->get_param_path(chosen_pname, 80);
do_menu(chosen_pname);
} else {
chosen->text_ask(stdin, stderr);
chosen->text_ask();
}
}
}
}
}
void askparam(char *pname)
{
bx_param_c *param = SIM->get_param(pname);
param->text_ask(stdin, stderr);
}
int bx_config_interface(int menu)
{
Bit32u choice;
@ -430,7 +427,7 @@ int bx_config_interface(int menu)
if (ask_uint(startup_menu_prompt, "", 1, n_choices, default_choice, &choice, 10) < 0) return -1;
switch (choice) {
case 1:
fprintf(stderr, "I reset all options back to their factory defaults.\n\n");
bx_printf("I reset all options back to their factory defaults.\n\n");
SIM->reset_all_param();
SIM->get_param_enum(BXPN_BOCHS_START)->set(BX_EDIT_START);
break;
@ -509,10 +506,10 @@ int bx_config_interface(int menu)
break;
case BX_CI_RT_CONT:
SIM->update_runtime_options();
fprintf(stderr, "Continuing simulation\n");
bx_printf("Continuing simulation\n");
return 0;
case BX_CI_RT_QUIT:
fprintf(stderr, "You chose quit on the configuration interface.\n");
bx_printf("You chose quit on the configuration interface.\n");
bx_user_quit = 1;
#if !BX_DEBUGGER
bx_atexit();
@ -521,12 +518,12 @@ int bx_config_interface(int menu)
bx_dbg_exit(1);
#endif
return -1;
default: fprintf(stderr, "Menu choice %d not implemented.\n", choice);
default: bx_printf("Menu choice %d not implemented.\n", choice);
}
}
break;
default:
fprintf(stderr, "Unknown config interface menu type.\n");
bx_printf("Unknown config interface menu type.\n");
assert(menu >=0 && menu < BX_CI_N_MENUS);
}
}
@ -535,18 +532,18 @@ int bx_config_interface(int menu)
static void bx_print_log_action_table()
{
// just try to print all the prefixes first.
fprintf(stderr, "Current log settings:\n");
fprintf(stderr, " Debug Info Error Panic\n");
fprintf(stderr, "ID Device Action Action Action Action\n");
fprintf(stderr, "---- --------- --------- --------- ---------- ----------\n");
bx_printf("Current log settings:\n");
bx_printf(" Debug Info Error Panic\n");
bx_printf("ID Device Action Action Action Action\n");
bx_printf("---- --------- --------- --------- ---------- ----------\n");
int i, j, imax=SIM->get_n_log_modules();
for (i=0; i<imax; i++) {
if (strcmp(SIM->get_prefix(i), BX_NULL_PREFIX)) {
fprintf(stderr, "%3d. %s ", i, SIM->get_prefix(i));
bx_printf("%3d. %s ", i, SIM->get_prefix(i));
for (j=0; j<SIM->get_max_log_level(); j++) {
fprintf(stderr, "%10s ", SIM->get_action_name(SIM->get_log_action(i, j)));
bx_printf("%10s ", SIM->get_action_name(SIM->get_log_action(i, j)));
}
fprintf(stderr, "\n");
bx_printf("\n");
}
}
}
@ -566,7 +563,7 @@ void bx_log_options(int individual)
if (ask_int(log_options_prompt1, "", -1, maxid-1, -1, &id) < 0)
return;
if (id < 0) return;
fprintf(stderr, "Editing log options for the device %s\n", SIM->get_prefix(id));
bx_printf("Editing log options for the device %s\n", SIM->get_prefix(id));
for (level=0; level<SIM->get_max_log_level(); level++) {
char prompt[1024];
int default_action = SIM->get_log_action(id, level);
@ -579,7 +576,7 @@ void bx_log_options(int individual)
if (!BX_LOG_OPTS_EXCLUDE(level, action)) {
SIM->set_log_action(id, level, action);
} else {
fprintf(stderr, "Event type '%s' does not support log action '%s'.\n",
bx_printf("Event type '%s' does not support log action '%s'.\n",
SIM->get_log_level_name(level), log_level_choices[action]);
}
}
@ -599,7 +596,7 @@ void bx_log_options(int individual)
SIM->set_default_log_action(level, action);
SIM->set_log_action(-1, level, action);
} else {
fprintf(stderr, "Event type '%s' does not support log action '%s'.\n",
bx_printf("Event type '%s' does not support log action '%s'.\n",
SIM->get_log_level_name(level), log_level_choices[action]);
}
}
@ -618,7 +615,7 @@ int bx_read_rc(char *rc)
if (ask_string("\nWhat is the configuration file name?\nTo cancel, type 'none'. [%s] ", oldrc, newrc) < 0) return -1;
if (!strcmp(newrc, "none")) return -1;
if (SIM->read_rc(newrc) >= 0) return 0;
fprintf(stderr, "The file '%s' could not be found.\n", newrc);
bx_printf("The file '%s' could not be found.\n", newrc);
}
}
@ -638,7 +635,7 @@ int bx_write_rc(char *rc)
// try with overwrite off first
int status = SIM->write_rc(newrc, 0);
if (status >= 0) {
fprintf(stderr, "Wrote configuration to '%s'.\n", newrc);
bx_printf("Wrote configuration to '%s'.\n", newrc);
return 0;
} else if (status == -2) {
// return code -2 indicates the file already exists, and overwrite
@ -650,10 +647,10 @@ int bx_write_rc(char *rc)
if (!overwrite) continue; // if "no", start loop over, asking for a different file
// they confirmed, so try again with overwrite bit set
if (SIM->write_rc(newrc, 1) >= 0) {
fprintf(stderr, "Overwriting existing configuration '%s'.\n", newrc);
bx_printf("Overwriting existing configuration '%s'.\n", newrc);
return 0;
} else {
fprintf(stderr, "Write failed to '%s'.\n", newrc);
bx_printf("Write failed to '%s'.\n", newrc);
}
}
}
@ -674,27 +671,27 @@ void bx_plugin_ctrl()
plugin_ctrl = (bx_list_c*) SIM->get_param(BXPN_PLUGIN_CTRL);
count = plugin_ctrl->get_size();
if (count == 0) {
fprintf(stderr, "\nNo optional plugins loaded\n");
bx_printf("\nNo optional plugins loaded\n");
} else {
fprintf(stderr, "\nCurrently loaded plugins:");
bx_printf("\nCurrently loaded plugins:");
for (int i = 0; i < count; i++) {
if (i > 0) fprintf(stderr, ",");
fprintf(stderr, " %s", plugin_ctrl->get(i)->get_name());
if (i > 0) bx_printf(",");
bx_printf(" %s", plugin_ctrl->get(i)->get_name());
}
fprintf(stderr, "\n");
bx_printf("\n");
}
if (choice == 1) {
ask_string("\nEnter the name of the plugin to load.\nTo cancel, type 'none'. [%s] ", "none", plugname);
if (strcmp(plugname, "none")) {
if (!SIM->opt_plugin_ctrl(plugname, 1)) {
fprintf(stderr, "\nPlugin already loaded.\n");
bx_printf("\nPlugin already loaded.\n");
}
}
} else {
ask_string("\nEnter the name of the plugin to unload.\nTo cancel, type 'none'. [%s] ", "none", plugname);
if (strcmp(plugname, "none")) {
if (!SIM->opt_plugin_ctrl(plugname, 0)) {
fprintf(stderr, "\nNo plugin unloaded.\n");
bx_printf("\nNo plugin unloaded.\n");
}
}
}
@ -715,7 +712,7 @@ config_interface_notify_callback(void *unused, BxEvent *event)
event->retcode = 0;
return event;
case BX_SYNC_EVT_ASK_PARAM:
event->retcode = event->u.param.param->text_ask(stdin, stderr);
event->retcode = event->u.param.param->text_ask();
return event;
case BX_SYNC_EVT_LOG_DLG:
if (event->u.logmsg.mode == BX_LOG_DLG_ASK) {
@ -774,97 +771,97 @@ void bx_config_interface_init()
/////////////////////////////////////////////////////////////////////
// implement the text_* methods for bx_param types.
void bx_param_num_c::text_print(FILE *fp)
void bx_param_num_c::text_print()
{
if (get_long_format()) {
fprintf(fp, get_long_format(), get());
bx_printf(get_long_format(), get());
} else {
const char *format = "%s: %d";
assert(base==10 || base==16);
if (base==16) format = "%s: 0x%x";
if (get_label()) {
fprintf(fp, format, get_label(), get());
bx_printf(format, get_label(), get());
} else {
fprintf(fp, format, get_name(), get());
bx_printf(format, get_name(), get());
}
}
}
void bx_param_bool_c::text_print(FILE *fp)
void bx_param_bool_c::text_print()
{
if (get_format()) {
fprintf(fp, get_format(), get() ? "yes" : "no");
bx_printf(get_format(), get() ? "yes" : "no");
} else {
const char *format = "%s: %s";
if (get_label()) {
fprintf(fp, format, get_label(), get() ? "yes" : "no");
bx_printf(format, get_label(), get() ? "yes" : "no");
} else {
fprintf(fp, format, get_name(), get() ? "yes" : "no");
bx_printf(format, get_name(), get() ? "yes" : "no");
}
}
}
void bx_param_enum_c::text_print(FILE *fp)
void bx_param_enum_c::text_print()
{
int n = get();
assert(n >= min && n <= max);
const char *choice = choices[n - min];
if (get_format()) {
fprintf(fp, get_format(), choice);
bx_printf(get_format(), choice);
} else {
const char *format = "%s: %s";
if (get_label()) {
fprintf(fp, format, get_label(), choice);
bx_printf(format, get_label(), choice);
} else {
fprintf(fp, format, get_name(), choice);
bx_printf(format, get_name(), choice);
}
}
}
void bx_param_string_c::text_print(FILE *fp)
void bx_param_string_c::text_print()
{
char value[1024];
this->sprint(value, 1024, 0);
if (get_format()) {
fprintf(fp, get_format(), value);
bx_printf(get_format(), value);
} else {
if (get_label()) {
fprintf(fp, "%s: %s", get_label(), value);
bx_printf("%s: %s", get_label(), value);
} else {
fprintf(fp, "%s: %s", get_name(), value);
bx_printf("%s: %s", get_name(), value);
}
}
}
void bx_list_c::text_print(FILE *fp)
void bx_list_c::text_print()
{
bx_listitem_t *item;
int i = 0;
fprintf(fp, "%s: ", get_name());
bx_printf("%s: ", get_name());
for (item = list; item; item = item->next) {
if (item->param->get_enabled()) {
if ((i > 0) && (options & SERIES_ASK))
fprintf(fp, ", ");
item->param->text_print(fp);
bx_printf(", ");
item->param->text_print();
if (!(options & SERIES_ASK))
fprintf(fp, "\n");
bx_printf("\n");
}
i++;
}
}
int bx_param_num_c::text_ask(FILE *fpin, FILE *fpout)
int bx_param_num_c::text_ask()
{
fprintf(fpout, "\n");
bx_printf("\n");
int status;
const char *prompt = get_ask_format();
const char *help = get_description();
if (prompt == NULL) {
// default prompt, if they didn't set an ask format string
text_print(fpout);
fprintf(fpout, "\n");
text_print();
bx_printf("\n");
prompt = "Enter new value or '?' for help: [%d] ";
if (base==16)
prompt = "Enter new value in hex or '?' for help: [%x] ";
@ -876,9 +873,9 @@ int bx_param_num_c::text_ask(FILE *fpin, FILE *fpout)
return 0;
}
int bx_param_bool_c::text_ask(FILE *fpin, FILE *fpout)
int bx_param_bool_c::text_ask()
{
fprintf(fpout, "\n");
bx_printf("\n");
int status;
const char *prompt = get_ask_format();
const char *help = get_description();
@ -900,16 +897,16 @@ int bx_param_bool_c::text_ask(FILE *fpin, FILE *fpout)
return 0;
}
int bx_param_enum_c::text_ask(FILE *fpin, FILE *fpout)
int bx_param_enum_c::text_ask()
{
fprintf(fpout, "\n");
bx_printf("\n");
const char *prompt = get_ask_format();
const char *help = get_description();
if (prompt == NULL) {
// default prompt, if they didn't set an ask format string
fprintf(fpout, "%s = ", get_name());
text_print(fpout);
fprintf(fpout, "\n");
bx_printf("%s = ", get_name());
text_print();
bx_printf("\n");
prompt = "Enter new value or '?' for help: [%s] ";
}
Bit32s n = (Bit32s)(get() - min);
@ -941,19 +938,19 @@ int parse_raw_bytes(char *dest, char *src, int destsize, char separator)
return 0;
}
int bx_param_string_c::text_ask(FILE *fpin, FILE *fpout)
int bx_param_string_c::text_ask()
{
fprintf(fpout, "\n");
bx_printf("\n");
int status;
const char *prompt = get_ask_format();
if (prompt == NULL) {
if (options & SELECT_FOLDER_DLG) {
fprintf(fpout, "%s\n\n", get_label());
bx_printf("%s\n\n", get_label());
prompt = "Enter a path to an existing folder or press enter to cancel\n";
} else {
// default prompt, if they didn't set an ask format string
text_print(fpout);
fprintf(fpout, "\n");
text_print();
bx_printf("\n");
prompt = "Enter a new value, '?' for help, or press return for no change.\n";
}
}
@ -961,7 +958,7 @@ int bx_param_string_c::text_ask(FILE *fpin, FILE *fpout)
char buffer[1024];
status = ask_string(prompt, getptr(), buffer);
if (status == -2) {
fprintf(fpout, "\n%s\n", get_description());
bx_printf("\n%s\n", get_description());
continue;
}
if (status < 0) return status;
@ -973,7 +970,7 @@ int bx_param_string_c::text_ask(FILE *fpin, FILE *fpout)
// copy raw hex into buffer
status = parse_raw_bytes(buffer, buffer2, maxsize, separator);
if (status < 0) {
fprintf(fpout, "Illegal raw byte format. I expected something like 3A%c03%c12%c...\n", separator, separator, separator);
bx_printf("Illegal raw byte format. I expected something like 3A%c03%c12%c...\n", separator, separator, separator);
continue;
}
}
@ -983,54 +980,54 @@ int bx_param_string_c::text_ask(FILE *fpin, FILE *fpout)
}
}
int bx_list_c::text_ask(FILE *fpin, FILE *fpout)
int bx_list_c::text_ask()
{
bx_listitem_t *item;
bx_list_c *child;
const char *my_title = title;
fprintf(fpout, "\n");
bx_printf("\n");
int i, imax = strlen(my_title);
for (i=0; i<imax; i++) fprintf(fpout, "-");
fprintf(fpout, "\n%s\n", my_title);
for (i=0; i<imax; i++) fprintf(fpout, "-");
fprintf(fpout, "\n");
for (i=0; i<imax; i++) bx_printf("-");
bx_printf("\n%s\n", my_title);
for (i=0; i<imax; i++) bx_printf("-");
bx_printf("\n");
if (options & SERIES_ASK) {
for (item = list; item; item = item->next) {
if (item->param->get_enabled()) {
if (!SIM->get_init_done() || item->param->get_runtime_param()) {
item->param->text_ask(fpin, fpout);
item->param->text_ask();
}
}
}
} else {
if (options & SHOW_PARENT)
fprintf(fpout, "0. Return to previous menu\n");
bx_printf("0. Return to previous menu\n");
int i = 0;
for (item = list; item; item = item->next) {
fprintf(fpout, "%d. ", i+1);
bx_printf("%d. ", i+1);
if ((item->param->get_enabled()) &&
(!SIM->get_init_done() || item->param->get_runtime_param())) {
if (item->param->get_type() == BXT_LIST) {
child = (bx_list_c*)item->param;
fprintf(fpout, "%s\n", child->get_title());
bx_printf("%s\n", child->get_title());
} else {
if ((options & SHOW_GROUP_NAME) && (item->param->get_group() != NULL))
fprintf(fpout, "%s ", item->param->get_group());
item->param->text_print(fpout);
fprintf(fpout, "\n");
bx_printf("%s ", item->param->get_group());
item->param->text_print();
bx_printf("\n");
}
} else {
if (item->param->get_type() == BXT_LIST) {
child = (bx_list_c*)item->param;
fprintf(fpout, "%s (disabled)\n", child->get_title());
bx_printf("%s (disabled)\n", child->get_title());
} else {
fprintf(fpout, "(disabled)\n");
bx_printf("(disabled)\n");
}
}
i++;
}
fprintf(fpout, "\n");
bx_printf("\n");
int min = (options & SHOW_PARENT) ? 0 : 1;
int max = size;
int status = ask_uint("Please choose one: [%d] ", "", min, max, choice, &choice, 10);
@ -1046,10 +1043,10 @@ static int ci_callback(void *userdata, ci_command_t command)
case CI_START:
bx_config_interface_init();
if (SIM->get_param_enum(BXPN_BOCHS_START)->get() == BX_QUICK_START)
bx_config_interface(BX_CI_START_SIMULATION);
bx_config_interface(BX_CI_START_SIMULATION);
else {
if (!SIM->test_for_text_console())
return CI_ERR_NO_TEXT_CONSOLE;
return CI_ERR_NO_TEXT_CONSOLE;
bx_config_interface(BX_CI_START_MENU);
}
break;

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2016 The Bochs Project
// Copyright (C) 2001-2017 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -63,12 +63,17 @@ public:
#endif
virtual void beep_on(float frequency);
virtual void beep_off();
virtual void set_display_mode(disp_mode_t newmode);
virtual void statusbar_setitem_specific(int element, bx_bool active, bx_bool w);
virtual void get_capabilities(Bit16u *xres, Bit16u *yres, Bit16u *bpp);
virtual void set_mouse_mode_absxy(bx_bool mode);
#if BX_SHOW_IPS
virtual void show_ips(Bit32u ips_count);
#endif
private:
void headerbar_click(int x);
void send_mouse_status(void);
void xkeypress(KeySym keysym, int press_release);
};
// declare one instance of the gui object and call macro to insert the
@ -170,8 +175,6 @@ static char x11_ips_text[20];
static Bit8u x11_mouse_msg_counter = 0;
#endif
static void headerbar_click(int x, int y);
static void send_keyboard_mouse_status(void);
static void set_status_text(int element, const char *text, bx_bool active, bx_bool w=0);
@ -301,7 +304,6 @@ Bit32u ascii_to_key_event[0x5f] = {
extern Bit8u graphics_snapshot[32 * 1024];
static void create_internal_vga_font(void);
static void xkeypress(KeySym keysym, int press_release);
// extern "C" void select_visual(void);
#define ROUNDUP(nbytes, pad) ((((nbytes) + ((pad)-1)) / (pad)) * ((pad)>>3))
@ -693,6 +695,9 @@ void bx_x_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y)
new_gfx_api = 1;
dialog_caps |= (BX_GUI_DLG_USER | BX_GUI_DLG_SNAPSHOT | BX_GUI_DLG_CDROM);
#if BX_USE_TEXTCONFIG
console.present = 1;
#endif
}
void set_status_text(int element, const char *text, bx_bool active, bx_bool w)
@ -836,17 +841,20 @@ void bx_x_gui_c::handle_events(void)
y = 0;
}
DEV_vga_redraw_area(
(unsigned) expose_event->x,
y,
(unsigned) expose_event->width,
height);
#if BX_USE_TEXTCONFIG
if (console.running) {
console_refresh(1);
} else
#endif
{
DEV_vga_redraw_area((unsigned) expose_event->x, y,
(unsigned) expose_event->width, height);
}
/* Always draw headerbar, even if not touched by expose event.
* As a small optimization, only do it on last contigous expose.
*/
if (expose_event->count == 0) {
show_headerbar();
show_headerbar();
}
break;
@ -865,12 +873,12 @@ void bx_x_gui_c::handle_events(void)
BX_DEBUG(("xxx: in headerbar"));
if (mouse_update) {
BX_DEBUG(("xxx: mouse_update=1"));
send_keyboard_mouse_status();
send_mouse_status();
mouse_update = 0;
}
prev_x = current_x = -1;
prev_y = current_y = -1;
headerbar_click(button_event->x, button_event->y);
headerbar_click(button_event->x);
break;
}
current_x = button_event->x;
@ -880,7 +888,7 @@ void bx_x_gui_c::handle_events(void)
switch (button_event->button) {
case Button1:
mouse_button_state |= 0x01;
send_keyboard_mouse_status();
send_mouse_status();
mouse_update = 0;
break;
case Button2:
@ -888,13 +896,13 @@ void bx_x_gui_c::handle_events(void)
toggle_mouse_enable();
} else {
mouse_button_state |= 0x04;
send_keyboard_mouse_status();
send_mouse_status();
mouse_update = 0;
}
break;
case Button3:
mouse_button_state |= 0x02;
send_keyboard_mouse_status();
send_mouse_status();
mouse_update = 0;
break;
}
@ -904,7 +912,7 @@ void bx_x_gui_c::handle_events(void)
button_event = (XButtonEvent *) &report;
if (button_event->y < BX_HEADER_BAR_Y) {
if (mouse_update) {
send_keyboard_mouse_status();
send_mouse_status();
mouse_update = 0;
}
prev_x = current_x = -1;
@ -918,28 +926,28 @@ void bx_x_gui_c::handle_events(void)
switch (button_event->button) {
case Button1:
mouse_button_state &= ~0x01;
send_keyboard_mouse_status();
send_mouse_status();
mouse_update = 0;
break;
case Button2:
mouse_toggle_check(BX_MT_MBUTTON, 0);
mouse_button_state &= ~0x04;
send_keyboard_mouse_status();
send_mouse_status();
mouse_update = 0;
break;
case Button3:
mouse_button_state &= ~0x02;
send_keyboard_mouse_status();
send_mouse_status();
mouse_update = 0;
break;
case Button4:
current_z = 1;
send_keyboard_mouse_status();
send_mouse_status();
mouse_update = 0;
break;
case Button5:
current_z = -1;
send_keyboard_mouse_status();
send_mouse_status();
mouse_update = 0;
break;
}
@ -1004,7 +1012,7 @@ void bx_x_gui_c::handle_events(void)
if (mouse_update) {
BX_DEBUG(("handle_events(): send mouse status"));
send_keyboard_mouse_status();
send_mouse_status();
}
#if BX_SHOW_IPS
if (x11_ips_update) {
@ -1014,12 +1022,15 @@ void bx_x_gui_c::handle_events(void)
#endif
}
void send_keyboard_mouse_status(void)
void bx_x_gui_c::send_mouse_status(void)
{
int dx, dy, dz;
BX_DEBUG(("XXX: prev=(%d,%d) curr=(%d,%d)",
prev_x, prev_y, current_x, current_y));
#if BX_USE_TEXTCONFIG
if (console.running) return;
#endif
if (x11_mouse_mode_absxy) {
if ((current_y >= (int)bx_headerbar_y) && (current_y < (int)(dimension_y + bx_headerbar_y))) {
dx = current_x * 0x7fff / dimension_x;
@ -1059,22 +1070,31 @@ void bx_x_gui_c::flush(void)
XFlush(bx_x_display);
}
void xkeypress(KeySym keysym, int press_release)
void bx_x_gui_c::xkeypress(KeySym keysym, int press_release)
{
Bit32u key_event;
bx_bool mouse_toggle = 0;
#if BX_USE_TEXTCONFIG
if (console.running && !press_release) {
if (((keysym >= XK_space) && (keysym <= XK_asciitilde)) ||
(keysym == XK_Return) || (keysym == XK_BackSpace)) {
console_key_enq((Bit8u)(keysym & 0xff));
}
return;
}
#endif
if ((keysym == XK_Control_L) || (keysym == XK_Control_R)) {
mouse_toggle = bx_gui->mouse_toggle_check(BX_MT_KEY_CTRL, !press_release);
mouse_toggle = mouse_toggle_check(BX_MT_KEY_CTRL, !press_release);
} else if (keysym == XK_Alt_L) {
mouse_toggle = bx_gui->mouse_toggle_check(BX_MT_KEY_ALT, !press_release);
mouse_toggle = mouse_toggle_check(BX_MT_KEY_ALT, !press_release);
} else if (keysym == XK_F10) {
mouse_toggle = bx_gui->mouse_toggle_check(BX_MT_KEY_F10, !press_release);
mouse_toggle = mouse_toggle_check(BX_MT_KEY_F10, !press_release);
} else if (keysym == XK_F12) {
mouse_toggle = bx_gui->mouse_toggle_check(BX_MT_KEY_F12, !press_release);
}
if (mouse_toggle) {
bx_gui->toggle_mouse_enable();
toggle_mouse_enable();
return;
}
@ -1738,6 +1758,7 @@ void bx_x_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight, unsi
BX_PANIC(("%d bpp graphics mode not supported", bpp));
}
guest_textmode = (fheight > 0);
guest_fsize = (fheight << 4) | fwidth;
guest_xres = x;
guest_yres = y;
if (guest_textmode) {
@ -1868,18 +1889,20 @@ void bx_x_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id)
xorigin, 0, 1);
}
void headerbar_click(int x, int y)
void bx_x_gui_c::headerbar_click(int x)
{
int xorigin;
// assuming y is in bounds
UNUSED(y);
for (unsigned i=0; i<bx_headerbar_entries; i++) {
if (bx_headerbar_entry[i].alignment == BX_GRAVITY_LEFT)
xorigin = bx_headerbar_entry[i].xorigin;
else
xorigin = dimension_x - bx_headerbar_entry[i].xorigin;
if ((x>=xorigin) && (x<(xorigin+int(bx_headerbar_entry[i].xdim)))) {
#if BX_USE_TEXTCONFIG
if (console.running && (i != power_hbar_id))
return;
#endif
bx_headerbar_entry[i].f();
return;
}
@ -2123,6 +2146,19 @@ void bx_x_gui_c::show_ips(Bit32u ips_count)
}
#endif
void bx_x_gui_c::set_display_mode(disp_mode_t newmode)
{
// if no mode change, do nothing.
if (disp_mode == newmode) return;
// remember the display mode for next time
disp_mode = newmode;
#if BX_USE_TEXTCONFIG
if ((newmode == DISP_MODE_SIM) && console.running) {
console_cleanup();
}
#endif
}
// X11 control class
enum {