Rewrite of the optional plugin control feature.

- Now that we know about all available plugins at startup, the bx_list_c object
  "plugin_ctrl" contains a fixed number of bx_param_bool_c objects representing
  the requested status (1 = load). It is verified at simulation startup.
- The config interface creates two text lists (textconfig) or list boxes (win32,
  wx) from it to show the remaining available and the loaded plugins. Loading
  and unloading is performed immediately and plugins may install / uninstall
  options in other menus / dialogs.
- Modified the "non-plugin" code to make the optional plugin control work very
  similar in this mode.
This commit is contained in:
Volker Ruppert 2021-01-21 18:10:40 +00:00
parent 9e95491fb5
commit e5c68dd4ac
13 changed files with 234 additions and 127 deletions

View File

@ -250,6 +250,27 @@ void bx_init_usb_options(const char *usb_name, const char *pname, int maxports)
enabled->set_dependent_list(deplist);
}
void bx_plugin_ctrl_init()
{
bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_PLUGIN_CTRL);
#if !BX_PLUGINS
int i = 0;
while (strcmp(bx_builtin_plugins[i].name, "NULL")) {
if (bx_builtin_plugins[i].type == PLUGTYPE_OPTIONAL) {
new bx_param_bool_c(base, bx_builtin_plugins[i].name, "", "", 0);
}
i++;
}
#else
const char *name;
int count = bx_get_plugins_count(PLUGTYPE_OPTIONAL);
for (int i = 0; i < count; i++) {
name = bx_get_plugin_name(PLUGTYPE_OPTIONAL, i);
new bx_param_bool_c(base, name, "", "", 0);
}
#endif
}
void bx_plugin_ctrl_reset(bx_bool init_done)
{
bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_PLUGIN_CTRL);
@ -259,18 +280,18 @@ void bx_plugin_ctrl_reset(bx_bool init_done)
}
SIM->opt_plugin_ctrl("*", 0);
}
// add the default set of plugins to the list
new bx_param_bool_c(base, "unmapped", "", "", 1);
new bx_param_bool_c(base, "biosdev", "", "", 1);
new bx_param_bool_c(base, "speaker", "", "", 1);
new bx_param_bool_c(base, "extfpuirq", "", "", 1);
new bx_param_bool_c(base, "parallel", "", "", 1);
new bx_param_bool_c(base, "serial", "", "", 1);
// enable the default set of plugins to be loaded
SIM->get_param_bool("unmapped", base)->set(1);
SIM->get_param_bool("biosdev", base)->set(1);
SIM->get_param_bool("speaker", base)->set(1);
SIM->get_param_bool("extfpuirq", base)->set(1);
SIM->get_param_bool("parallel", base)->set(1);
SIM->get_param_bool("serial", base)->set(1);
#if BX_SUPPORT_GAMEPORT
new bx_param_bool_c(base, "gameport", "", "", 1);
SIM->get_param_bool("gameport", base)->set(1);
#endif
#if BX_SUPPORT_IODEBUG && BX_DEBUGGER
new bx_param_bool_c(base, "iodebug", "", "", 1);
SIM->get_param_bool("iodebug", base)->set(1);
#endif
SIM->opt_plugin_ctrl("*", 1);
}
@ -364,6 +385,7 @@ void bx_init_options()
// optional plugin control
new bx_list_c(menu, "plugin_ctrl", "Optional Plugin Control");
bx_plugin_ctrl_init();
// subtree for special menus
bx_list_c *special_menus = new bx_list_c(root_param, "menu", "");

View File

@ -46,21 +46,25 @@ typedef void (CDECL *plugin_fini_t)(void);
typedef struct _plugin_t
{
plugintype_t type;
bx_bool loaded;
bx_bool initialized;
#if BX_PLUGINS
char *name;
#if defined(WIN32)
HINSTANCE handle;
#else
lt_dlhandle handle;
#endif
#else
const char *name;
#endif
char *name;
plugintype_t type;
plugin_init_t plugin_init;
plugin_fini_t plugin_fini;
bool initialized;
#if BX_PLUGINS
bool loaded;
struct _plugin_t *next;
#endif
} plugin_t;

