2001-10-03 17:10:38 +04:00
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
2002-04-08 04:11:52 +04:00
|
|
|
|
// $Id: control.cc,v 1.46 2002-04-08 00:11:52 bdenney Exp $
|
2001-10-03 17:10:38 +04:00
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
2001-06-08 11:20:07 +04:00
|
|
|
|
/*
|
|
|
|
|
* gui/control.cc
|
2002-04-08 04:11:52 +04:00
|
|
|
|
* $Id: control.cc,v 1.46 2002-04-08 00:11:52 bdenney Exp $
|
2001-06-08 11:20:07 +04:00
|
|
|
|
*
|
|
|
|
|
* This is code for a text-mode control panel. Note that this file
|
|
|
|
|
* does NOT include bochs.h. Instead, it does all of its contact with
|
|
|
|
|
* the simulator through an object called SIM, defined in siminterface.cc
|
|
|
|
|
* and siminterface.h. This separation adds an extra layer of method
|
|
|
|
|
* calls before any work can be done, but the benefit is that the compiler
|
|
|
|
|
* enforces the rules. I can guarantee that control.cc doesn't call any
|
|
|
|
|
* I/O device objects directly, for example, because the bx_devices symbol
|
|
|
|
|
* isn't even defined in this context.
|
|
|
|
|
*
|
2001-06-08 00:42:00 +04:00
|
|
|
|
|
2001-06-08 11:20:07 +04:00
|
|
|
|
Musings by Bryce:
|
2001-06-08 00:42:00 +04:00
|
|
|
|
|
2001-06-08 11:20:07 +04:00
|
|
|
|
Now that there are some capabilities here, start moving toward the desired
|
|
|
|
|
model of separation of gui and simulator. Design a method-call interface
|
|
|
|
|
between objects which could later be turned into a network protocol.
|
2001-06-08 00:42:00 +04:00
|
|
|
|
|
2001-06-08 11:20:07 +04:00
|
|
|
|
Most messages go from the control panel to bochs, with bochs sending a response
|
|
|
|
|
back. Examples: turn on debug event logging for the PIC, or set IPS to
|
|
|
|
|
1.5million. Others kinds of messages go from bochs to the control panel.
|
|
|
|
|
Example: errors such as "disk image not found", status information such as the
|
|
|
|
|
current CPU state.
|
|
|
|
|
|
|
|
|
|
But because of the nature of a control panel, most information flows from
|
|
|
|
|
the control panel to Bochs. I think we can take advantage of this to
|
|
|
|
|
simplify the protocol. The GUI can ask bochs to do things and get a
|
|
|
|
|
response back. Bochs can tell the GUI something, but will not get a
|
|
|
|
|
response back.
|
|
|
|
|
|
|
|
|
|
The control panel should exist before the Bochs simulator starts, so that the
|
|
|
|
|
user can get their settings right before booting up a simulator. Once
|
|
|
|
|
bochs has begun, some settings can no longer be changed, such as how much
|
|
|
|
|
memory there is. Others can be changed at any time, like the value of IPS
|
|
|
|
|
or the name of the floppy disk images. If you had the bochs simulator
|
|
|
|
|
as a shared library, the GUI could let you choose which version of the
|
|
|
|
|
simulator library to load (one with debugging or SMP support or not,
|
|
|
|
|
for example).
|
|
|
|
|
|
|
|
|
|
When the control panel connects to Bochs, each needs to learn what the other
|
|
|
|
|
can do. Some versions of Bochs will have cdrom support, others will not.
|
|
|
|
|
Design a simple and general way for the two parties to describe what they
|
|
|
|
|
can do, so that the GUI can grey-out some menu choices, and Bochs knows
|
|
|
|
|
what the GUI can handle. I think Bochs should provide a list of
|
|
|
|
|
capabilities in something like the form of:
|
|
|
|
|
typedef struct { Bit16u id; String name; } bx_capability_t;
|
|
|
|
|
Only the negotiation of capabilities uses the string name, and for everything
|
|
|
|
|
else the 16-bit id is used (use htons() if sending over network). Each
|
|
|
|
|
capability is like a function that can be called on the remote object,
|
|
|
|
|
and each function needs an input list and a return value.
|
|
|
|
|
|
|
|
|
|
Hmm.... This sounds like reinventing function calls. Next I'm going to
|
2001-06-10 00:01:12 +04:00
|
|
|
|
say we need to implement prototypes and type checking. Why not just
|
|
|
|
|
write a compiler!
|
2001-06-08 11:20:07 +04:00
|
|
|
|
*/
|
|
|
|
|
|
2001-06-11 10:48:37 +04:00
|
|
|
|
#include "config.h"
|
|
|
|
|
|
2001-06-08 11:20:07 +04:00
|
|
|
|
extern "C" {
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <string.h>
|
2001-06-10 00:01:12 +04:00
|
|
|
|
#include <assert.h>
|
2001-06-08 00:42:00 +04:00
|
|
|
|
}
|
2001-06-10 07:53:43 +04:00
|
|
|
|
#include "osdep.h"
|
2001-06-10 00:01:12 +04:00
|
|
|
|
#include "control.h"
|
2001-06-08 11:20:07 +04:00
|
|
|
|
#include "siminterface.h"
|
|
|
|
|
|
2001-06-11 10:35:18 +04:00
|
|
|
|
#define CPANEL_PATH_LEN 512
|
2001-06-08 00:42:00 +04:00
|
|
|
|
|
2002-03-10 13:19:32 +03:00
|
|
|
|
#define BX_INSERTED 11
|
|
|
|
|
|
2001-06-10 00:01:12 +04:00
|
|
|
|
/* functions for changing particular options */
|
2001-06-11 18:03:35 +04:00
|
|
|
|
void bx_control_panel_init ();
|
2001-06-10 00:01:12 +04:00
|
|
|
|
int bx_read_rc (char *rc);
|
2001-06-11 10:35:18 +04:00
|
|
|
|
int bx_write_rc (char *rc);
|
2001-06-10 00:01:12 +04:00
|
|
|
|
void bx_log_options (int individual);
|
2001-06-08 00:42:00 +04:00
|
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
/* lots of code stolen from bximage.c */
|
|
|
|
|
/* remove leading spaces, newline junk at end. returns pointer to
|
|
|
|
|
cleaned string, which is between s0 and the null */
|
|
|
|
|
char *
|
|
|
|
|
clean_string (char *s0)
|
|
|
|
|
{
|
|
|
|
|
char *s = s0;
|
|
|
|
|
char *ptr;
|
|
|
|
|
/* find first nonblank */
|
|
|
|
|
while (isspace (*s))
|
|
|
|
|
s++;
|
|
|
|
|
/* truncate string at first non-alphanumeric */
|
|
|
|
|
ptr = s;
|
|
|
|
|
while (isprint (*ptr))
|
|
|
|
|
ptr++;
|
|
|
|
|
*ptr = 0;
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* returns 0 on success, -1 on failure. The value goes into out. */
|
|
|
|
|
int
|
2001-06-18 18:11:55 +04:00
|
|
|
|
ask_uint (char *prompt, Bit32u min, Bit32u max, Bit32u the_default, Bit32u *out, int base)
|
|
|
|
|
{
|
2002-03-10 13:19:32 +03:00
|
|
|
|
Bit32u n = max + 1;
|
2001-06-18 18:11:55 +04:00
|
|
|
|
char buffer[1024];
|
|
|
|
|
char *clean;
|
|
|
|
|
int illegal;
|
|
|
|
|
assert (base==10 || base==16);
|
|
|
|
|
while (1) {
|
|
|
|
|
printf (prompt, the_default);
|
|
|
|
|
if (!fgets (buffer, sizeof(buffer), stdin))
|
|
|
|
|
return -1;
|
|
|
|
|
clean = clean_string (buffer);
|
|
|
|
|
if (strlen(clean) < 1) {
|
|
|
|
|
// empty line, use the default
|
|
|
|
|
*out = the_default;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-06-19 18:55:34 +04:00
|
|
|
|
const char *format = (base==10) ? "%d" : "%x";
|
2001-06-18 18:11:55 +04:00
|
|
|
|
illegal = (1 != sscanf (buffer, format, &n));
|
|
|
|
|
if (illegal || n<min || n>max) {
|
|
|
|
|
printf ("Your choice (%s) was not an integer between %u and %u.\n\n",
|
|
|
|
|
clean, min, max);
|
|
|
|
|
} else {
|
|
|
|
|
// choice is okay
|
|
|
|
|
*out = n;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// identical to ask_uint, but uses signed comparisons
|
|
|
|
|
int
|
|
|
|
|
ask_int (char *prompt, Bit32s min, Bit32s max, Bit32s the_default, Bit32s *out)
|
2001-06-08 00:42:00 +04:00
|
|
|
|
{
|
|
|
|
|
int n = max + 1;
|
|
|
|
|
char buffer[1024];
|
|
|
|
|
char *clean;
|
|
|
|
|
int illegal;
|
|
|
|
|
while (1) {
|
2001-06-10 00:01:12 +04:00
|
|
|
|
printf (prompt, the_default);
|
2001-06-08 00:42:00 +04:00
|
|
|
|
if (!fgets (buffer, sizeof(buffer), stdin))
|
|
|
|
|
return -1;
|
|
|
|
|
clean = clean_string (buffer);
|
|
|
|
|
if (strlen(clean) < 1) {
|
|
|
|
|
// empty line, use the default
|
|
|
|
|
*out = the_default;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
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",
|
|
|
|
|
clean, min, max);
|
|
|
|
|
} else {
|
|
|
|
|
// choice is okay
|
|
|
|
|
*out = n;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
ask_menu (char *prompt, int n_choices, char *choice[], int the_default, int *out)
|
|
|
|
|
{
|
|
|
|
|
char buffer[1024];
|
|
|
|
|
char *clean;
|
|
|
|
|
int i;
|
|
|
|
|
*out = -1;
|
|
|
|
|
while (1) {
|
2001-06-10 00:01:12 +04:00
|
|
|
|
printf (prompt, choice[the_default]);
|
2001-06-08 00:42:00 +04:00
|
|
|
|
if (!fgets (buffer, sizeof(buffer), stdin))
|
|
|
|
|
return -1;
|
|
|
|
|
clean = clean_string (buffer);
|
|
|
|
|
if (strlen(clean) < 1) {
|
|
|
|
|
// empty line, use the default
|
|
|
|
|
*out = the_default;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
for (i=0; i<n_choices; i++) {
|
|
|
|
|
if (!strcmp (choice[i], clean)) {
|
|
|
|
|
// matched, return the choice number
|
|
|
|
|
*out = i;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
printf ("Your choice (%s) did not match any of the choices:\n", clean);
|
|
|
|
|
for (i=0; i<n_choices; i++) {
|
|
|
|
|
if (i>0) printf (", ");
|
|
|
|
|
printf ("%s", choice[i]);
|
|
|
|
|
}
|
|
|
|
|
printf ("\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2001-06-18 18:11:55 +04:00
|
|
|
|
ask_yn (char *prompt, Bit32u the_default, Bit32u *out)
|
2001-06-08 00:42:00 +04:00
|
|
|
|
{
|
|
|
|
|
char buffer[16];
|
|
|
|
|
char *clean;
|
2001-06-18 18:11:55 +04:00
|
|
|
|
*out = 1<<31;
|
2001-06-08 00:42:00 +04:00
|
|
|
|
while (1) {
|
2001-06-10 00:01:12 +04:00
|
|
|
|
// if there's a %s field, substitute in the default yes/no.
|
|
|
|
|
printf (prompt, the_default ? "yes" : "no");
|
2001-06-08 00:42:00 +04:00
|
|
|
|
if (!fgets (buffer, sizeof(buffer), stdin))
|
|
|
|
|
return -1;
|
|
|
|
|
clean = clean_string (buffer);
|
|
|
|
|
if (strlen(clean) < 1) {
|
|
|
|
|
// empty line, use the default
|
|
|
|
|
*out = the_default;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
switch (tolower(clean[0])) {
|
|
|
|
|
case 'y': *out=1; return 0;
|
|
|
|
|
case 'n': *out=0; return 0;
|
|
|
|
|
}
|
|
|
|
|
printf ("Please type either yes or no.\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-21 23:27:05 +04:00
|
|
|
|
// returns -1 on error (stream closed or something)
|
|
|
|
|
// returns 0 if default was taken
|
|
|
|
|
// returns 1 if value changed
|
2001-06-08 00:42:00 +04:00
|
|
|
|
int
|
|
|
|
|
ask_string (char *prompt, char *the_default, char *out)
|
|
|
|
|
{
|
|
|
|
|
char buffer[1024];
|
|
|
|
|
char *clean;
|
2001-06-20 18:01:39 +04:00
|
|
|
|
assert (the_default != out);
|
2001-06-08 00:42:00 +04:00
|
|
|
|
out[0] = 0;
|
2001-06-10 00:01:12 +04:00
|
|
|
|
printf (prompt, the_default);
|
2001-06-20 18:01:39 +04:00
|
|
|
|
if (fgets (buffer, sizeof(buffer), stdin) == NULL)
|
2001-06-08 00:42:00 +04:00
|
|
|
|
return -1;
|
|
|
|
|
clean = clean_string (buffer);
|
|
|
|
|
if (strlen(clean) < 1) {
|
|
|
|
|
// empty line, use the default
|
|
|
|
|
strcpy (out, the_default);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
strcpy (out, clean);
|
2001-06-21 23:27:05 +04:00
|
|
|
|
return 1;
|
2001-06-08 00:42:00 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
|
2001-06-10 00:01:12 +04:00
|
|
|
|
static char *ask_about_control_panel =
|
2001-06-12 01:03:05 +04:00
|
|
|
|
"\n"
|
|
|
|
|
"This version of Bochs has a prototype configuration interface. Would\n"
|
|
|
|
|
"you like to try it?\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"If you choose yes, you can use a menu to choose configuration options.\n"
|
|
|
|
|
"If you choose no, Bochs will read a bochsrc file and run as usual.\n"
|
|
|
|
|
"Type yes or no: [yes] ";
|
2001-06-10 00:01:12 +04:00
|
|
|
|
|
2001-12-08 21:06:12 +03:00
|
|
|
|
|
|
|
|
|
|
2001-06-10 00:01:12 +04:00
|
|
|
|
static char *startup_menu_prompt =
|
2001-12-08 21:06:12 +03:00
|
|
|
|
"------------------------------\n"
|
|
|
|
|
"Bochs Configuration: Main Menu\n"
|
|
|
|
|
"------------------------------\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"This is the Bochs Configuration Interface, where you can describe the\n"
|
|
|
|
|
"machine that you want to simulate. The first choice, \"Read options\n"
|
|
|
|
|
"from...\", lets you read in a saved machine configuration from a file.\n"
|
|
|
|
|
"The second choice lets you edit the present configuration. The\n"
|
|
|
|
|
"third choice saves the current configuration to a file so that you\n"
|
|
|
|
|
"can use it again next time. When you are satisfied with the config-\n"
|
|
|
|
|
"uration, go ahead and start the simulation.\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Most people will want to read options from a file called .bochsrc,\n"
|
|
|
|
|
"then immediately start the simulation. A quick way to do this is to\n"
|
|
|
|
|
"press return three times to accept the default choices (shown in\n"
|
|
|
|
|
"square brackets).\n"
|
|
|
|
|
"\n"
|
2001-06-12 01:03:05 +04:00
|
|
|
|
"1. Read options from...\n"
|
|
|
|
|
"2. Edit options\n"
|
|
|
|
|
"3. Save options to...\n"
|
|
|
|
|
"4. Begin simulation\n"
|
|
|
|
|
"5. Quit now\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Please choose one: [%d] ";
|
2001-06-10 00:01:12 +04:00
|
|
|
|
|
|
|
|
|
static char *startup_options_prompt =
|
2001-06-12 01:03:05 +04:00
|
|
|
|
"------------------\n"
|
|
|
|
|
"Bochs Options Menu\n"
|
|
|
|
|
"------------------\n"
|
|
|
|
|
"0. Return to previous menu\n"
|
|
|
|
|
"1. Log file: %s\n"
|
|
|
|
|
"2. Log options for all devices\n"
|
|
|
|
|
"3. Log options for individual devices\n"
|
2001-06-13 19:52:04 +04:00
|
|
|
|
"4. Memory options\n"
|
2001-06-12 01:03:05 +04:00
|
|
|
|
"5. Interface options\n"
|
|
|
|
|
"6. Disk options\n"
|
2002-03-03 09:10:04 +03:00
|
|
|
|
"7. Serial or Parallel port options\n"
|
2001-11-12 05:35:09 +03:00
|
|
|
|
"8. Sound Blaster 16 options\n"
|
|
|
|
|
"9. NE2000 network card options\n"
|
|
|
|
|
"10. Other options\n"
|
2001-06-12 01:03:05 +04:00
|
|
|
|
"\n"
|
|
|
|
|
"Please choose one: [0] ";
|
2001-06-10 00:01:12 +04:00
|
|
|
|
|
|
|
|
|
static char *startup_sound_options_prompt =
|
2001-06-12 01:03:05 +04:00
|
|
|
|
"------------------\n"
|
|
|
|
|
"Bochs Sound Options\n"
|
|
|
|
|
"------------------\n"
|
|
|
|
|
"0. Return to previous menu\n"
|
|
|
|
|
"1. Sound Blaster 16: disabled\n"
|
|
|
|
|
"2. MIDI mode: 1, \n"
|
|
|
|
|
"3. MIDI output file: /dev/midi00\n"
|
|
|
|
|
"4. Wave mode: 1\n"
|
|
|
|
|
"5. Wave output file: dev/dsp\n"
|
|
|
|
|
"6. SB16 log level: 2\n"
|
|
|
|
|
"7. SB16 log file: sb16.log\n"
|
|
|
|
|
"8. DMA Timer: 600000\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Please choose one: [0] ";
|
2001-06-10 00:01:12 +04:00
|
|
|
|
|
|
|
|
|
static char *startup_misc_options_prompt =
|
2001-06-12 01:03:05 +04:00
|
|
|
|
"---------------------------\n"
|
|
|
|
|
"Bochs Miscellaneous Options\n"
|
|
|
|
|
"---------------------------\n"
|
|
|
|
|
"1. Keyboard Serial Delay: 250\n"
|
|
|
|
|
"2. Floppy command delay: 500\n"
|
|
|
|
|
"To be added someday: magic_break, ne2k, load32bitOSImage,i440fxsupport,time0"
|
|
|
|
|
"\n"
|
|
|
|
|
"Please choose one: [0] ";
|
2001-06-08 00:42:00 +04:00
|
|
|
|
|
2001-06-10 00:01:12 +04:00
|
|
|
|
static char *runtime_menu_prompt =
|
2001-06-12 01:03:05 +04:00
|
|
|
|
"---------------------\n"
|
|
|
|
|
"Bochs Runtime Options\n"
|
|
|
|
|
"---------------------\n"
|
2001-06-13 12:14:49 +04:00
|
|
|
|
"1. Floppy disk 0: %s\n"
|
|
|
|
|
"2. Floppy disk 1: %s\n"
|
|
|
|
|
"3. CDROM: %s\n"
|
2001-11-10 03:40:40 +03:00
|
|
|
|
"4. (not implemented)\n"
|
2001-06-13 12:14:49 +04:00
|
|
|
|
"5. Log options for all devices\n"
|
|
|
|
|
"6. Log options for individual devices\n"
|
|
|
|
|
"7. VGA Update Interval: %d\n"
|
|
|
|
|
"8. Mouse: %s\n"
|
2002-03-26 17:46:03 +03:00
|
|
|
|
"9. Keyboard paste delay: %d\n"
|
|
|
|
|
"10. Instruction tracing: off (doesn't exist yet)\n"
|
|
|
|
|
"11. Continue simulation\n"
|
|
|
|
|
"12. Quit now\n"
|
2001-06-12 01:03:05 +04:00
|
|
|
|
"\n"
|
2002-04-08 04:11:52 +04:00
|
|
|
|
"Please choose one: [11] ";
|
2001-06-10 00:01:12 +04:00
|
|
|
|
|
|
|
|
|
char *menu_prompt_list[BX_CPANEL_N_MENUS] = {
|
|
|
|
|
ask_about_control_panel,
|
|
|
|
|
startup_menu_prompt,
|
|
|
|
|
startup_options_prompt,
|
2001-06-21 18:37:55 +04:00
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
2001-06-10 00:01:12 +04:00
|
|
|
|
startup_sound_options_prompt,
|
|
|
|
|
startup_misc_options_prompt,
|
|
|
|
|
runtime_menu_prompt
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define NOT_IMPLEMENTED(choice) \
|
|
|
|
|
fprintf (stderr, "ERROR: choice %d not implemented\n", choice);
|
|
|
|
|
|
|
|
|
|
#define BAD_OPTION(menu,choice) \
|
|
|
|
|
do {fprintf (stderr, "ERROR: control panel menu %d has no choice %d\n", menu, choice); \
|
|
|
|
|
assert (0); } while (0)
|
|
|
|
|
|
2001-06-13 12:14:49 +04:00
|
|
|
|
void build_runtime_options_prompt (char *format, char *buf, int size)
|
|
|
|
|
{
|
|
|
|
|
bx_floppy_options floppyop;
|
|
|
|
|
bx_cdrom_options cdromop;
|
2001-06-16 23:29:59 +04:00
|
|
|
|
bx_param_num_c *ips = SIM->get_param_num (BXP_IPS);
|
2001-06-13 12:14:49 +04:00
|
|
|
|
char buffer[3][128];
|
|
|
|
|
for (int i=0; i<2; i++) {
|
|
|
|
|
SIM->get_floppy_options (i, &floppyop);
|
2001-06-20 18:01:39 +04:00
|
|
|
|
sprintf (buffer[i], "%s, size=%s, %s", floppyop.Opath->getptr (),
|
2002-01-28 00:55:27 +03:00
|
|
|
|
SIM->get_floppy_type_name (floppyop.Otype->get ()),
|
2002-03-10 13:19:32 +03:00
|
|
|
|
(floppyop.Oinitial_status->get () == BX_INSERTED)? "inserted" : "ejected");
|
2001-06-20 18:01:39 +04:00
|
|
|
|
if (!floppyop.Opath->getptr ()[0]) strcpy (buffer[i], "none");
|
2001-06-13 12:14:49 +04:00
|
|
|
|
}
|
|
|
|
|
SIM->get_cdrom_options (0, &cdromop);
|
|
|
|
|
sprintf (buffer[2], "%s, %spresent, %s",
|
2002-01-28 00:55:27 +03:00
|
|
|
|
cdromop.Opath->getptr (), cdromop.Opresent->get ()?"":"not ",
|
2002-03-10 13:19:32 +03:00
|
|
|
|
(cdromop.Oinserted->get () == BX_INSERTED)? "inserted" : "ejected");
|
2001-06-13 12:14:49 +04:00
|
|
|
|
snprintf (buf, size, format, buffer[0], buffer[1], buffer[2],
|
2001-11-10 06:12:44 +03:00
|
|
|
|
/* ips->get (), */
|
2001-06-16 23:29:59 +04:00
|
|
|
|
SIM->get_param_num (BXP_VGA_UPDATE_INTERVAL)->get (),
|
2002-03-26 17:46:03 +03:00
|
|
|
|
SIM->get_param_num (BXP_MOUSE_ENABLED)->get () ? "enabled" : "disabled",
|
|
|
|
|
SIM->get_param_num (BXP_KBD_PASTE_DELAY)->get ());
|
2001-06-13 12:14:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
2001-06-21 18:37:55 +04:00
|
|
|
|
int do_menu (bx_id id) {
|
|
|
|
|
bx_list_c *menu = (bx_list_c *)SIM->get_param (id);
|
2001-06-18 18:11:55 +04:00
|
|
|
|
while (1) {
|
|
|
|
|
menu->get_choice()->set (0);
|
|
|
|
|
int status = menu->text_ask (stdin, stderr);
|
|
|
|
|
if (status < 0) return status;
|
|
|
|
|
bx_param_num_c *choice = menu->get_choice();
|
|
|
|
|
if (choice->get () < 1)
|
|
|
|
|
return choice->get ();
|
|
|
|
|
else {
|
|
|
|
|
int index = choice->get () - 1; // choosing 1 means list[0]
|
|
|
|
|
bx_param_c *chosen = menu->get (index);
|
|
|
|
|
assert (chosen != NULL);
|
|
|
|
|
chosen->text_ask (stdin, stderr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-21 18:37:55 +04:00
|
|
|
|
void askparam (bx_id id)
|
|
|
|
|
{
|
|
|
|
|
bx_param_c *param = SIM->get_param (id);
|
|
|
|
|
param->text_ask (stdin, stderr);
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-10 00:01:12 +04:00
|
|
|
|
int bx_control_panel (int menu)
|
|
|
|
|
{
|
2001-06-18 18:11:55 +04:00
|
|
|
|
Bit32u choice;
|
2001-06-10 00:01:12 +04:00
|
|
|
|
while (1) {
|
|
|
|
|
switch (menu)
|
|
|
|
|
{
|
2001-10-07 02:31:31 +04:00
|
|
|
|
case BX_CPANEL_INIT:
|
2001-06-11 18:03:35 +04:00
|
|
|
|
bx_control_panel_init ();
|
2001-10-07 02:31:31 +04:00
|
|
|
|
return 0;
|
2001-06-10 00:01:12 +04:00
|
|
|
|
case BX_CPANEL_START_MENU:
|
|
|
|
|
{
|
|
|
|
|
static int read_rc = 0;
|
2001-06-18 18:11:55 +04:00
|
|
|
|
Bit32u default_choice = 1;
|
2001-06-11 10:35:18 +04:00
|
|
|
|
default_choice = read_rc ? 4 : 1;
|
2001-06-18 18:11:55 +04:00
|
|
|
|
if (ask_uint (startup_menu_prompt, 1, 5, default_choice, &choice, 10) < 0) return -1;
|
2001-06-10 00:01:12 +04:00
|
|
|
|
switch (choice) {
|
2001-06-11 10:35:18 +04:00
|
|
|
|
case 1: if (bx_read_rc (NULL) >= 0) read_rc=1; break;
|
|
|
|
|
case 2: bx_control_panel (BX_CPANEL_START_OPTS); break;
|
|
|
|
|
case 3: bx_write_rc (NULL); break;
|
|
|
|
|
case 4: return 0; // return from menu
|
|
|
|
|
case 5: SIM->quit_sim (1); return -1;
|
2001-06-10 00:01:12 +04:00
|
|
|
|
default: BAD_OPTION(menu, choice);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case BX_CPANEL_START_OPTS:
|
|
|
|
|
{
|
2001-06-11 10:35:18 +04:00
|
|
|
|
char prompt[CPANEL_PATH_LEN];
|
2001-10-07 22:16:01 +04:00
|
|
|
|
char oldpath[CPANEL_PATH_LEN];
|
|
|
|
|
int retval = SIM->get_log_file (oldpath, CPANEL_PATH_LEN);
|
|
|
|
|
assert (retval >= 0);
|
2001-06-10 00:01:12 +04:00
|
|
|
|
sprintf (prompt, startup_options_prompt, oldpath);
|
2001-11-12 05:35:09 +03:00
|
|
|
|
if (ask_uint (prompt, 0, 10, 0, &choice, 10) < 0) return -1;
|
2001-06-10 00:01:12 +04:00
|
|
|
|
switch (choice) {
|
|
|
|
|
case 0: return 0;
|
2001-06-21 18:37:55 +04:00
|
|
|
|
case 1: askparam (BXP_LOG_FILENAME); break;
|
2001-06-10 00:01:12 +04:00
|
|
|
|
case 2: bx_log_options (0); break;
|
|
|
|
|
case 3: bx_log_options (1); break;
|
2001-06-21 22:34:50 +04:00
|
|
|
|
case 4: do_menu (BXP_MENU_MEMORY); break;
|
|
|
|
|
case 5: do_menu (BXP_MENU_INTERFACE); break;
|
|
|
|
|
case 6: do_menu (BXP_MENU_DISK); break;
|
2002-03-03 09:10:04 +03:00
|
|
|
|
case 7: do_menu (BXP_MENU_SERIAL_PARALLEL); break;
|
2001-11-12 05:35:09 +03:00
|
|
|
|
case 8: do_menu (BXP_SB16); break;
|
|
|
|
|
case 9: do_menu (BXP_NE2K); break;
|
|
|
|
|
case 10: do_menu (BXP_MENU_MISC); break;
|
2001-06-10 00:01:12 +04:00
|
|
|
|
default: BAD_OPTION(menu, choice);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case BX_CPANEL_RUNTIME:
|
2001-06-13 12:14:49 +04:00
|
|
|
|
char prompt[1024];
|
|
|
|
|
build_runtime_options_prompt (runtime_menu_prompt, prompt, 1024);
|
2002-03-26 17:46:03 +03:00
|
|
|
|
if (ask_uint (prompt, 1, 12, 11, &choice, 10) < 0) return -1;
|
2001-06-10 00:01:12 +04:00
|
|
|
|
switch (choice) {
|
2001-06-21 18:37:55 +04:00
|
|
|
|
case 1: do_menu (BXP_FLOPPYA); break;
|
|
|
|
|
case 2: do_menu (BXP_FLOPPYB); break;
|
|
|
|
|
case 3: do_menu (BXP_CDROMD); break;
|
2001-11-10 03:40:40 +03:00
|
|
|
|
case 4: // not implemented yet because I would have to mess with
|
|
|
|
|
// resetting timers and pits and everything on the fly.
|
|
|
|
|
// askparam (BXP_IPS);
|
|
|
|
|
break;
|
2001-06-13 12:14:49 +04:00
|
|
|
|
case 5: bx_log_options (0); break;
|
|
|
|
|
case 6: bx_log_options (1); break;
|
2001-06-21 18:37:55 +04:00
|
|
|
|
case 7: askparam (BXP_VGA_UPDATE_INTERVAL); break;
|
|
|
|
|
case 8: askparam (BXP_MOUSE_ENABLED); break;
|
2002-03-26 17:46:03 +03:00
|
|
|
|
case 9: askparam (BXP_KBD_PASTE_DELAY); break;
|
|
|
|
|
case 10: NOT_IMPLEMENTED (choice); break;
|
|
|
|
|
case 11: fprintf (stderr, "Continuing simulation\n"); return 0;
|
|
|
|
|
case 12:
|
2001-06-10 00:01:12 +04:00
|
|
|
|
fprintf (stderr, "You chose quit on the control panel.\n");
|
|
|
|
|
SIM->quit_sim (1);
|
|
|
|
|
return -1;
|
|
|
|
|
default: fprintf (stderr, "Menu choice %d not implemented.\n", choice);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
assert (menu >=0 && menu < BX_CPANEL_N_MENUS);
|
|
|
|
|
fprintf (stderr, "--THIS IS A SAMPLE MENU, NO OPTIONS ARE IMPLEMENTED EXCEPT #0--\n");
|
2001-06-18 18:11:55 +04:00
|
|
|
|
if (ask_uint (menu_prompt_list[menu], 0, 99, 0, &choice, 10) < 0) return -1;
|
2001-06-10 00:01:12 +04:00
|
|
|
|
if (choice == 0) return 0;
|
|
|
|
|
fprintf (stderr, "This is a sample menu. Option %d is not implemented.\n", choice);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-06-08 00:42:00 +04:00
|
|
|
|
|
|
|
|
|
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");
|
2001-06-10 00:01:12 +04:00
|
|
|
|
fprintf (stderr, "---- --------- --------- --------- ---------- ----------\n");
|
2001-06-12 00:51:15 +04:00
|
|
|
|
int i, j, imax=SIM->get_n_log_modules ();
|
|
|
|
|
for (i=0; i<imax; i++) {
|
2001-06-08 11:20:07 +04:00
|
|
|
|
fprintf (stderr, "%3d. %s ", i, SIM->get_prefix (i));
|
2001-06-12 00:51:15 +04:00
|
|
|
|
for (j=0; j<SIM->get_max_log_level (); j++) {
|
2001-06-08 11:20:07 +04:00
|
|
|
|
fprintf (stderr, "%10s ", SIM->get_action_name (SIM->get_log_action (i, j)));
|
2001-06-08 00:42:00 +04:00
|
|
|
|
}
|
|
|
|
|
fprintf (stderr, "\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *log_options_prompt1 = "Enter the ID of the device to edit, or -1 to return: [-1] ";
|
2001-06-13 12:14:49 +04:00
|
|
|
|
static char *log_level_choices[] = { "ignore", "report", "ask", "fatal", "no change" };
|
|
|
|
|
static int log_level_n_choices_normal = 4;
|
2001-06-08 00:42:00 +04:00
|
|
|
|
|
2001-06-10 00:01:12 +04:00
|
|
|
|
void bx_log_options (int individual)
|
2001-06-08 00:42:00 +04:00
|
|
|
|
{
|
2001-06-10 00:01:12 +04:00
|
|
|
|
if (individual) {
|
|
|
|
|
int done = 0;
|
|
|
|
|
while (!done) {
|
|
|
|
|
bx_print_log_action_table ();
|
2001-06-18 18:11:55 +04:00
|
|
|
|
Bit32s id, level, action;
|
|
|
|
|
Bit32s maxid = SIM->get_n_log_modules ();
|
2001-06-10 00:01:12 +04:00
|
|
|
|
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));
|
|
|
|
|
for (level=0; level<SIM->get_max_log_level (); level++) {
|
|
|
|
|
char prompt[1024];
|
|
|
|
|
int default_action = SIM->get_log_action (id, level);
|
|
|
|
|
sprintf (prompt, "Enter action for %s event: [%s] ", SIM->get_log_level_name (level), SIM->get_action_name(default_action));
|
|
|
|
|
// don't show the no change choice (choices=3)
|
2001-06-13 12:14:49 +04:00
|
|
|
|
if (ask_menu (prompt, log_level_n_choices_normal, log_level_choices, default_action, &action)<0)
|
2001-06-10 00:01:12 +04:00
|
|
|
|
return;
|
|
|
|
|
SIM->set_log_action (id, level, action);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// provide an easy way to set log options for all devices at once
|
2001-06-08 00:42:00 +04:00
|
|
|
|
bx_print_log_action_table ();
|
2001-06-10 00:01:12 +04:00
|
|
|
|
for (int level=0; level<SIM->get_max_log_level (); level++) {
|
2001-06-08 00:42:00 +04:00
|
|
|
|
char prompt[1024];
|
2001-06-10 00:01:12 +04:00
|
|
|
|
int action, default_action = 3; // default to no change
|
|
|
|
|
sprintf (prompt, "Enter action for %s event on all devices: [no change] ", SIM->get_log_level_name (level));
|
|
|
|
|
// do show the no change choice (choices=4)
|
2001-06-13 12:14:49 +04:00
|
|
|
|
if (ask_menu (prompt, log_level_n_choices_normal+1, log_level_choices, default_action, &action)<0)
|
2001-06-08 00:42:00 +04:00
|
|
|
|
return;
|
2001-06-10 00:01:12 +04:00
|
|
|
|
if (action < 3) {
|
|
|
|
|
for (int i=0; i<SIM->get_n_log_modules (); i++)
|
|
|
|
|
SIM->set_log_action (i, level, action);
|
|
|
|
|
}
|
2001-06-08 00:42:00 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-06-10 00:01:12 +04:00
|
|
|
|
|
|
|
|
|
int bx_read_rc (char *rc)
|
|
|
|
|
{
|
|
|
|
|
if (rc && SIM->read_rc (rc) >= 0) return 0;
|
2001-06-11 10:35:18 +04:00
|
|
|
|
char oldrc[CPANEL_PATH_LEN];
|
|
|
|
|
if (SIM->get_default_rc (oldrc, CPANEL_PATH_LEN) < 0)
|
|
|
|
|
strcpy (oldrc, "none");
|
|
|
|
|
char newrc[CPANEL_PATH_LEN];
|
2001-06-10 00:01:12 +04:00
|
|
|
|
while (1) {
|
2001-06-11 10:35:18 +04:00
|
|
|
|
if (ask_string ("\nWhat is the configuration file name?\nTo cancel, type 'none'. [%s] ", oldrc, newrc) < 0) return -1;
|
2001-06-10 00:01:12 +04:00
|
|
|
|
if (!strcmp (newrc, "none")) return 0;
|
|
|
|
|
if (SIM->read_rc (newrc) >= 0) return 0;
|
|
|
|
|
fprintf (stderr, "The file '%s' could not be found.\n", newrc);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-11 10:35:18 +04:00
|
|
|
|
int bx_write_rc (char *rc)
|
|
|
|
|
{
|
|
|
|
|
char oldrc[CPANEL_PATH_LEN], newrc[CPANEL_PATH_LEN];
|
|
|
|
|
if (rc == NULL) {
|
|
|
|
|
if (SIM->get_default_rc (oldrc, CPANEL_PATH_LEN) < 0)
|
|
|
|
|
strcpy (oldrc, "none");
|
|
|
|
|
} else {
|
|
|
|
|
strncpy (oldrc, rc, CPANEL_PATH_LEN);
|
|
|
|
|
}
|
|
|
|
|
while (1) {
|
|
|
|
|
if (ask_string ("Save configuration to what file? To cancel, type 'none'.\n[%s] ", oldrc, newrc) < 0) return -1;
|
|
|
|
|
if (!strcmp (newrc, "none")) return 0;
|
|
|
|
|
// try with overwrite off first
|
|
|
|
|
int status = SIM->write_rc (newrc, 0);
|
|
|
|
|
if (status >= 0) {
|
|
|
|
|
fprintf (stderr, "Wrote configuration to '%s'.\n", newrc);
|
|
|
|
|
return 0;
|
|
|
|
|
} else if (status == -2) {
|
|
|
|
|
// return code -2 indicates the file already exists, and overwrite
|
|
|
|
|
// confirmation is required.
|
2001-06-18 18:11:55 +04:00
|
|
|
|
Bit32u overwrite = 0;
|
2001-06-11 10:35:18 +04:00
|
|
|
|
char prompt[256];
|
|
|
|
|
sprintf (prompt, "Configuration file '%s' already exists. Overwrite it? [no] ", newrc);
|
|
|
|
|
if (ask_yn (prompt, 0, &overwrite) < 0) return -1;
|
|
|
|
|
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);
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
fprintf (stderr, "Write failed to '%s'.\n", newrc);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-10-07 04:35:35 +04:00
|
|
|
|
char *log_action_ask_choices[] = { "cont", "alwayscont", "die", "abort", "debug" };
|
|
|
|
|
int log_action_n_choices = 4 + (BX_DEBUGGER?1:0);
|
2001-06-11 18:03:35 +04:00
|
|
|
|
|
|
|
|
|
int control_panel_notify_callback (int code)
|
|
|
|
|
{
|
|
|
|
|
switch (code)
|
|
|
|
|
{
|
|
|
|
|
case NOTIFY_CODE_LOGMSG:
|
|
|
|
|
{
|
|
|
|
|
int level;
|
2001-10-07 22:16:01 +04:00
|
|
|
|
char prefix[512], msg[512];
|
|
|
|
|
int retval = SIM->log_msg_2 (prefix, &level, msg, sizeof(msg)) >= 0;
|
|
|
|
|
assert (retval);
|
2001-06-11 18:03:35 +04:00
|
|
|
|
fprintf (stderr, "========================================================================\n");
|
|
|
|
|
fprintf (stderr, "Event type: %s\n", SIM->get_log_level_name (level));
|
|
|
|
|
fprintf (stderr, "Device: %s\n", prefix);
|
|
|
|
|
fprintf (stderr, "Message: %s\n\n", msg);
|
2001-06-11 18:07:54 +04:00
|
|
|
|
fprintf (stderr, "A %s has occurred. Do you want to:\n", SIM->get_log_level_name (level));
|
2001-06-11 18:03:35 +04:00
|
|
|
|
fprintf (stderr, " cont - continue execution\n");
|
|
|
|
|
fprintf (stderr, " alwayscont - continue execution, and don't ask again.\n");
|
|
|
|
|
fprintf (stderr, " This affects only %s events from device %s\n", SIM->get_log_level_name (level), prefix);
|
|
|
|
|
fprintf (stderr, " die - stop execution now\n");
|
2001-10-07 04:35:35 +04:00
|
|
|
|
fprintf (stderr, " abort - dump core %s\n",
|
|
|
|
|
BX_HAVE_ABORT ? "" : "(Disabled)");
|
2001-10-06 09:51:34 +04:00
|
|
|
|
#if BX_DEBUGGER
|
2001-10-06 12:45:18 +04:00
|
|
|
|
fprintf (stderr, " debug - continue and return to bochs debugger\n");
|
2001-10-06 09:51:34 +04:00
|
|
|
|
#endif
|
2001-06-11 18:03:35 +04:00
|
|
|
|
int choice;
|
2001-10-07 04:35:35 +04:00
|
|
|
|
ask:
|
|
|
|
|
if (ask_menu ("Choose one of the actions above: [%s] ",
|
2001-10-06 09:51:34 +04:00
|
|
|
|
log_action_n_choices, log_action_ask_choices, 2, &choice) < 0)
|
2001-06-11 18:03:35 +04:00
|
|
|
|
return SIM->notify_return(-1);
|
2001-10-06 09:51:34 +04:00
|
|
|
|
// return 0 for continue, 1 for alwayscontinue, 2 for die, 3 for debug.
|
2001-10-07 04:35:35 +04:00
|
|
|
|
if (!BX_HAVE_ABORT && choice==3) goto ask;
|
2002-04-01 08:12:11 +04:00
|
|
|
|
fflush(stdout);
|
|
|
|
|
fflush(stderr);
|
2001-06-11 18:03:35 +04:00
|
|
|
|
SIM->notify_return(choice);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
fprintf (stderr, "Control panel: notify callback called with unknown code %04x\n", code);
|
|
|
|
|
}
|
2001-06-12 00:51:15 +04:00
|
|
|
|
// error if we fall through the case
|
|
|
|
|
return -1;
|
2001-06-11 18:03:35 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void bx_control_panel_init () {
|
|
|
|
|
//fprintf (stderr, "bx_control_panel_init()\n");
|
|
|
|
|
SIM->set_notify_callback (control_panel_notify_callback);
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-18 18:11:55 +04:00
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
// implement the text_* methods for bx_param types.
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
bx_param_num_c::text_print (FILE *fp)
|
|
|
|
|
{
|
|
|
|
|
//fprintf (fp, "number parameter, id=%u, name=%s\n", get_id (), get_name ());
|
|
|
|
|
//fprintf (fp, "value=%u\n", get ());
|
|
|
|
|
if (get_format ()) {
|
|
|
|
|
fprintf (fp, get_format (), get ());
|
|
|
|
|
} else {
|
2001-06-21 18:37:55 +04:00
|
|
|
|
char *format = "%s: %d";
|
2001-06-18 18:11:55 +04:00
|
|
|
|
assert (base==10 || base==16);
|
2001-06-21 22:34:50 +04:00
|
|
|
|
if (base==16) format = "%s: 0x%x";
|
2001-06-18 18:11:55 +04:00
|
|
|
|
fprintf (fp, format, get_name (), get ());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-20 18:01:39 +04:00
|
|
|
|
void
|
|
|
|
|
bx_param_bool_c::text_print (FILE *fp)
|
|
|
|
|
{
|
|
|
|
|
if (get_format ()) {
|
2001-06-21 18:37:55 +04:00
|
|
|
|
fprintf (fp, get_format (), get () ? "yes" : "no");
|
|
|
|
|
} else {
|
|
|
|
|
char *format = "%s: %s";
|
|
|
|
|
fprintf (fp, format, get_name (), get () ? "yes" : "no");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
bx_param_enum_c::text_print (FILE *fp)
|
|
|
|
|
{
|
|
|
|
|
int n = get ();
|
|
|
|
|
assert (n >= min && n <= max);
|
|
|
|
|
char *choice = choices[n - min];
|
|
|
|
|
if (get_format ()) {
|
|
|
|
|
fprintf (fp, get_format (), choice);
|
2001-06-20 18:01:39 +04:00
|
|
|
|
} else {
|
2001-06-21 18:37:55 +04:00
|
|
|
|
char *format = "%s: %s";
|
2001-06-20 18:01:39 +04:00
|
|
|
|
fprintf (fp, format, get_name (), get () ? "yes" : "no");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-18 18:11:55 +04:00
|
|
|
|
void
|
|
|
|
|
bx_param_string_c::text_print (FILE *fp)
|
|
|
|
|
{
|
2001-06-21 23:27:05 +04:00
|
|
|
|
char *value = getptr ();
|
|
|
|
|
int opts = options->get ();
|
|
|
|
|
if (opts & BX_RAW_BYTES) {
|
|
|
|
|
char buffer[1024];
|
|
|
|
|
buffer[0] = 0;
|
|
|
|
|
char sep_string[2];
|
|
|
|
|
sep_string[0] = separator;
|
|
|
|
|
sep_string[1] = 0;
|
|
|
|
|
for (int i=0; i<maxsize; i++) {
|
|
|
|
|
char eachbyte[16];
|
|
|
|
|
sprintf (eachbyte, "%s%02x", (i>0)?sep_string : "", (unsigned int)0xff&val[i]);
|
|
|
|
|
strncat (buffer, eachbyte, sizeof(buffer));
|
|
|
|
|
}
|
|
|
|
|
if (strlen (buffer) > sizeof(buffer)-4) {
|
|
|
|
|
assert (0); // raw byte print buffer is probably overflowing. increase the max or make it dynamic
|
|
|
|
|
}
|
|
|
|
|
value = buffer;
|
|
|
|
|
}
|
2001-06-18 18:11:55 +04:00
|
|
|
|
if (get_format ()) {
|
2001-06-21 23:27:05 +04:00
|
|
|
|
fprintf (fp, get_format (), value);
|
2001-06-18 18:11:55 +04:00
|
|
|
|
} else {
|
2001-06-21 23:27:05 +04:00
|
|
|
|
fprintf (fp, "%s: %s", get_name (), value);
|
2001-06-18 18:11:55 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
bx_list_c::text_print (FILE *fp)
|
|
|
|
|
{
|
2001-06-21 18:37:55 +04:00
|
|
|
|
//fprintf (fp, "This is a list.\n");
|
|
|
|
|
//fprintf (fp, "title=%s\n", title->getptr ());
|
|
|
|
|
fprintf (fp, "%s: ", get_name ());
|
|
|
|
|
/*
|
2001-06-18 18:11:55 +04:00
|
|
|
|
fprintf (fp, "options=%s%s%s\n",
|
|
|
|
|
(options->get () == 0) ? "none" : "",
|
|
|
|
|
(options->get () & BX_SHOW_PARENT) ? "SHOW_PARENT " : "",
|
|
|
|
|
(options->get () & BX_SERIES_ASK) ? "SERIES_ASK " : "");
|
2001-06-21 18:37:55 +04:00
|
|
|
|
*/
|
2001-06-18 18:11:55 +04:00
|
|
|
|
for (int i=0; i<size; i++) {
|
2001-06-21 18:37:55 +04:00
|
|
|
|
//fprintf (fp, "param[%d] = %p\n", i, list[i]);
|
|
|
|
|
assert (list[i] != NULL);
|
|
|
|
|
if (list[i]->get_enabled ()) {
|
2001-06-18 18:11:55 +04:00
|
|
|
|
list[i]->text_print (fp);
|
2001-06-21 18:37:55 +04:00
|
|
|
|
if (!options->get () & BX_SERIES_ASK)
|
|
|
|
|
fprintf (fp, "\n");
|
|
|
|
|
}
|
2001-06-18 18:11:55 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
bx_param_num_c::text_ask (FILE *fpin, FILE *fpout)
|
|
|
|
|
{
|
|
|
|
|
fprintf (fpout, "\n");
|
|
|
|
|
int status;
|
|
|
|
|
char *prompt = get_ask_format ();
|
|
|
|
|
if (prompt == NULL) {
|
|
|
|
|
// default prompt, if they didn't set an ask format string
|
|
|
|
|
text_print (fpout);
|
2001-06-21 18:37:55 +04:00
|
|
|
|
fprintf (fpout, "\n");
|
2001-06-18 18:11:55 +04:00
|
|
|
|
prompt = "Enter new value: [%d] ";
|
|
|
|
|
if (base==16)
|
|
|
|
|
prompt = "Enter new value in hex: [%x] ";
|
|
|
|
|
}
|
|
|
|
|
Bit32u n = get ();
|
|
|
|
|
status = ask_uint (prompt, min, max, n, &n, base);
|
|
|
|
|
if (status < 0) return status;
|
|
|
|
|
set (n);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-20 18:01:39 +04:00
|
|
|
|
int
|
|
|
|
|
bx_param_bool_c::text_ask (FILE *fpin, FILE *fpout)
|
|
|
|
|
{
|
|
|
|
|
fprintf (fpout, "\n");
|
|
|
|
|
int status;
|
|
|
|
|
char *prompt = get_ask_format ();
|
|
|
|
|
if (prompt == NULL) {
|
|
|
|
|
// default prompt, if they didn't set an ask format string
|
2001-06-21 18:37:55 +04:00
|
|
|
|
char buffer[512];
|
|
|
|
|
sprintf (buffer, "%s? [%%s] ", get_name ());
|
|
|
|
|
prompt = buffer;
|
2001-06-20 18:01:39 +04:00
|
|
|
|
}
|
|
|
|
|
Bit32u n = get ();
|
|
|
|
|
status = ask_yn (prompt, n, &n);
|
|
|
|
|
if (status < 0) return status;
|
|
|
|
|
set (n);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-21 18:37:55 +04:00
|
|
|
|
int
|
|
|
|
|
bx_param_enum_c::text_ask (FILE *fpin, FILE *fpout)
|
|
|
|
|
{
|
|
|
|
|
fprintf (fpout, "\n");
|
|
|
|
|
char *prompt = get_ask_format ();
|
|
|
|
|
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");
|
|
|
|
|
prompt = "Enter new value: [%s] ";
|
|
|
|
|
}
|
|
|
|
|
Bit32s n = get () - min;
|
|
|
|
|
int status = ask_menu (prompt, (max-min+1), choices, n, &n);
|
|
|
|
|
if (status < 0) return status;
|
|
|
|
|
n += min;
|
|
|
|
|
set (n);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-06-20 18:01:39 +04:00
|
|
|
|
|
2001-06-21 23:27:05 +04:00
|
|
|
|
int parse_raw_bytes (char *dest, char *src, int destsize, char separator)
|
|
|
|
|
{
|
2001-06-21 23:31:19 +04:00
|
|
|
|
//printf ("parsing src='%s'\n", src);
|
2001-06-21 23:27:05 +04:00
|
|
|
|
int i;
|
|
|
|
|
unsigned int n;
|
|
|
|
|
for (i=0; i<destsize; i++)
|
|
|
|
|
dest[i] = 0;
|
|
|
|
|
for (i=0; i<destsize; i++) {
|
|
|
|
|
while (*src == separator)
|
|
|
|
|
src++;
|
|
|
|
|
if (*src == 0) break;
|
|
|
|
|
// try to read a byte of hex
|
|
|
|
|
if (sscanf (src, "%02x", &n) == 1) {
|
2001-06-21 23:31:19 +04:00
|
|
|
|
//printf ("found a byte %02x\n", n);
|
2001-06-21 23:27:05 +04:00
|
|
|
|
dest[i] = n;
|
|
|
|
|
src+=2;
|
|
|
|
|
} else {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-18 18:11:55 +04:00
|
|
|
|
int
|
|
|
|
|
bx_param_string_c::text_ask (FILE *fpin, FILE *fpout)
|
|
|
|
|
{
|
|
|
|
|
fprintf (fpout, "\n");
|
|
|
|
|
int status;
|
|
|
|
|
char *prompt = get_ask_format ();
|
|
|
|
|
if (prompt == NULL) {
|
|
|
|
|
// default prompt, if they didn't set an ask format string
|
|
|
|
|
text_print (fpout);
|
2001-06-21 18:37:55 +04:00
|
|
|
|
fprintf (fpout, "\n");
|
2001-06-18 18:11:55 +04:00
|
|
|
|
prompt = "Enter a new value, or press return for no change.\n";
|
|
|
|
|
}
|
2001-06-21 23:27:05 +04:00
|
|
|
|
while (1) {
|
|
|
|
|
char buffer[1024];
|
|
|
|
|
status = ask_string (prompt, getptr(), buffer);
|
|
|
|
|
if (status < 0) return status;
|
|
|
|
|
int opts = options->get ();
|
|
|
|
|
char buffer2[1024];
|
|
|
|
|
strcpy (buffer2, buffer);
|
|
|
|
|
if (status == 1 && opts & BX_RAW_BYTES) {
|
|
|
|
|
// 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);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
set (buffer);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-06-18 18:11:55 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
bx_list_c::text_ask (FILE *fpin, FILE *fpout)
|
|
|
|
|
{
|
2001-06-21 18:37:55 +04:00
|
|
|
|
char *my_title = title->getptr ();
|
2001-06-18 18:11:55 +04:00
|
|
|
|
fprintf (fpout, "\n");
|
2001-06-21 18:37:55 +04:00
|
|
|
|
int i, imax = strlen (my_title);
|
2001-06-18 18:11:55 +04:00
|
|
|
|
for (i=0; i<imax; i++) fprintf (fpout, "-");
|
2001-06-21 18:37:55 +04:00
|
|
|
|
fprintf (fpout, "\n%s\n", my_title);
|
2001-06-18 18:11:55 +04:00
|
|
|
|
for (i=0; i<imax; i++) fprintf (fpout, "-");
|
2001-06-21 18:37:55 +04:00
|
|
|
|
fprintf (fpout, "\n"); //fprintf (fp, "options=%s\n", options->get ());
|
|
|
|
|
if (options->get () & BX_SERIES_ASK) {
|
|
|
|
|
for (int i=0; i<size; i++) {
|
|
|
|
|
if (list[i]->get_enabled ())
|
|
|
|
|
list[i]->text_ask (fpin, fpout);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (options->get () & BX_SHOW_PARENT)
|
|
|
|
|
fprintf (fpout, "0. Return to previous menu\n");
|
|
|
|
|
for (int i=0; i<size; i++) {
|
|
|
|
|
assert (list[i] != NULL);
|
|
|
|
|
fprintf (fpout, "%d. ", i+1);
|
|
|
|
|
if (list[i]->get_enabled ()) {
|
|
|
|
|
list[i]->text_print (fpout);
|
|
|
|
|
fprintf (fpout, "\n");
|
|
|
|
|
} else
|
|
|
|
|
fprintf (fpout, "(disabled)\n");
|
|
|
|
|
}
|
2001-06-18 18:11:55 +04:00
|
|
|
|
fprintf (fpout, "\n");
|
2001-06-21 18:37:55 +04:00
|
|
|
|
Bit32u n = choice->get ();
|
|
|
|
|
int min = (options->get () & BX_SHOW_PARENT) ? 0 : 1;
|
|
|
|
|
int max = size;
|
|
|
|
|
int status = ask_uint ("Please choose one: [%d] ", min, max, n, &n, 10);
|
|
|
|
|
if (status < 0) return status;
|
|
|
|
|
choice->set (n);
|
|
|
|
|
}
|
2001-06-18 18:11:55 +04:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|