The device is the main unit of emulated components in 86Box. Each device is represented by one or more constant device_t
objects, which contain metadata about the device itself, several callbacks and an array of user-facing configuration options. Unless otherwise stated, all structures, functions and constants in this page are provided by 86box/device.h
.
device_t
1
Member- Description
1
name
- The device's name, displayed in the user interface.
"Foo-1234"
for example. Suffixes like"(PCI)"
are removed at run-time.
1
internal_name
- The device's internal name, used to identify it in the emulated machine's configuration file.
"foo1234"
for example.
1
flags
- One or more bit flags to indicate the expansion bus(es) supported by the device, for determining
device availability <dev/api/device:Availability>
on the selected machine:DEVICE_ISA
: 8-bit ISA;DEVICE_AT
: 16-bit ISA;DEVICE_EISA
: EISA (reserved for future use);DEVICE_VLB
: VESA Local Bus or proprietary equivalents;DEVICE_PCI
: 32-bit PCI;DEVICE_AGP
: AGP 3.3V;DEVICE_AC97
: AMR, CNR or ACR;DEVICE_PCJR
: IBM PCjr;DEVICE_PS2
: IBM PS/1 or PS/2;DEVICE_MCA
: IBM Micro Channel Architecture;DEVICE_CBUS
: PC-98 C-BUS (reserved for future use);DEVICE_COM
: serial port (reserved for future use);DEVICE_LPT
: parallel port (reserved for future use).
1
local
- 32-bit value which can be read from this structure by the
init
callback. Use this value to tell different subtypes of the same device, for example.
1
init
Function called whenever this device is initialized, either from starting 86Box or from a hard reset. Can be
NULL
, in which case the opaque pointer passed to other callbacks will be invalid. Takes the form of:void *init(const struct device_t *info)
info
: pointer to thisdevice_t
structure;- Return value: opaque pointer passed to the other callbacks below, usually a pointer to the device's
state structure <dev/api/device:State structure>
.
1
close
Function called whenever this device is de-initialized, either from closing 86Box or from a hard reset. Can be
NULL
. Takes the form of:void close(void *priv)
priv
: opaque pointer previously returned byinit
.
1
reset
Function called whenever this device undergoes a soft reset. Can be
NULL
. Takes the form of:void reset(void *priv)
priv
: opaque pointer previously returned byinit
.
2
unionavailable
Function called whenever this device's availability is being checked. Can be
NULL
, in which case the device will always be available. Takes the form of:int available()
- Return value:
1
if the device is available for selection, or0
if it is unavailable (due to missing ROMs, for example).
- Return value:
poll
Function called whenever the mouse position is updated. Valid for mouse devices only. Takes the form of:
int poll(int x, int y, int z, int b, void *priv)
x
andy
: relative mouse movement coordinates (signed);z
: relative scroll wheel movement coordinate (signed);b
: button state: bit 0 (0x1
) set if left button pressed, bit 1 (0x2
) set if right button pressed, bit 2 (0x4
) set if middle button pressed;priv
: opaque pointer previously returned byinit
;- Return value:
0
if the change was processed, or any other value otherwise.
register_pci_slot
- Reserved for future use.
1
speed_changed
Function called whenever the emulated CPU clock speed is changed. Can be
NULL
. Timer intervals (when using the undocumented legacy timer API) and anything else sensitive to the CPU clock speed should be updated in this callback. Takes the form of:void speed_changed(void *priv)
priv
: opaque pointer previously returned byinit
.
1
force_redraw
Function called whenever the emulated screen has to be fully redrawn. Can be
NULL
. Only useful for video cards. Takes the form of:void force_redraw(void *priv)
priv
: opaque pointer previously returned byinit
.
1
config
- Array of
device configuration options <dev/api/device:Configuration>
, orNULL
if no options are available.
Most devices need a place to store their internal state. We discourage the use of global structures, and instead recommend allocating a state structure dynamically in the init
callback and freeing it in the close
callback.
Code example: allocating and deallocating a state structure
#include <86box/device.h>
typedef struct {
uint32_t type; /* example: copied from device_t.local */
uint8_t regs[256]; /* example: 256*8-bit registers */
} foo_t;
static void *
foo_init(const device_t *info)
{
/* Allocate the device state structure. */
foo_t *dev = (foo_t *) malloc(sizeof(foo_t));
memset(dev, 0, sizeof(foo_t)); /* blank structure */
/* Do whatever you want. */
dev->type = info->local; /* copy device_t.local value */
/* Return a pointer to the state structure. */
return dev;
}
static void
foo_close(void *priv)
{
/* Get the device state structure. */
foo_t *dev = (foo_t *) priv;
/* Do whatever you want, then deallocate the state structure. */
free(dev);
}
const device_t foo1234_device = {
.name = "Foo-1234",
.internal_name = "foo1234",
.flags = DEVICE_AT, /* 16-bit ISA */
.local = 1234,
.init = foo_init,
.close = foo_close,
/* ... */
};
const device_t foo4321_device = {
.name = "Foo-4321",
.internal_name = "foo4321",
.flags = DEVICE_PCI, /* 32-bit PCI */
.local = 4321, /* different device subtype */
.init = foo_init,
.close = foo_close,
/* ... */
};
New devices must be registered before they can be selected by the user. This is usually accomplished by adding one or more device_t
pointers to the device table for the device's class:
- Video cards:
video_cards
insrc/video/vid_table.c
- Sound cards:
sound_cards
insrc/sound/sound.c
- Network cards:
net_cards
insrc/network/network.c
- Parallel port devices:
lpt_devices
insrc/lpt.c
- Hard disk controllers:
controllers
insrc/disk/hdc.c
- Floppy disk controllers:
fdc_cards
insrc/floppy/fdc.c
- SCSI controllers:
scsi_cards
insrc/scsi/scsi.c
- ISA RTC cards:
boards
insrc/device/isartc.c
- ISA memory expansion cards:
boards
insrc/device/isamem.c
Devices not covered by any of the above classes may require further integration through modifications to the user interface and configuration loading/saving systems.
A device will be available for selection by the user if these criteria are met:
- The device is
registered <dev/api/device:Registration>
, so that the user interface knows about it; - The selected machine has any of the expansion buses specified in the device's
flags
; - The device's
available
callback returns1
to indicate the device is available (this will always be true if theavailable
callback function isNULL
).
The available
callback can be used to verify the presence of ROM files if any ROMs are required by the device.
Code example: available
checking for the presence of a ROM
#include <86box/device.h>
#include <86box/rom.h>
static int
foo1234_available()
{
return rom_present("roms/scsi/foo/foo1234.bin");
}
const device_t foo1234_device = {
/* ... */
{ .available = foo1234_available }, /* must have brackets due to the union */
/* ... */
};
Devices can have any number of user-facing configuration options, usually accessed through the Configure button next to the selection box for the device's class:
All option types currently configurable through the user interface.These options are stored in the emulated machine's configuration file, in a section identified by the device's name
:
[Foo-1234]
selection = 0
hex16 = 0220
hex20 = D8000
fname = D:/VMs/86Box/86Box.exe
binary = 1
spinner = 1234
midi_out = 0
midi_in = 0
Configuration options can be specified in the config
member of device_t
, as a pointer to a const
array of device_config_t
objects terminated by an object of type
CONFIG_END
.
Code example: device configuration options
#include <86box/device.h>
static const device_config_t foo_config[] = {
{ "selection", "Selection", CONFIG_SELECTION, "", 5, "", { 0 },
{
{ "IRQ 5", 5 },
{ "IRQ 7", 7 },
{ "" }
}
},
{ "hex16", "16-bit hex", CONFIG_HEX16, "", 0x220, "", { 0 },
{
{ "0x220", 0x220 },
{ "0x330", 0x330 },
{ "" }
}
},
{ "hex20", "20-bit hex", CONFIG_HEX20, "", 0xd8000, "", { 0 },
{
/* While the memory *segment* is displayed to the user, we store the
*linear* (segment << 4) base address in the configuration file. */
{ "D800h", 0xd8000 },
{ "DC00h", 0xdc000 },
{ "" }
}
},
{ "string", "String", CONFIG_STRING, "Default" },
{ "fname", "Filename", CONFIG_FNAME, "", 0, "File type (*.foo)|*.foo|Another file type (*.bar)|*.bar" },
{ "binary", "Binary", CONFIG_BINARY, "", 1 /* checked by default */ },
{ "int", "Integer", CONFIG_INT, "", 1234 },
{ "spinner", "Spinner", CONFIG_SPINNER, "", 1234, "", { 1204, 1294, 10 } },
{ "mac", "MAC address", CONFIG_MAC, "", 0 },
{ "midi_out", "MIDI output", CONFIG_MIDI_OUT, "", 0 },
{ "midi_in", "MIDI input", CONFIG_MIDI_IN, "", 0 },
{ "", "", CONFIG_END }
};
const device_t foo_device = {
/* ... */
.config = foo_config
};
device_config_t
- Member
- Description
name
- Internal name for this option, used to identify it in the emulated machine's configuration file.
description
- Description for this option, displayed in the user interface.
type
- One of the following option types:
CONFIG_SELECTION
: combobox containing a list of values specified by theselection
member;CONFIG_HEX16
: combobox containing a list of 16-bit hexadecimal values (useful for ISA I/O ports) specified by theselection
member;CONFIG_HEX20
: combobox containing a list of 20-bit hexadecimal values (useful for ISA memory addresses) specified by theselection
member;CONFIG_STRING
: arbitrary text string entered by the user, currently not visible nor configurable in the user interface;CONFIG_FNAME
: arbitrary file path entered by the user directly or through a file selector button;CONFIG_BINARY
: checkbox;CONFIG_INT
: arbitrary integer number, currently not visible nor configurable in the user interface;CONFIG_SPINNER
: arbitrary integer number entered by the user directly or through up/down arrows, within a range specified by thespinner
member;CONFIG_MAC
: last 3 octets of a MAC address, currently not visible nor configurable in the user interface;CONFIG_MIDI_OUT
: combobox containing a list of system MIDI output devices;CONFIG_MIDI_IN
: combobox containing a list of system MIDI input devices;CONFIG_END
: mandatory terminator to indicate the end of the option list.
default_string
- Default string value for a
CONFIG_STRING
option. Can be""
if not applicable.
default_int
- Default integer value for a
CONFIG_HEX16
,CONFIG_HEX20
,CONFIG_BINARY
,CONFIG_INT
orCONFIG_SPINNER
option. Can be0
if not applicable.
file_filter
File type filter for a
CONFIG_FNAME
option. Can be""
if not applicable. Must be specified in Windowsdescription|mask|description|mask...
format, for example:"Raw image (*.img)|*.img|Virtual Hard Disk (*.vhd)|*.vhd"
spinner
device_config_spinner_t
sub-structure containing the minimum/maximum/step values for aCONFIG_SPINNER
option. Can be{ 0 }
if not applicable.- Member
- Description
min
- Minimum selectable value.
max
- Maximum selectable value.
step
- Units to be incremented/decremented with the arrow buttons. Note that the user can still type in arbitrary numbers that are within
min
andmax
but not aligned tostep
.
selection
Array of
device_config_selection_t
sub-structures containing the choices for aCONFIG_SELECTION
,CONFIG_HEX16
orCONFIG_HEX20
option. Can be{ 0 }
if not applicable. Must be terminated with an object with adescription
of""
.- Member
- Description
description
- Description for this choice, displayed in the user interface.
value
- Integer value corresponding to this choice, used to identify it in the emulated machine's configuration file.
Configured option values can be read from within the device's init
callback with the device_get_config_*
functions. These functions automatically operate in the context of the device currently being initialized.
Note
device_get_config_*
functions should never be called outside of a device's init
callback. You are responsible for reading the options' configured values in the init
callback and storing them in the device's state structure <dev/api/device:State structure>
if necessary.
device_get_config_string
- Parameter
- Description
name
- The option's
name
. Accepted option types areCONFIG_STRING
andCONFIG_FNAME
.
- Return value
- The option's configured string value, or its
default_string
if no value is present. Note that aconst char *
is returned.
device_get_config_int
/ device_get_config_hex16
/ device_get_config_hex20
- Parameter
- Description
name
- The option's
name
. Accepted option types are:device_get_config_int
:CONFIG_SELECTION
,CONFIG_BINARY
,CONFIG_INT
,CONFIG_SPINNER
,CONFIG_MIDI_OUT
,CONFIG_MIDI_IN
device_get_config_hex16
:CONFIG_HEX16
device_get_config_hex20
:CONFIG_HEX20
- Return value
- The option's configured integer value (
CONFIG_BINARY
returns 1 if checked or 0 otherwise), or itsdefault_int
if no value is present.
device_get_config_int_ex
/ device_get_config_mac
- Parameter
- Description
name
- The option's
name
. Accepted option types are:device_get_config_int_ex
:CONFIG_SELECTION
,CONFIG_BINARY
,CONFIG_INT
,CONFIG_SPINNER
,CONFIG_MIDI_OUT
,CONFIG_MIDI_IN
device_get_config_mac
:CONFIG_MAC
dflt_int
- The default value to return if no configured value is present.
- Return value
- The option's configured integer value (
CONFIG_BINARY
returns 1 if checked or 0 otherwise), ordflt_int
if no value is present.