View File

@ -1452,31 +1452,33 @@ bool bx_real_sim_c::opt_plugin_ctrl(const char *plugname, bx_bool load)
bx_param_bool_c *plugin = (bx_param_bool_c*)plugin_ctrl->get(i);
if (load == (bx_bool)plugin->get()) {
opt_plugin_ctrl(plugin->get_name(), load);
if (load) i++;
} else {
}
i++;
}
}
return 1;
}
if (plugin_ctrl->get_by_name(plugname) == NULL) {
BX_PANIC(("Plugin '%s' not found", plugname));
return 0;
}
if (load != PLUG_device_present(plugname)) {
if (load) {
if (PLUG_load_opt_plugin(plugname)) {
if (plugin_ctrl->get_by_name(plugname) == NULL) {
new bx_param_bool_c(plugin_ctrl, plugname, "", "", 1);
}
SIM->get_param_bool(plugname, plugin_ctrl)->set(1);
return 1;
} else {
// plugin load code panics in this case
return 0;
}
} else {
PLUG_unload_opt_plugin(plugname);
plugin_ctrl->remove(plugname);
if (PLUG_unload_opt_plugin(plugname)) {
SIM->get_param_bool(plugname, plugin_ctrl)->set(0);
return 1;
} else {
// plugin load code panics in this case
return 0;
}
}
} else if (!load && !PLUG_device_present(plugname)) {
plugin_ctrl->remove(plugname);
}
return 0;
}

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002-2020 The Bochs Project
// Copyright (C) 2002-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
@ -665,7 +665,8 @@ void bx_plugin_ctrl()
{
Bit32u choice;
bx_list_c *plugin_ctrl;
int count;
bx_param_bool_c *plugin;
int i, count;
char plugname[512];
while (1) {
@ -679,24 +680,38 @@ void bx_plugin_ctrl()
bx_printf("\nNo optional plugins loaded\n");
} else {
bx_printf("\nCurrently loaded plugins:");
for (int i = 0; i < count; i++) {
for (i = 0; i < count; i++) {
plugin = (bx_param_bool_c*)plugin_ctrl->get(i);
if (plugin->get()) {
if (i > 0) bx_printf(",");
bx_printf(" %s", plugin_ctrl->get(i)->get_name());
bx_printf(" %s", plugin->get_name());
}
}
bx_printf("\n");
if (choice == 1) {
bx_printf("\nAdditionally available plugins:");
for (i = 0; i < count; i++) {
plugin = (bx_param_bool_c*)plugin_ctrl->get(i);
if (!plugin->get()) {
if (i > 0) bx_printf(",");
bx_printf(" %s", plugin->get_name());
}
}
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)) {
bx_printf("\nPlugin already loaded.\n");
if (SIM->opt_plugin_ctrl(plugname, 1)) {
bx_printf("\nLoaded plugin '%s'.\n", plugname);
}
}
} 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)) {
bx_printf("\nNo plugin unloaded.\n");
if (SIM->opt_plugin_ctrl(plugname, 0)) {
bx_printf("\nUnloaded plugin '%s'.\n", plugname);
}
}
}

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2003-2020 The Bochs Project
// Copyright (C) 2003-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
@ -358,6 +358,7 @@ static BOOL CALLBACK PluginCtrlDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARA
int count, i;
long code;
bx_list_c *plugin_ctrl;
bx_param_bool_c *plugin;
char plugname[20], message[80];
switch (msg) {
@ -365,7 +366,12 @@ static BOOL CALLBACK PluginCtrlDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARA
plugin_ctrl = (bx_list_c*) SIM->get_param(BXPN_PLUGIN_CTRL);
count = plugin_ctrl->get_size();
for (i = 0; i < count; i++) {
SendMessage(GetDlgItem(hDlg, IDPLUGLIST), LB_ADDSTRING, 0, (LPARAM)plugin_ctrl->get(i)->get_name());
plugin = (bx_param_bool_c*)plugin_ctrl->get(i);
if (plugin->get()) {
SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_ADDSTRING, 0, (LPARAM)plugin->get_name());
} else {
SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_ADDSTRING, 0, (LPARAM)plugin->get_name());
}
}
EnableWindow(GetDlgItem(hDlg, IDLOAD), FALSE);
EnableWindow(GetDlgItem(hDlg, IDUNLOAD), FALSE);
@ -376,32 +382,39 @@ static BOOL CALLBACK PluginCtrlDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARA
case WM_COMMAND:
code = HIWORD(wParam);
switch (LOWORD(wParam)) {
case IDPLUGLIST:
case IDPLUGLIST1:
if (code == LBN_SELCHANGE) {
SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_SETCURSEL, -1, 0);
EnableWindow(GetDlgItem(hDlg, IDLOAD), TRUE);
EnableWindow(GetDlgItem(hDlg, IDUNLOAD), FALSE);
}
break;
case IDPLUGLIST2:
if (code == LBN_SELCHANGE) {
SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_SETCURSEL, -1, 0);
EnableWindow(GetDlgItem(hDlg, IDLOAD), FALSE);
EnableWindow(GetDlgItem(hDlg, IDUNLOAD), TRUE);
}
break;
case IDEDIT:
if (code == EN_CHANGE) {
i = GetWindowTextLength(GetDlgItem(hDlg, IDEDIT));
EnableWindow(GetDlgItem(hDlg, IDLOAD), i > 0);
}
break;
case IDLOAD:
GetDlgItemText(hDlg, IDEDIT, plugname, 18);
i = SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_GETCURSEL, 0, 0);
SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_GETTEXT, i, (LPARAM)plugname);
if (SIM->opt_plugin_ctrl(plugname, 1)) {
wsprintf(message, "Plugin '%s' loaded", plugname);
MessageBox(hDlg, message, "Plugin Control", MB_ICONINFORMATION);
SendMessage(GetDlgItem(hDlg, IDPLUGLIST), LB_ADDSTRING, 0, (LPARAM)plugname);
SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_DELETESTRING, i, 0);
SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_ADDSTRING, 0, (LPARAM)plugname);
EnableWindow(GetDlgItem(hDlg, IDLOAD), FALSE);
}
break;
case IDUNLOAD:
i = SendMessage(GetDlgItem(hDlg, IDPLUGLIST), LB_GETCURSEL, 0, 0);
SendMessage(GetDlgItem(hDlg, IDPLUGLIST), LB_GETTEXT, i, (LPARAM)plugname);
i = SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_GETCURSEL, 0, 0);
SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_GETTEXT, i, (LPARAM)plugname);
if (SIM->opt_plugin_ctrl(plugname, 0)) {
wsprintf(message, "Plugin '%s' unloaded", plugname);
MessageBox(hDlg, message, "Plugin Control", MB_ICONINFORMATION);
SendMessage(GetDlgItem(hDlg, IDPLUGLIST), LB_DELETESTRING, i, 0);
SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_ADDSTRING, 0, (LPARAM)plugname);
SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_DELETESTRING, i, 0);
EnableWindow(GetDlgItem(hDlg, IDUNLOAD), FALSE);
}
break;

