Bochs/bochs/gui/siminterface.h
Volker Ruppert 6ad19a7716 Rewrite of the sound driver handling similar to the hdimage and networking
module code. Sound driver names are now stored as string constants instead
of hardcoded values. Available modules are detected at Bochs startup and stored
in a string array before initializing options. In the plugins case available
modules are read from the plugins list. If plugins are off, the registry of
bx_sound_lowlevel_c is used. Related changes similar to the hdimage and
network modifications.
2021-02-06 16:51:55 +00:00

819 lines
35 KiB
C++

/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2021 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
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
/////////////////////////////////////////////////////////////////////////
#ifndef BX_SIM_INTERFACE_H
#define BX_SIM_INTERFACE_H
//
// Intro to siminterface by Bryce Denney:
//
// Before I can describe what this file is for, I have to make the
// distinction between a configuration interface (CI) and the VGA display
// window (VGAW). I will try to avoid the term 'GUI' because it is unclear
// if that means CI or VGAW, and because not all interfaces are graphical
// anyway.
//
// The traditional Bochs screen is a window with a large VGA display panel and
// a series of buttons (floppy, cdrom, snapshot, power). Over the years, we
// have collected many implementations of the VGAW for different environments
// and platforms; each implementation is in a separate file under gui/*:
// x.cc, win32.cc, macintosh.cc, etc. The files gui.h and gui.cc
// define the platform independent part of the VGAW, leaving about 15 methods
// of the bx_gui_c class undefined. The platform dependent file must
// implement the remaining 15 methods.
//
// The configuration interface is relatively new, started by Bryce Denney in
// June 2001. The CI is intended to allow the user to edit a variety of
// configuration and runtime options. Some options, such as memory size or
// enabling the ethernet card, should only be changed before the simulation
// begins; others, such as floppy disk image, instructions per second, and
// logging options can be safely changed at runtime. The CI allows the user to
// make these changes. Before the CI existed, only a few things could be
// changed at runtime, all linked to clicking on the VGAW buttons.
//
// At the time that the CI was conceived, we were still debating what form the
// user interface part would take: stdin/stdout menus, a graphical application
// with menus and dialogs running in a separate thread, or even a tiny web
// server that you can connect to with a web browser. As a result the
// interface to the CI was designed so that the user interface of the CI
// could be replaced easily at compile time, or maybe even at runtime via
// a plugin architecture. To this end, we kept a clear separation between
// the user interface code and the siminterface, the code that interfaces with
// the simulator. The same siminterface is used all the time, while
// different implementations of the CI can be switched in reasonably easily.
// Only the CI code uses library specific graphics and I/O functions; the
// siminterface deals in portable abstractions and callback functions.
// The first CI implementation was a series of text mode menus implemented in
// textconfig.cc.
//
// The configuration interface MUST use the siminterface methods to access the
// simulator. It should not modify settings in some device with code like
// bx_floppy.s.media[2].heads = 17. If such access is needed, then a
// siminterface method should be written to make the change on the CI's behalf.
// This separation is enforced by the fact that the CI does not even include
// bochs.h. You'll notice that textconfig.cc includes osdep.h, textconfig.h,
// and siminterface.h, so it doesn't know what bx_floppy or bx_cpu_c are.
// I'm sure some people will say is overly restrictive and/or annoying. When I
// set it up this way, we were still talking about making the CI in a seperate
// process, where direct method calls would be impossible. Also, we have been
// considering turning devices into plugin modules which are dynamically
// linked. Any direct references to something like bx_floppy.s.media[2].heads
// would have to be reworked before a plugin interface was possible as well.
//
// The siminterface is the glue between the CI and the simulator. There is
// just one global instance of the siminterface object, which can be referred
// to by the global variable bx_simulator_interface_c *SIM. The base class
// bx_simulator_interface_c, contains only virtual functions and it defines the
// interface that the CI is allowed to use. In siminterface.cc, a class
// called bx_real_sim_c is defined with bx_simulator_interface_c as its parent
// class. Bx_real_sim_c implements each of the functions. The separation into
// parent class and child class leaves the possibility of making a different
// child class that talks to the simulator in a different way (networking for
// example). If you were writing a user interface in a separate process, you
// could define a subclass of bx_simulator_interface_c called
// bx_siminterface_proxy_c which opens up a network port and turns all method
// calls into network sends and receives. Because the interface is defined
// entirely by the base class, the code that calls the methods would not know
// the difference.
//
// An important part of the siminterface implementation is the use of parameter
// classes, or bx_param_*. The parameter classes are described below, where
// they are declared. Search for "parameter classes" below for details.
//
// Also this header file declares data structures for certain events that pass
// between the siminterface and the CI. Search for "event structures" below.
//////////////////////////////////////////////////////
// BX_USE_TEXTCONFIG should be set to 1 when the text mode configuration interface
// is compiled in. This gives each type of parameter a text_print and text_ask
// method (defined in gui/textconfig.cc) so that you can call text_ask() on any
// kind of parameter to ask the user to edit the value.
//
// I have been considering whether to use the same strategy for the
// wxWidgets interface, but I'm not sure if I like it. One problem is
// that in order to declare member functions that are useful for
// wxWidgets, the wxWidgets header files would have to be included
// before the param object definitions. That means that all the
// wxWidgets headers would have be included when compiling every
// single bochs file. One of the things I like about the separation
// between the simulator and CI is that the two parts can be
// compiled without any knowledge of the other. Bochs doesn't include
// <wx.h>, and the wxWidgets CI (wxmain.cc) doesn't need to include <bochs.h>.
// Aside from making compiles faster, this enforces the use of the siminterface
// so it keeps the interface clean (important when we may have multiple UI
// implementations for example). This argues for keeping UI-specific
// structures out of the simulator interface. It certainly works ok for the
// text interface, but that's because FILE* is standard and portable.
//////////////////////////////////////////////////////
// base value for generated new parameter id
#define BXP_NEW_PARAM_ID 1001
typedef enum {
BX_TOOLBAR_UNDEFINED,
BX_TOOLBAR_FLOPPYA,
BX_TOOLBAR_FLOPPYB,
BX_TOOLBAR_CDROM1,
BX_TOOLBAR_RESET,
BX_TOOLBAR_POWER,
BX_TOOLBAR_SAVE_RESTORE,
BX_TOOLBAR_COPY,
BX_TOOLBAR_PASTE,
BX_TOOLBAR_SNAPSHOT,
BX_TOOLBAR_CONFIG,
BX_TOOLBAR_MOUSE_EN,
BX_TOOLBAR_USER
} bx_toolbar_buttons;
// normally all action choices are available for all event types. The exclude
// expression allows some choices to be eliminated if they don't make any
// sense. For example, it would be stupid to ignore a panic.
#define BX_LOG_OPTS_EXCLUDE(type, choice) ( \
/* can't die, ask or warn, on debug or info events */ \
(type <= LOGLEV_INFO && (choice >= ACT_WARN)) \
/* can't ignore panics */ \
|| (type == LOGLEV_PANIC && choice == ACT_IGNORE) \
)
// floppy / cdrom media status
enum { BX_EJECTED = 0, BX_INSERTED = 1 };
// boot devices (using the same values as the rombios)
enum {
BX_BOOT_NONE,
BX_BOOT_FLOPPYA,
BX_BOOT_DISKC,
BX_BOOT_CDROM,
BX_BOOT_NETWORK
};
///////////////////////////////////////////////////////////////////
// event structures for communication between simulator and CI
///////////////////////////////////////////////////////////////////
// Because the CI (configuration interface) might be in a different
// thread or even a different process, we pass events encoded in data
// structures to it instead of just calling functions. Each type of
// event is declared as a different structure, and then all those
// structures are squished into a union in BxEvent. (BTW, this is
// almost exactly how X windows event structs work.)
//
// These are simple structs, unblemished by C++ methods and tricks.
// No matter what event type it is, we allocate a BxEvent for each
// one, as opposed to trying to save a few bytes on small events by
// allocating only the bytes necessary for it. This makes it easy and
// fast to store events in a queue, like this
// BxEvent event_queue[MAX_EVENTS];
//
// Events come in two varieties: synchronous and asynchronous. We
// have to worry about sync and async events because the CI and the
// simulation may be running in different threads. An async event is
// the simplest. Whichever thread originates the event just builds
// the data structure, sends it, and then continues with its business.
// Async events can go in either direction. Synchronous events
// require the other thread to "respond" before the originating thread
// can continue. It's like a function with a return value; you can't
// continue until you get the return value back.
//
// Examples:
//
// async event: In the wxWidgets implementation, both the CI and the
// VGAW operate in the wxWidgets GUI thread. When the user presses a
// key, wxWidgets sends a wxKeyEvent to the VGAW event handler code in
// wx.cc. The VGAW handler then builds a BxEvent with
// type=BX_ASYNC_EVT_KEY, and fills in the bx_key and raw_scancode
// fields. The asynchronous event is placed on the event_queue for
// the simulator, then the VGAW handler returns. (With wxWidgets and
// many other graphical libaries, the event handler must return
// quickly because the window will not be updated until it's done.)
// Some time later, the simulator reaches the point where it checks
// for new events from the user (actually controlled by
// bx_devices_c::timer() in iodev/devices.cc) and calls
// bx_gui->handle_events(). Then all the events in the queue are
// processed by the simulator. There is no "response" sent back to
// the originating thread.
//
// sync event: Sometimes the simulator reaches a point where it needs
// to ask the user how to proceed. In this case, the simulator sends
// a synchronous event because it requires a response before it can
// continue. It builds an event structure, perhaps with type
// BX_SYNC_EVT_ASK_PARAM, sends it to the user interface
// using the event handler function defined by set_notify_callback(),
// and pauses the simulation. The user interface asks the user the
// question, and puts the answer into the BxEvent.retcode field. The
// event handler function returns the modified BxEvent with retcode
// filled in, and the simulation continues. The details of this
// transaction can be complicated if the simulation and CI are not
// in the same thread, but the behavior is as described.
//
///// types and definitions used in event structures
#define BX_EVT_IS_ASYNC(type) ((type) > __ALL_EVENTS_BELOW_ARE_ASYNC__)
typedef enum {
__ALL_EVENTS_BELOW_ARE_SYNCHRONOUS__ = 2000,
BX_SYNC_EVT_GET_PARAM, // CI -> simulator -> CI
BX_SYNC_EVT_ASK_PARAM, // simulator -> CI -> simulator
BX_SYNC_EVT_TICK, // simulator -> CI, wait for response.
BX_SYNC_EVT_LOG_DLG, // simulator -> CI, wait for response.
BX_SYNC_EVT_GET_DBG_COMMAND, // simulator -> CI, wait for response.
BX_SYNC_EVT_MSG_BOX, // simulator -> CI, wait for response.
__ALL_EVENTS_BELOW_ARE_ASYNC__,
BX_ASYNC_EVT_KEY, // vga window -> simulator
BX_ASYNC_EVT_MOUSE, // vga window -> simulator
BX_ASYNC_EVT_SET_PARAM, // CI -> simulator
BX_ASYNC_EVT_LOG_MSG, // simulator -> CI
BX_ASYNC_EVT_DBG_MSG, // simulator -> CI
BX_ASYNC_EVT_VALUE_CHANGED, // simulator -> CI
BX_ASYNC_EVT_TOOLBAR, // CI -> simulator
BX_ASYNC_EVT_STATUSBAR, // simulator -> CI
BX_ASYNC_EVT_REFRESH, // simulator -> CI
BX_ASYNC_EVT_QUIT_SIM // simulator -> CI
} BxEventType;
typedef union {
Bit32s s32;
char *charptr;
} AnyParamVal;
// Define substructures which make up the interior of BxEvent. The
// substructures, such as BxKeyEvent or BxMouseEvent, should never be
// allocated on their own. They are only intended to be used within
// the union in the BxEvent structure.
// Event type: BX_SYNC_EVT_TICK
//
// A tick event is synchronous, sent from the simulator to the GUI. The
// event doesn't do anything visible. Primarily it gives the GUI a chance
// to tell the simulator to quit, if necessary. There may be other uses
// for the tick in the future, such as giving some kind of regular
// status report or mentioning watched values that changed, but so far
// it's just for that one thing. There is no data associated with a
// tick event.
// Event type: BX_ASYNC_EVT_KEY
//
// A key event can be sent from the VGA window to the Bochs simulator.
// It is asynchronous.
typedef struct {
// what was pressed? This is a BX_KEY_* value. For key releases,
// BX_KEY_RELEASED is ORed with the base BX_KEY_*.
Bit32u bx_key;
bool raw_scancode;
} BxKeyEvent;
// Event type: BX_ASYNC_EVT_MOUSE
//
// A mouse event can be sent from the VGA window to the Bochs
// simulator. It is asynchronous.
typedef struct {
// type is BX_EVT_MOUSE
Bit16s dx, dy, dz; // mouse motion delta
Bit8u buttons; // which buttons are pressed.
// bit 0: 1=left button down, 0=up
// bit 1: 1=right button down, 0=up
// bit 2: 1=middle button down, 0=up
} BxMouseEvent;
// Event type: BX_SYNC_EVT_GET_PARAM, BX_ASYNC_EVT_SET_PARAM
//
// Parameter set/get events are initiated by the CI, since Bochs can
// always access the parameters directly. So far, I haven't used
// these event types. In the CI I just call
// SIM->get_param(parameter_id) to get a pointer to the bx_param_c
// object and then call the get/set methods. This is okay for
// configuration since bochs is not running. However it could be
// dangerous for the GUI thread to poke around in Bochs structures
// while the thread is running. For these cases, I may have to be
// more careful and actually build get/set events and place them on
// Bochs's event queue to be processed during SIM->periodic() or
// something.
typedef struct {
// type is BX_EVT_GET_PARAM, BX_EVT_SET_PARAM
class bx_param_c *param; // pointer to param structure
AnyParamVal val;
} BxParamEvent;
// Event type: BX_SYNC_EVT_ASK_PARAM
// Synchronous event sent from the simulator to the CI. This tells the
// CI to ask the user to choose the value of a parameter. The CI may
// need to discover the type of parameter so that it can use the right
// kind of graphical display. The BxParamEvent is used for these events
// too.
// FIXME: at the moment the GUI implements the ASK_PARAM event for just
// a few parameter types. I need to implement the event for all parameter
// types.
// Event type: BX_ASYNC_EVT_VALUE_CHANGED
//
// Asynchronous event sent from the simulator to the CI, telling it that
// some value that it (hopefully) cares about has changed. This isn't
// being used yet, but a good example is in a debugger interface, you might
// want to maintain a reasonably current display of the PC or some other
// simulation state. The CI would set some kind of event mask (which
// doesn't exist now of course) and then when certain values change, the
// simulator would send this event so that the CI can update. We may need
// some kind of "flow control" since the simulator will be able to produce
// new events much faster than the gui can accept them.
// Event type: BX_ASYNC_EVT_LOG_MSG
//
// Asynchronous event from the simulator to the CI. When a BX_PANIC,
// BX_ERROR, BX_INFO, or BX_DEBUG is found in the simulator code, this
// event type can be used to inform the CI of the condition. There is
// no point in sending messages to the CI that will not be displayed; these
// would only slow the simulation. So we will need some mechanism for
// choosing what kinds of events will be delivered to the CI. Normally,
// you wouldn't want to look at the log unless something is going wrong.
// At that point, you might want to open up a window to watch the debug
// messages from one or two devices only.
//
// Idea: Except for panics that require user attention to continue, it
// might be most efficient to just append log messages to a file.
// When the user wants to look at the log messages, the gui can reopen
// the file (read only), skip to the end, and look backward for a
// reasonable number of lines to display (200?). This allows it to
// skip over huge bursts of log entries without allocating memory,
// synchronizing threads, etc. for each.
typedef struct {
Bit8u level;
Bit8u mode;
const char *prefix;
const char *msg;
} BxLogMsgEvent;
// Event type: BX_ASYNC_EVT_DBG_MSG
//
// Also uses BxLogMsgEvent, but this is a message to be displayed in
// the debugger history window.
// Event type: BX_SYNC_EVT_LOG_DLG
//
// This is a synchronous version of BX_ASYNC_EVT_LOG_MSG, which is used
// when the "action=ask" setting is used. If the simulator runs into a
// panic, it sends a synchronous BX_SYNC_EVT_LOG_DLG to the CI to be
// displayed. The CI shows a dialog that asks if the user wants to
// continue, quit, etc. and sends the answer back to the simulator.
// This event also uses BxLogMsgEvent.
enum {
BX_LOG_ASK_CHOICE_CONTINUE,
BX_LOG_ASK_CHOICE_CONTINUE_ALWAYS,
BX_LOG_ASK_CHOICE_DIE,
BX_LOG_ASK_CHOICE_DUMP_CORE,
BX_LOG_ASK_CHOICE_ENTER_DEBUG,
BX_LOG_ASK_N_CHOICES,
BX_LOG_NOTIFY_FAILED
};
enum {
BX_LOG_DLG_ASK,
BX_LOG_DLG_WARN,
BX_LOG_DLG_QUIT
};
// Event type: BX_SYNC_EVT_GET_DBG_COMMAND
//
// This is a synchronous event sent from the simulator to the debugger
// requesting the next action. In a text mode debugger, this would prompt
// the user for the next command. When a new command is ready, the
// synchronous event is sent back with its fields filled in.
typedef struct {
char *command; // null terminated string. allocated by debugger interface
// with new operator, freed by simulator with delete.
} BxDebugCommand;
// Event type: BX_ASYNC_EVT_TOOLBAR
// Asynchronous event from the VGAW to the simulator, sent when the user
// clicks on a toolbar button. This may one day become something more
// general, like a command event, but at the moment it's only needed for
// the toolbar events.
typedef struct {
bx_toolbar_buttons button;
bool on; // for toggling buttons, on=true means the toolbar button is
// pressed. on=false means it is not pressed.
} BxToolbarEvent;
// Event type: BX_ASYNC_EVT_STATUSAR
typedef struct {
int element;
char *text;
bool active;
bool w;
} BxStatusbarEvent;
// The BxEvent structure should be used for all events. Every event has
// a type and a spot for a return code (only used for synchronous events).
typedef struct {
BxEventType type; // what kind is this?
Bit32s retcode; // success or failure. only used for synchronous events.
union {
BxKeyEvent key;
BxMouseEvent mouse;
BxParamEvent param;
BxLogMsgEvent logmsg;
BxToolbarEvent toolbar;
BxStatusbarEvent statbar;
BxDebugCommand debugcmd;
} u;
} BxEvent;
#include "paramtree.h"
// These are the different start modes.
enum {
// Just start the simulation without running the configuration interface
// at all, unless something goes wrong.
BX_QUICK_START = 200,
// Run the configuration interface. The default action will be to load a
// configuration file. This makes sense if a config file could not be
// loaded, either because it wasn't found or because it had errors.
BX_LOAD_START,
// Run the configuration interface. The default action will be to
// edit the configuration.
BX_EDIT_START,
// Run the configuration interface, but make the default action be to
// start the simulation.
BX_RUN_START
};
enum {
BX_DDC_MODE_DISABLED,
BX_DDC_MODE_BUILTIN,
BX_DDC_MODE_FILE
};
enum {
BX_MOUSE_TYPE_NONE,
BX_MOUSE_TYPE_PS2,
BX_MOUSE_TYPE_IMPS2,
#if BX_SUPPORT_BUSMOUSE
BX_MOUSE_TYPE_INPORT,
BX_MOUSE_TYPE_BUS,
#endif
BX_MOUSE_TYPE_SERIAL,
BX_MOUSE_TYPE_SERIAL_WHEEL,
BX_MOUSE_TYPE_SERIAL_MSYS
};
enum {
BX_MOUSE_TOGGLE_CTRL_MB,
BX_MOUSE_TOGGLE_CTRL_F10,
BX_MOUSE_TOGGLE_CTRL_ALT,
BX_MOUSE_TOGGLE_F12
};
#define BX_FDD_NONE 0 // floppy not present
#define BX_FDD_525DD 1 // 360K 5.25"
#define BX_FDD_525HD 2 // 1.2M 5.25"
#define BX_FDD_350DD 3 // 720K 3.5"
#define BX_FDD_350HD 4 // 1.44M 3.5"
#define BX_FDD_350ED 5 // 2.88M 3.5"
#define BX_FLOPPY_NONE 10 // media not present
#define BX_FLOPPY_1_2 11 // 1.2M 5.25"
#define BX_FLOPPY_1_44 12 // 1.44M 3.5"
#define BX_FLOPPY_2_88 13 // 2.88M 3.5"
#define BX_FLOPPY_720K 14 // 720K 3.5"
#define BX_FLOPPY_360K 15 // 360K 5.25"
#define BX_FLOPPY_160K 16 // 160K 5.25"
#define BX_FLOPPY_180K 17 // 180K 5.25"
#define BX_FLOPPY_320K 18 // 320K 5.25"
#define BX_FLOPPY_LAST 18 // last legal value of floppy type
#define BX_FLOPPY_AUTO 19 // autodetect image size
#define BX_FLOPPY_UNKNOWN 20 // image size doesn't match one of the types above
#define BX_ATA_DEVICE_NONE 0
#define BX_ATA_DEVICE_DISK 1
#define BX_ATA_DEVICE_CDROM 2
#define BX_ATA_BIOSDETECT_AUTO 0
#define BX_ATA_BIOSDETECT_CMOS 1
#define BX_ATA_BIOSDETECT_NONE 2
enum {
BX_SECT_SIZE_512,
BX_SECT_SIZE_1024,
BX_SECT_SIZE_4096
};
enum {
BX_ATA_TRANSLATION_NONE,
BX_ATA_TRANSLATION_LBA,
BX_ATA_TRANSLATION_LARGE,
BX_ATA_TRANSLATION_RECHS,
BX_ATA_TRANSLATION_AUTO
};
#define BX_ATA_TRANSLATION_LAST BX_ATA_TRANSLATION_AUTO
enum {
BX_CLOCK_SYNC_NONE,
BX_CLOCK_SYNC_REALTIME,
BX_CLOCK_SYNC_SLOWDOWN,
BX_CLOCK_SYNC_BOTH
};
#define BX_CLOCK_SYNC_LAST BX_CLOCK_SYNC_BOTH
enum {
BX_PCI_CHIPSET_I430FX,
BX_PCI_CHIPSET_I440FX,
BX_PCI_CHIPSET_I440BX
};
enum {
BX_CPUID_SUPPORT_NOSSE,
BX_CPUID_SUPPORT_SSE,
BX_CPUID_SUPPORT_SSE2,
BX_CPUID_SUPPORT_SSE3,
BX_CPUID_SUPPORT_SSSE3,
BX_CPUID_SUPPORT_SSE4_1,
BX_CPUID_SUPPORT_SSE4_2,
#if BX_SUPPORT_AVX
BX_CPUID_SUPPORT_AVX,
BX_CPUID_SUPPORT_AVX2,
#if BX_SUPPORT_EVEX
BX_CPUID_SUPPORT_AVX512
#endif
#endif
};
enum {
BX_CPUID_SUPPORT_LEGACY_APIC,
BX_CPUID_SUPPORT_XAPIC,
#if BX_CPU_LEVEL >= 6
BX_CPUID_SUPPORT_XAPIC_EXT,
BX_CPUID_SUPPORT_X2APIC
#endif
};
#define BX_CLOCK_TIME0_LOCAL 1
#define BX_CLOCK_TIME0_UTC 2
BOCHSAPI extern const char *floppy_devtype_names[];
BOCHSAPI extern const char *floppy_type_names[];
BOCHSAPI extern int floppy_type_n_sectors[];
BOCHSAPI extern const char *media_status_names[];
BOCHSAPI extern const char *bochs_bootdisk_names[];
////////////////////////////////////////////////////////////////////
// base class simulator interface, contains just virtual functions.
// I'm not longer sure that having a base class is going to be of any
// use... -Bryce
#include <setjmp.h>
enum ci_command_t { CI_START, CI_RUNTIME_CONFIG, CI_SHUTDOWN };
enum ci_return_t {
CI_OK, // normal return value
CI_ERR_NO_TEXT_CONSOLE // err: can't work because there's no text console
};
typedef int (*config_interface_callback_t)(void *userdata, ci_command_t command);
typedef BxEvent* (*bxevent_handler)(void *theclass, BxEvent *event);
typedef void (*rt_conf_handler_t)(void *this_ptr);
typedef Bit32s (*addon_option_parser_t)(const char *context, int num_params, char *params[]);
typedef Bit32s (*addon_option_save_t)(FILE *fp);
// bx_gui->set_display_mode() changes the mode between the configuration
// interface and the simulation. This is primarily intended for display
// libraries which have a full-screen mode such as SDL or term. The display
// mode is set to DISP_MODE_CONFIG before displaying any configuration
// menus, for panics that requires user input, when entering the debugger, etc.
// It is set to DISP_MODE_SIM when the Bochs simulation resumes. The constants
// are defined here so that configuration interfaces can use them with the
// bx_simulator_interface_c::set_display_mode() method.
enum disp_mode_t { DISP_MODE_CONFIG=100, DISP_MODE_SIM };
class BOCHSAPI bx_simulator_interface_c {
public:
bx_simulator_interface_c() {}
virtual ~bx_simulator_interface_c() {}
virtual void set_quit_context(jmp_buf *context) {}
virtual int get_init_done() { return 0; }
virtual int set_init_done(int n) {return 0;}
virtual void reset_all_param() {}
// new param methods
virtual bx_param_c *get_param(const char *pname, bx_param_c *base=NULL) {return NULL;}
virtual bx_param_num_c *get_param_num(const char *pname, bx_param_c *base=NULL) {return NULL;}
virtual bx_param_string_c *get_param_string(const char *pname, bx_param_c *base=NULL) {return NULL;}
virtual bx_param_bool_c *get_param_bool(const char *pname, bx_param_c *base=NULL) {return NULL;}
virtual bx_param_enum_c *get_param_enum(const char *pname, bx_param_c *base=NULL) {return NULL;}
virtual unsigned gen_param_id() {return 0;}
virtual int get_n_log_modules() {return -1;}
virtual const char *get_logfn_name(int mod) {return NULL;}
virtual int get_logfn_id(const char *name) {return -1;}
virtual const char *get_prefix(int mod) {return NULL;}
virtual int get_log_action(int mod, int level) {return -1;}
virtual void set_log_action(int mod, int level, int action) {}
virtual int get_default_log_action(int level) {return -1;}
virtual void set_default_log_action(int level, int action) {}
virtual const char *get_action_name(int action) {return NULL;}
virtual int is_action_name(const char *val) {return -1;}
virtual const char *get_log_level_name(int level) {return NULL;}
virtual int get_max_log_level() {return -1;}
// exiting is somewhat complicated! The preferred way to exit bochs is
// to call BX_EXIT(exitcode). That is defined to call
// SIM->quit_sim(exitcode). The quit_sim function first calls
// the cleanup functions in bochs so that it can destroy windows
// and free up memory, then sends a notify message to the CI
// telling it that bochs has stopped.
virtual void quit_sim(int code) {}
virtual int get_exit_code() { return 0; }
virtual int get_default_rc(char *path, int len) {return -1;}
virtual int read_rc(const char *path) {return -1;}
virtual int write_rc(const char *rc, int overwrite) {return -1;}
virtual int get_log_file(char *path, int len) {return -1;}
virtual int set_log_file(const char *path) {return -1;}
virtual int get_log_prefix(char *prefix, int len) {return -1;}
virtual int set_log_prefix(const char *prefix) {return -1;}
virtual int get_debugger_log_file(char *path, int len) {return -1;}
virtual int set_debugger_log_file(const char *path) {return -1;}
// The CI calls set_notify_callback to register its event handler function.
// This event handler function is called whenever the simulator needs to
// send an event to the CI. For example, if the simulator hits a panic and
// wants to ask the user how to proceed, it would call the CI event handler
// to ask the CI to display a dialog.
//
// NOTE: At present, the standard VGAW buttons (floppy, snapshot, power,
// etc.) are displayed and handled by gui.cc, not by the CI or siminterface.
// gui.cc uses its own callback functions to implement the behavior of
// the buttons. Some of these implementations call the siminterface.
virtual void set_notify_callback(bxevent_handler func, void *arg) {}
virtual void get_notify_callback(bxevent_handler *func, void **arg) {}
// send an event from the simulator to the CI.
virtual BxEvent* sim_to_ci_event(BxEvent *event) {return NULL;}
// called from simulator to display a gui dialog in particular situations.
// 1. When it hits serious errors, to ask if the user wants to continue or not.
// 2. When it hits errors, to warn the user before continuing simulation
// 3. When it hits critical errors, inform the user before terminating simulation.
virtual int log_dlg(const char *prefix, int level, const char *msg, int mode) {return -1;}
// called from simulator when writing a message to log file
virtual void log_msg(const char *prefix, int level, const char *msg) {}
// set this to 1 if the gui has a log viewer
virtual void set_log_viewer(bool val) {}
virtual bool has_log_viewer() const {return 0;}
// tell the CI to ask the user for the value of a parameter.
virtual int ask_param(bx_param_c *param) {return -1;}
virtual int ask_param(const char *pname) {return -1;}
// ask the user for a pathname
virtual int ask_filename(const char *filename, int maxlen, const char *prompt, const char *the_default, int flags) {return -1;}
// yes/no dialog
virtual int ask_yes_no(const char *title, const char *prompt, bool the_default) {return -1;}
// simple message box
virtual void message_box(const char *title, const char *message) {}
// called at a regular interval, currently by the bx_devices_c::timer()
virtual void periodic() {}
virtual int create_disk_image(const char *filename, int sectors, bool overwrite) {return -3;}
// Tell the configuration interface (CI) that some parameter values have
// changed. The CI will reread the parameters and change its display if it's
// appropriate. Maybe later: mention which params have changed to save time.
virtual void refresh_ci() {}
// forces a vga update. This was added so that a debugger can force
// a vga update when single stepping, without having to wait thousands
// of cycles for the normal vga refresh triggered by the vga timer handler..
virtual void refresh_vga() {}
// forces a call to bx_gui.handle_events. This was added so that a debugger
// can force the gui events to be handled, so that interactive things such
// as a toolbar click will be processed.
virtual void handle_events() {}
// return first hard disk in ATA interface
virtual bx_param_c *get_first_cdrom() {return NULL;}
// return first cdrom in ATA interface
virtual bx_param_c *get_first_hd() {return NULL;}
// return 1 if device is connected to a PCI slot
virtual bool is_pci_device(const char *name) {return 0;}
// return 1 if device is connected to the AGP slot
virtual bool is_agp_device(const char *name) {return 0;}
#if BX_DEBUGGER
// for debugger: same behavior as pressing control-C
virtual void debug_break() {}
virtual void debug_interpret_cmd(char *cmd) {}
virtual char *debug_get_next_command() {return NULL;}
virtual void debug_puts(const char *text) {}
#endif
virtual void register_configuration_interface(
const char* name,
config_interface_callback_t callback,
void *userdata) {}
virtual int configuration_interface(const char* name, ci_command_t command) {return -1; }
virtual int begin_simulation(int argc, char *argv[]) {return -1;}
virtual int register_runtime_config_handler(void *dev, rt_conf_handler_t handler) {return 0;}
virtual void unregister_runtime_config_handler(int id) {}
virtual void update_runtime_options() {}
typedef bool (*is_sim_thread_func_t)();
is_sim_thread_func_t is_sim_thread_func;
virtual void set_sim_thread_func(is_sim_thread_func_t func) {
is_sim_thread_func = func;
}
virtual bool is_sim_thread() {return 1;}
virtual bool is_wx_selected() const {return 0;}
virtual void set_debug_gui(bool val) {}
virtual bool has_debug_gui() const {return 0;}
// provide interface to bx_gui->set_display_mode() method for config
// interfaces to use.
virtual void set_display_mode(disp_mode_t newmode) {}
virtual bool test_for_text_console() {return 1;}
// add-on config option support
virtual bool register_addon_option(const char *keyword, addon_option_parser_t parser, addon_option_save_t save_func) {return 0;}
virtual bool unregister_addon_option(const char *keyword) {return 0;}
virtual bool is_addon_option(const char *keyword) {return 0;}
virtual Bit32s parse_addon_option(const char *context, int num_params, char *params []) {return -1;}
virtual Bit32s save_addon_options(FILE *fp) {return -1;}
// statistics
virtual void init_statistics() {}
virtual void cleanup_statistics() {}
virtual bx_list_c *get_statistics_root() {return NULL;}
// save/restore support
virtual void init_save_restore() {}
virtual void cleanup_save_restore() {}
virtual bool save_state(const char *checkpoint_path) {return 0;}
virtual bool restore_config() {return 0;}
virtual bool restore_logopts() {return 0;}
virtual bool restore_hardware() {return 0;}
virtual bx_list_c *get_bochs_root() {return NULL;}
virtual bool restore_bochs_param(bx_list_c *root, const char *sr_path, const char *restore_name) { return 0; }
// special config parameter and options functions for plugins
virtual bool opt_plugin_ctrl(const char *plugname, bool load) {return 0;}
virtual void init_std_nic_options(const char *name, bx_list_c *menu) {}
virtual void init_usb_options(const char *usb_name, const char *pname, int maxports) {}
virtual int parse_param_from_list(const char *context, const char *param, bx_list_c *base) {return 0;}
virtual int parse_nic_params(const char *context, const char *param, bx_list_c *base) {return 0;}
virtual int parse_usb_port_params(const char *context, bool devopt,
const char *param, int maxports, bx_list_c *base) {return 0;}
virtual int split_option_list(const char *msg, const char *rawopt, char **argv, int max_argv) {return 0;}
virtual int write_param_list(FILE *fp, bx_list_c *base, const char *optname, bool multiline) {return 0;}
virtual int write_usb_options(FILE *fp, int maxports, bx_list_c *base) {return 0;}
#if BX_USE_GUI_CONSOLE
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;
extern void bx_init_siminterface();
#if defined(__WXMSW__) || defined(WIN32)
// Just to provide HINSTANCE, etc. in files that have not included bochs.h.
// I don't like this at all, but I don't see a way around it.
#include <windows.h>
#endif
// define structure to hold data that is passed into our main function.
typedef struct BOCHSAPI {
// standard argc,argv
int argc;
char **argv;
#ifdef WIN32
char initial_dir[MAX_PATH];
#endif
#ifdef __WXMSW__
// these are only used when compiling with wxWidgets. This gives us a
// place to store the data that was passed to WinMain.
HINSTANCE hInstance;
HINSTANCE hPrevInstance;
LPSTR m_lpCmdLine;
int nCmdShow;
#endif
} bx_startup_flags_t;
BOCHSAPI extern bx_startup_flags_t bx_startup_flags;
BOCHSAPI extern bool bx_user_quit;
#endif