View File

@ -27,8 +27,10 @@
#define IDADVLOGOPT 1240
#define IDAPPLY 1250
#define PLUGIN_CTRL_DLG 1300
#define IDPLUGLIST 1310
#define IDEDIT 1320
#define IDPLUGTXT1 1305
#define IDPLUGLIST1 1310
#define IDPLUGTXT2 1315
#define IDPLUGLIST2 1320
#define IDLOAD 1330
#define IDUNLOAD 1340
#define ASK_DLG 2000

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002-2020 The Bochs Project
// Copyright (C) 2002-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
@ -450,23 +450,30 @@ PluginControlDialog::PluginControlDialog(
SetTitle(wxT("Optional Plugin Control"));
vertSizer = new wxBoxSizer(wxVERTICAL);
horzSizer = new wxBoxSizer(wxHORIZONTAL);
listSizer = new wxBoxSizer(wxVERTICAL);
editSizer = new wxBoxSizer(wxVERTICAL);
leftSizer = new wxBoxSizer(wxVERTICAL);
centerSizer = new wxBoxSizer(wxVERTICAL);
rightSizer = new wxBoxSizer(wxVERTICAL);
buttonSizer = new wxBoxSizer(wxHORIZONTAL);
horzSizer->Add(listSizer, 0, wxALIGN_LEFT);
horzSizer->Add(editSizer, 0, wxALIGN_RIGHT);
vertSizer->Add(horzSizer, 0, wxALIGN_LEFT);
horzSizer->Add(leftSizer, 0, wxALIGN_LEFT);
horzSizer->Add(centerSizer, 0, wxALIGN_CENTER);
horzSizer->Add(rightSizer, 0, wxALIGN_RIGHT);
vertSizer->Add(horzSizer, 0, wxALIGN_CENTER);
vertSizer->Add(buttonSizer, 0, wxALIGN_CENTER);
// listSizer contents
pluglist = new wxListBox(this, ID_PluginList);
listSizer->Add(pluglist, 0, wxALL, 10);
// editSizer contents
plugname = new wxTextCtrl(this, ID_PluginName, wxT(""), wxDefaultPosition, wxSize(120, -1));
editSizer->Add(plugname, 0, wxALL, 10);
btn_load = new wxButton(this, ID_Load, wxT("Load"));
editSizer->Add(btn_load, 0, wxALL | wxALIGN_RIGHT, 5);
btn_unload = new wxButton(this, ID_Unload, wxT("Unload"));
editSizer->Add(btn_unload, 0, wxALL | wxALIGN_RIGHT, 5);
// leftSizer contents
plugtxt1 = new wxStaticText(this, -1, wxT("Available"));
pluglist1 = new wxListBox(this, ID_PluginList1, wxDefaultPosition, wxSize(120, 200));
leftSizer->Add(plugtxt1, 0, wxALL | wxALIGN_CENTER, 10);
leftSizer->Add(pluglist1, 0, wxALL, 10);
// rightSizer contents
plugtxt2 = new wxStaticText(this, -1, wxT("Loaded"));
pluglist2 = new wxListBox(this, ID_PluginList2, wxDefaultPosition, wxSize(120, 200));
rightSizer->Add(plugtxt2, 0, wxALL | wxALIGN_CENTER, 10);
rightSizer->Add(pluglist2, 0, wxALL, 10);
// centerSizer contents
btn_load = new wxButton(this, ID_Load, wxT(">> Load >>"));
centerSizer->Add(btn_load, 0, wxALL | wxALIGN_RIGHT, 5);
btn_unload = new wxButton(this, ID_Unload, wxT("<< Unload <<"));
centerSizer->Add(btn_unload, 0, wxALL | wxALIGN_RIGHT, 5);
// buttonSizer contents
wxButton *btn = new wxButton(this, wxID_HELP, BTNLABEL_HELP);
buttonSizer->Add(btn, 0, wxALL, 5);
@ -475,9 +482,14 @@ PluginControlDialog::PluginControlDialog(
// make sure all plugins are loaded and add them to the listbox
SIM->opt_plugin_ctrl("*", 1);
bx_list_c *plugin_ctrl = (bx_list_c*) SIM->get_param(BXPN_PLUGIN_CTRL);
int a = 0, b = 0;
for (int i = 0; i < plugin_ctrl->get_size(); i++) {
bx_param_bool_c *plugin = (bx_param_bool_c*)plugin_ctrl->get(i);
pluglist->Insert(wxString(plugin->get_name(), wxConvUTF8), i);
if (plugin->get()) {
pluglist2->Insert(wxString(plugin->get_name(), wxConvUTF8), a++);
} else {
pluglist1->Insert(wxString(plugin->get_name(), wxConvUTF8), b++);
}
}
btn_load->Enable(0);
btn_unload->Enable(0);
@ -496,41 +508,52 @@ void PluginControlDialog::Init()
void PluginControlDialog::OnEvent(wxCommandEvent& event)
{
char buf[1024];
int i;
int id = event.GetId();
switch (id) {
case ID_PluginList:
case ID_PluginList1:
if (event.GetEventType() == wxEVT_COMMAND_LISTBOX_SELECTED) {
btn_unload->Enable(1);
pluglist2->SetSelection(-1);
btn_load->Enable(1);
btn_unload->Enable(0);
}
break;
case ID_PluginName:
if (event.GetEventType() == wxEVT_COMMAND_TEXT_UPDATED) {
btn_load->Enable(!plugname->IsEmpty());
case ID_PluginList2:
if (event.GetEventType() == wxEVT_COMMAND_LISTBOX_SELECTED) {
pluglist1->SetSelection(-1);
btn_load->Enable(0);
btn_unload->Enable(1);
}
break;
case ID_Load:
{
wxString tmpname(plugname->GetValue());
i = pluglist1->GetSelection();
wxString tmpname = pluglist1->GetString(i);
strncpy(buf, tmpname.mb_str(wxConvUTF8), sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
if (SIM->opt_plugin_ctrl(buf, 1)) {
tmpname.Printf(wxT("Plugin '%s' loaded"), buf);
wxMessageBox(tmpname, wxT("Plugin Control"), wxOK | wxICON_INFORMATION, this);
pluglist->Insert(wxString(buf, wxConvUTF8), pluglist->GetCount());
pluglist1->Delete(i);
pluglist2->Insert(wxString(buf, wxConvUTF8), pluglist2->GetCount());
pluglist1->SetSelection(-1);
btn_load->Enable(0);
}
}
break;
case ID_Unload:
{
int i = pluglist->GetSelection();
wxString tmpname = pluglist->GetString(i);
i = pluglist2->GetSelection();
wxString tmpname = pluglist2->GetString(i);
strncpy(buf, tmpname.mb_str(wxConvUTF8), sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
if (SIM->opt_plugin_ctrl(buf, 0)) {
tmpname.Printf(wxT("Plugin '%s' unloaded"), buf);
wxMessageBox(tmpname, wxT("Plugin Control"), wxOK | wxICON_INFORMATION, this);
pluglist->Delete(i);
pluglist1->Insert(wxString(buf, wxConvUTF8), pluglist1->GetCount());
pluglist2->Delete(i);
pluglist2->SetSelection(-1);
btn_unload->Enable(0);
}
}

View File

@ -2,7 +2,7 @@
// $Id$
////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002-2016 The Bochs Project
// Copyright (C) 2002-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
@ -187,9 +187,10 @@ class PluginControlDialog: public wxDialog
private:
void Init(); // called automatically by ShowModal()
void ShowHelp();
wxBoxSizer *vertSizer, *horzSizer, *listSizer, *editSizer, *buttonSizer;
wxTextCtrl *plugname;
wxListBox *pluglist;
wxBoxSizer *vertSizer, *horzSizer, *buttonSizer;
wxBoxSizer *leftSizer, *centerSizer, *rightSizer;
wxStaticText *plugtxt1, *plugtxt2;
wxListBox *pluglist1, *pluglist2;
wxButton *btn_load, *btn_unload;
public:
PluginControlDialog(wxWindow* parent, wxWindowID id);

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002-2020 The Bochs Project
// Copyright (C) 2002-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
@ -108,8 +108,8 @@ enum
// advanced log options
ID_ApplyDefault,
// dialog box: PluginControlDialog
ID_PluginList,
ID_PluginName,
ID_PluginList1,
ID_PluginList2,
ID_Load,
ID_Unload,
// that's all

View File

@ -225,7 +225,7 @@ void bx_devices_c::init(BX_MEM_C *newmem)
(chipset == BX_PCI_CHIPSET_I440BX)) {
// UHCI is a part of the PIIX3/PIIX4, so load / enable it
if (!PLUG_device_present("usb_uhci")) {
PLUG_load_plugin(usb_uhci, PLUGTYPE_OPTIONAL);
SIM->opt_plugin_ctrl("usb_uhci", 1);
}
SIM->get_param_bool(BXPN_UHCI_ENABLED)->set(1);
}
@ -265,7 +265,7 @@ void bx_devices_c::init(BX_MEM_C *newmem)
#if BX_SUPPORT_BUSMOUSE
if ((mouse_type == BX_MOUSE_TYPE_INPORT) ||
(mouse_type == BX_MOUSE_TYPE_BUS)) {
PLUG_load_plugin(busmouse, PLUGTYPE_OPTIONAL);
SIM->opt_plugin_ctrl("busmouse", 1);
}
#endif
if (is_harddrv_enabled()) {

View File

@ -368,6 +368,25 @@ void plugins_search(void)
delete [] pgn_path;
}
bool plugin_is_optional_device(plugin_t *plugin)
{
const char *core_plugins[] = {"cmos", "dma", "floppy", "pci", "pci2isa",
"pic", "pit", "svga_cirrus", "vga", NULL};
const char *std_plugins[] = {"acpi", "harddrv", "hpet", "ioapic", "keyboard",
"pci_ide", NULL};
int i = 0;
while (core_plugins[i] != NULL) {
if (!strcmp(plugin->name, core_plugins[i])) return 0;
i++;
}
i = 0;
while (std_plugins[i] != NULL) {
if (!strcmp(plugin->name, std_plugins[i])) return 0;
i++;
}
return 1;
}
Bit8u bx_get_plugins_count(plugintype_t type)
{
plugin_t *temp;
@ -377,7 +396,9 @@ Bit8u bx_get_plugins_count(plugintype_t type)
temp = plugins;
while (temp != NULL) {
if (type == temp->type)
if ((type == temp->type) ||
((type == PLUGTYPE_OPTIONAL) && (temp->type == PLUGTYPE_DEV) &&
plugin_is_optional_device(temp)))
count++;
temp = temp->next;
}
@ -394,7 +415,9 @@ const char* bx_get_plugin_name(plugintype_t type, Bit8u index)
temp = plugins;
while (temp != NULL) {
if (type == temp->type) {
if ((type == temp->type) ||
((type == PLUGTYPE_OPTIONAL) && (temp->type == PLUGTYPE_DEV) &&
plugin_is_optional_device(temp))) {
if (count == index)
return temp->name;
count++;
@ -423,7 +446,7 @@ bool plugin_init_one(plugin_t *plugin)
}
void plugin_unload(plugin_t *plugin)
bool plugin_unload(plugin_t *plugin)
{
if (plugin->loaded) {
if (plugin->initialized)
@ -437,6 +460,9 @@ void plugin_unload(plugin_t *plugin)
plugin->type = PLUGTYPE_DEV;
}
plugin->loaded = 0;
return 1;
} else {
return 0;
}
}
@ -770,19 +796,22 @@ bool bx_load_plugin(const char *name, plugintype_t type)
}
}
void bx_unload_plugin(const char *name, bx_bool devflag)
bool bx_unload_plugin(const char *name, bx_bool devflag)
{
plugin_t *plugin;
bool ret = 0;
for (plugin = plugins; plugin; plugin = plugin->next) {
if (!strcmp(plugin->name, name)) {
BX_INFO(("bx_unload_plugin(): name = %s", plugin->name));
if (devflag) {
pluginUnregisterDeviceDevmodel(plugin->name);
}
plugin_unload(plugin);
ret = plugin_unload(plugin);
break;
}
}
return ret;
}
void bx_unload_plugin_type(const char *name, plugintype_t type)
@ -968,14 +997,6 @@ void bx_plugins_after_restore_state()
// Special code for loading gui, optional and sound plugins when plugin support
// is turned off.
typedef struct {
const char* name;
plugintype_t type;
plugin_init_t plugin_init;
plugin_fini_t plugin_fini;
bx_bool status;
} builtin_plugin_t;
#define BUILTIN_GUI_PLUGIN_ENTRY(mod) {#mod, PLUGTYPE_GUI, lib##mod##_gui_plugin_init, lib##mod##_gui_plugin_fini, 0}
#define BUILTIN_OPT_PLUGIN_ENTRY(mod) {#mod, PLUGTYPE_OPTIONAL, lib##mod##_LTX_plugin_init, lib##mod##_LTX_plugin_fini, 0}
#define BUILTIN_SND_PLUGIN_ENTRY(mod) {#mod, PLUGTYPE_SND, lib##mod##_sound_plugin_init, lib##mod##_sound_plugin_fini, 0}
@ -984,7 +1005,7 @@ typedef struct {
#define BUILTIN_VGA_PLUGIN_ENTRY(mod) {#mod, PLUGTYPE_VGA, lib##mod##_LTX_plugin_init, lib##mod##_LTX_plugin_fini, 0}
#define BUILTIN_IMG_PLUGIN_ENTRY(mod) {#mod, PLUGTYPE_IMG, lib##mod##_img_plugin_init, lib##mod##_img_plugin_fini, 0}
static builtin_plugin_t builtin_plugins[] = {
plugin_t bx_builtin_plugins[] = {
#if BX_WITH_AMIGAOS
BUILTIN_GUI_PLUGIN_ENTRY(amigaos),
#endif
@ -1132,40 +1153,40 @@ static builtin_plugin_t builtin_plugins[] = {
{"NULL", PLUGTYPE_GUI, NULL, NULL, 0}
};
int bx_load_plugin2(const char *name, plugintype_t type)
int bx_load_plugin_np(const char *name, plugintype_t type)
{
int i = 0;
while (strcmp(builtin_plugins[i].name, "NULL")) {
if ((!strcmp(name, builtin_plugins[i].name)) &&
(type == builtin_plugins[i].type)) {
if (builtin_plugins[i].status == 0) {
builtin_plugins[i].plugin_init(NULL, type);
builtin_plugins[i].status = 1;
while (strcmp(bx_builtin_plugins[i].name, "NULL")) {
if ((!strcmp(name, bx_builtin_plugins[i].name)) &&
(type == bx_builtin_plugins[i].type)) {
if (bx_builtin_plugins[i].initialized == 0) {
bx_builtin_plugins[i].plugin_init(NULL, type);
bx_builtin_plugins[i].initialized = 1;
}
return 1;
}
i++;
};
}
return 0;
}
int bx_unload_opt_plugin(const char *name, bx_bool devflag)
{
int i = 0;
while (strcmp(builtin_plugins[i].name, "NULL")) {
if ((!strcmp(name, builtin_plugins[i].name)) &&
(builtin_plugins[i].type == PLUGTYPE_OPTIONAL)) {
if (builtin_plugins[i].status == 1) {
while (strcmp(bx_builtin_plugins[i].name, "NULL")) {
if ((!strcmp(name, bx_builtin_plugins[i].name)) &&
(bx_builtin_plugins[i].type == PLUGTYPE_OPTIONAL)) {
if (bx_builtin_plugins[i].initialized == 1) {
if (devflag) {
pluginUnregisterDeviceDevmodel(builtin_plugins[i].name);
pluginUnregisterDeviceDevmodel(bx_builtin_plugins[i].name);
}
builtin_plugins[i].plugin_fini();
builtin_plugins[i].status = 0;
bx_builtin_plugins[i].plugin_fini();
bx_builtin_plugins[i].initialized = 0;
}
return 1;
}
i++;
};
}
return 0;
}

View File

@ -114,11 +114,11 @@ extern "C" {
// When plugins are off, PLUG_load_plugin will call the plugin_init function
// directly.
#define PLUG_load_plugin(name,type) {lib##name##_LTX_plugin_init(NULL,type);}
#define PLUG_load_gui_plugin(name) bx_load_plugin2(name,PLUGTYPE_GUI)
#define PLUG_load_opt_plugin(name) bx_load_plugin2(name,PLUGTYPE_OPTIONAL)
#define PLUG_load_vga_plugin(name) bx_load_plugin2(name,PLUGTYPE_VGA)
#define PLUG_load_gui_plugin(name) bx_load_plugin_np(name,PLUGTYPE_GUI)
#define PLUG_load_opt_plugin(name) bx_load_plugin_np(name,PLUGTYPE_OPTIONAL)
#define PLUG_load_vga_plugin(name) bx_load_plugin_np(name,PLUGTYPE_VGA)
#define PLUG_unload_plugin(name) {lib##name##_LTX_plugin_fini();}
#define PLUG_unload_opt_plugin(name) bx_unload_opt_plugin(name,1);
#define PLUG_unload_opt_plugin(name) bx_unload_opt_plugin(name,1)
#define DEV_register_ioread_handler(b,c,d,e,f) bx_devices.register_io_read_handler(b,c,d,e,f)
#define DEV_register_iowrite_handler(b,c,d,e,f) bx_devices.register_io_write_handler(b,c,d,e,f)
@ -339,7 +339,7 @@ Bit8u bx_get_plugins_count(plugintype_t type);
const char* bx_get_plugin_name(plugintype_t type, Bit8u index);
#endif
bool bx_load_plugin(const char *name, plugintype_t type);
extern void bx_unload_plugin(const char *name, bx_bool devflag);
bool bx_unload_plugin(const char *name, bx_bool devflag);
extern void bx_unload_plugin_type(const char *name, plugintype_t type);
extern void bx_init_plugins(void);
extern void bx_reset_plugins(unsigned);
@ -349,7 +349,9 @@ extern void bx_plugins_register_state(void);
extern void bx_plugins_after_restore_state(void);
#if !BX_PLUGINS
int bx_load_plugin2(const char *name, plugintype_t type);
extern plugin_t bx_builtin_plugins[];
int bx_load_plugin_np(const char *name, plugintype_t type);
int bx_unload_opt_plugin(const char *name, bx_bool devflag);
#endif

View File

@ -76,16 +76,18 @@ BEGIN
PUSHBUTTON "Apply", IDAPPLY, 155, 155, 50, 14
END
PLUGIN_CTRL_DLG DIALOG 100, 120, 180, 135
PLUGIN_CTRL_DLG DIALOG 100, 120, 280, 140
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Optional Plugin Control"
FONT 8, "Helv"
BEGIN
LISTBOX IDPLUGLIST, 15, 15, 85, 100, WS_VSCROLL | WS_TABSTOP
EDITTEXT IDEDIT, 110, 15, 60, 14
PUSHBUTTON "Load", IDLOAD, 110, 35, 50, 14
PUSHBUTTON "Unload", IDUNLOAD, 110, 55, 50, 14
DEFPUSHBUTTON "OK", IDOK, 65, 115, 50, 14
LTEXT "Available", IDPLUGTXT1, 40, 10, 55, 14
LISTBOX IDPLUGLIST1, 15, 20, 85, 100, WS_VSCROLL | WS_TABSTOP
LTEXT "Loaded", IDPLUGTXT2, 200, 10, 55, 14
LISTBOX IDPLUGLIST2, 175, 20, 85, 100, WS_VSCROLL | WS_TABSTOP
PUSHBUTTON ">> Load >>", IDLOAD, 110, 40, 50, 14
PUSHBUTTON "<< Unload <<", IDUNLOAD, 110, 60, 50, 14
DEFPUSHBUTTON "OK", IDOK, 115, 120, 50, 14
END
PARAM_DLG DIALOG 30, 30, 200, 65