Drivers Bochs

This file is intended for programmers who would like to port the soundoutput routines to their platform. It gives a short outline what serviceshave to be provided.

You should also have a look at the exisiting files, SOUNDLOW.CC,SOUNDMOD.CC and e.g. SOUNDLNX.CC for Linuxor SOUNDWIN.CC for Windows and their respective header filesto get an idea about how these things really work.

2.9.1. Files

The main include file for a lowlevel sound driver is iodev.h.It has all definitions for the system-independent functions that a sound driveruses. The sound driver also needs to include soundlow.h forthe definitions of the base classes bx_sound_lowlevel_c,bx_soundlow_waveout_c, bx_soundlow_wavein_cand bx_soundlow_midiout_c.

Bochs Sourceforge.net site revealed that the version of Bochs I was using had a bug in the serial driver (a fix is apparently in the current CVS tree). So I rebooted Windows under Bochs in safe mode and disabled the serial device. That allowed me to continue with the Windows configuration. Here is version 0.5b, with some bugfixes. This version is to be included in Bochs 2.2. 2005-03-07: vruppert: Version 0.5a of the LGPL'd VGABios with Cirrus support for Bochs and Qemu is available now. It will be included in the first pre-release of Bochs 2.2. 2003-11-06: cbothamy: Version 0.4c is a bugfix release. 2003-11-04: cbothamy. Bosch Impact Drivers at Total Tools. 80+ stores nationwide & access to over 60,000 Tools online. Every Tool, Every Trade. Bochs is first emulator which allowed me to let Windows 98 SE run on my Windows 10 AMD Ryzen 5 3600 machine, others crash. Volker Ruppert - 2020-10-03 The release binaries are compiled with Cirrus support. For compiling with Cirrus support you can use the shortcut script for your platform (e.g.conf.linux or.conf.win32-cygwin). Download the latest Bochs installer for Windows. A Windows 98 CD-ROM or an ISO image of a CD Creating a Hard Disk Image First, run the “Disk Image Creation Tool” to create a hard disk image.

Additionally, every output driver will have an include file, which should beincluded on top of soundmod.cc to allow the emulatorto use that driver. The code to initialize the object for the selected driverscan be found in that file, so a soundcard emulation does not need to includethe specific driver headers.

To actually make the emulator use any specific driver as the default,BX_SOUND_LOWLEVEL_NAME has to be set to the name of therespective driver.

Note that if your class contains any system-specific statements,include-files and so on, you should enclose both the include-file andthe CC-file in an #if defined (OS-define) construct.Also don't forget to add your file to the list of lowlevel sound objectfiles (SOUNDLOW_OBJS) in the file configure.inand to regenerate the configure script,

2.9.2. Defines and strutures

The maximum size of a wave data packet, the return values of the lowlevelfunctions, the structure for the PCM parameters and the default parameterset are also important for the sound driver development. They can be foundin the main include file soundlow.h.

All lowlevel sound methods called from the device code have to return eitherBX_SOUNDLOW_OK if the function was successful, orBX_SOUNDLOW_ERR if not. If any of the initializationfunctions fail, the device emulation should disable the affected feature.

2.9.3. Classes

The following classes are involved with the sound lowlevel interface:

  • bx_soundmod_ctl_c is a pseudo device that is used toinitialize the sound drivers depending on the configuration.

  • bx_sound_lowlevel_c is the base class of thelowlevel sound support. It has methods to return pointers to the objects forthe available services waveout, waveinand midiout. The base class returns NULL for all services.

  • bx_sound_dummy_c is derived from bx_sound_lowlevel_c.It returns vaild pointers for all services, but the output classes are onlyimplemented as stubs and the wavein service returns silence.This 'dummy' driver is used whenever a OS specific driver does not implementall services.

  • bx_soundlow_waveout_c, bx_soundlow_wavein_cand bx_soundlow_midiout_c are the base classes for theservices provided by the Bochs lowlevel sound support. Some methods are stubsand used by the 'dummy' sound driver, others are helper methods and used bythe OS specific implementations derived from these base classes.

  • bx_sound_OS_c is derived from bx_sound_lowlevel_c.It returns vaild pointers for all services it implements for the selectedOS (operating system / library) or NULL for services it doesnot implement. In the second case the Bochs sound init code falls back to the'dummy' driver.

2.9.4. The base class bx_sound_lowlevel_c

The base class for sound lowlevel support is derived from the logfunctionsclass to make the Bochs logging capabilities available in the sound driver code.The constructor of this base class only initializes all pointers to NULL andthe destructor deletes the objects if necessary.

2.9.5. The waveout base class Driversbx_soundlow_waveout_c

The base class for wave output support is also derived from thelogfunctions class. In addition to wave output methodsused from sound devices, it contains everything required for the mixer threadfeature (register PCM sources, convert data formats, start mixer).

The constructor should not allocate the output devices.This should be done in openwaveoutput().

This table shows the waveout class methods, where are they called from andif a platform / library specific implementation is required.

Table 2-4. Waveout methods

MethodCalled fromPlatform codeopenwaveoutput()Sound init codeRequiredset_pcm_params()openwaveoutput() and sendwavepacket()Requiredsendwavepacket()Sound device emulationOptionalget_packetsize()Mixer threadOptionaloutput()Mixer threadRequiredclosewaveoutput()Sound device emulationOptionalregister_wave_callback()openwaveoutput() and sound device emulationOptionalunregister_wave_callback()class destructor and sound device emulationOptionalmixer_common()Mixer threadOptionalconvert_pcm_data()InternalNostart_mixer_thread()InternalNo2.9.5.1. int openwaveoutput(const char *wavedev)

openwaveoutput() is called when the sound output subsysteminitializes. It should do the following:

  • Set up the default PCM parameters for output.

  • Open the given device, and prepare it for wave output.

  • Register the callback function for the PCM buffer queue (sendwavepacket()adds the output to the queue and the mixer thread gets it from there).

  • Start the mixer thread, unless the sound library has it's own one (e.g. SDL).

openwaveoutput() will only be called once, whereasset_pcm_params() is called whenever the PCM sampleratehas been changed.

The parameters are the following:

  • wavedev is the wave output device selected by the user.It is strictly system-dependent. Some sound libraries currently ignore thisvalue and use the default one instead. The value is that of the waveout=deviceconfiguration parameter of the sound bochsrc option.

Note that only one wave output device will be used at any one time.wavedev may not have the same value throughout one session,but it will be closed before it is changed.

2.9.5.2. int set_pcm_params(bx_pcm_param_t *param)

This function should called from openwaveoutput() to initializethe output device with the default parameters and from sendwavepacket()whenever the samplerate has been changed in the emulated sound device.It should do the following:

  • Open the wave output device, unless openwaveoutput() did thatalready.

  • Prepare the device for data and set the device parameters to those givenin the function call.

The parameters are the following:

  • param is a pointer to a structure containing the set ofparameters required to set up a sound device for PCM output.

The members of the structure bx_pcm_param_t are these:

  • samplerate is the desired frequency of theoutput. Because of the capabities of the soundcards, it can have any valuebetween 5000 and 48,000.

  • bits is either 8 or 16, denoting the resolutionof one sample.

  • channels is the number of channels (2 for stereo output,or 1 for mono output.

  • format is a bit-coded value (see below).

  • volume is the output volume to be used by the mixer code.The 16 bit value consists of two 8 bit values for each channel.

Table 2-5. format bits

Bit numberMeaning 0 (LSB)

0: unsigned data

1: signed data

1..6 Type of codec (see below) 7

0: no reference byte

1: with reference byte

8..x reserved (0)

Table 2-6. codecs

ValueMeaning 0 PCM (raw data) 1 reserved 2 2-bit ADPCM (Creative Labs format) 3 2.4-bit (3-bit) ADPCM (Creative Labs format) 4 4-bit ADPCM (Creative Labs format)

Other codecs are not supported by the SB hardware. In fact, most applications willtranslate their data into raw data, so that in most cases the codec will be zero.

The number of bytes per sample can be calculated from this as (bits / 8) * channels.

2.9.5.3. int sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *src_param)Bochs

This function is called whenever a data packet of at mostBX_SOUNDLOW_WAVEPACKETSIZE is ready at the soundcardemulation. It should then do the following:

  • Add this wave packet to the waveout buffer chain after converting to 16 bit signedlittle endian. If the samplerate has been changed set_pcm_params()should be called to update the sound hardware settings.

Parameters:

  • length is the number of data bytes inthe data stream. It will never be larger than BX_SOUNDLOW_WAVEPACKETSIZE.

  • data is the array of data bytes.

  • src_param is a pointer to a structure containing the PCM parameters(see above).

The order of bytes in the data stream is the same as that in the Wave file format:

Table 2-7. wave output types

Output typeSequence of data bytes 8 bit mono Sample 1; Sample 2; Sample 3; etc. 8 bit stereo Sample 1, Channel 0; Sample 1, Channel 1; Sample 2, Channel 0; Sample 2, Channel 1; etc. 16 bit mono Sample 1, LSB; Sample 1, MSB; Sample 2, LSB; Sample 2, MSB; etc. 16 bit stereo Sample 1, LSB, Channel 0; Sample 1, MSB, Channel 0; Sample 1, LSB, Channel 1; Sample 1, MSB, Channel 1; etc.

Typically 8 bit data will be unsigned with values from 0 to 255, and16 bit data will be signed with values from -32768 to 32767, although thesoundcard emulations are not limited to this.site.

2.9.5.4. int get_packetsize()

This function is called from the mixer thread to retrieve the size of a wave datapacket based on the current samplerate. By default the packet size is big enoughto send output for 0.1 seconds. If the host sound driver / library uses a differentvalue, this value should be returned with this method.

2.9.5.5. int output(int length, Bit8u data[])

This function is called from the mixer thread to send the mixed PCM output tothe host sound hardware.

Parameters:

  • length is the number of data bytes inthe data stream. It will never be larger than the value returned from get_packetsize.

  • data is the array of data bytes.

Bochs drivers2.9.5.6. int closewaveoutput()

This function is currently only called from the soundcard emulation if the 'file'driver is used. This makes the runtime change of the output file possible.By default this method does nothing and the wave output device is closed in thedestructor of the specific class.

2.9.5.7. int register_wave_callback(void *arg, get_wave_cb_t wd_cb)

This function is called from openwaveoutput() to registerthe function to retrieve data from the PCM output buffer chain. Other soundemulation devices (e.g. OPL3, PC speaker) can register a function to poll thedata from the device emulation. The return value is the ID of the registeredfunction and it is usually used to unregister the source.

Parameters:

  • arg is the pointer to the device emulation object.

  • wd_cb is the pointer to a static function that returnswave data from the device emulation. This function is usually called from themixer_common() method.

Drivers Bochs2.9.5.8. void unregister_wave_callback(int callback_id)

This function is usually called from the destructor of the sound emulationdevice to unregister it's registered function to poll PCM data. If thedriver / library doesn't use the default mixer thread, a specific implementationof this method my be required.

Parameter:

  • callback_id is the ID of the function to unregister.

2.9.5.9. bx_bool mixer_common(Bit8u *buffer, int len)

This is the main wave output mixing function. It is called from the mixerthread, it polls the wave data from all registered sources and it mixes thedata using a simple algorithm (addition and clipping). The return valueindicates whether or not wave data is available for output.

Parameters:

  • buffer is the output buffer for the wave data.

  • len is the maximum length of the output buffer.

2.9.5.10. void convert_pcm_data(Bit8u *src, int srcsize, Bit8u *dst, int dstsize, bx_pcm_param_t *param)

Drivers Boost

This function converts the PCM data sent from the sound device emulation to the16 bit stereo signed little endian format. It should be called in sendwavepacket()after allocating the output buffer in the buffer queue. Future versions mightalso perform resampling here.

Parameters:

  • src is the buffer containing data sent from the sound emulation.

  • srcsize is the amount of wave data to be converted.

  • dst is the buffer for the converted wave data.

  • dstsize is the size of the destination buffer.

  • param is a pointer to the struture containing the formatparameters of the source data.

2.9.5.11. void start_mixer_thread()

This function starts the mixer thread and it should be called in openwaveoutput()unless the sound driver / library has it's own way to do this (e.g. SDL). Thisfunction also initializes the mutex required for locking the mixer thread whenadding data to the buffer chain or unregistering a source.

2.9.6. The wavein base class

Drivers Books

bx_soundlow_wavein_c

The base class for wave input support is also derived from thelogfunctions class. It contains the framework for waveinput (recording) support. The base class is used by the 'dummy' sound driverand returns silence to let the input mechanism of the soundcard emulation work.The soundcard emulator object needs to implement a callback function to notifiesthe emulation about available data. This function usually calls the driver methodto get the wave data packet. The driver objects has a periodic timer with aninterval of 0.1 emulated seconds that is active during recording. The timerhandler processes the wave data recorded with platform or library specificfunction and finally notifies the emulator.

The constructor of the base class only initializes the timer ID. OS specificimplementations should initialize other required members here.

The destructor of the base class only calls stopwaverecord().OS specific implementations should close the input device here if necessary.

2.9.6.1. int openwaveinput(char *device, sound_record_handler_t rh)

openwaveinput() is called when the sound emulation firstreceives a sound recording command. It should do the following:

  • Open the given device, and prepare it for wave input

or

  • Store the device name so that the device can be opened in startwaverecord().

In addition to this the record handler value should be stored and the record timershould be registered. This is the definition of record handler callback function:

openwaveinput() will only be called once, whereasstartwaverecord() is called for every new wave inputcommand to the soundcard emulation. If feasible, it could be useful to openand/or lock the input device in startwaverecord() asopposed to openwaveinput() to ensure that it can be usedby other applications while Bochs doesn't need it.

The parameters are the following:

  • device is the wave device selected by the user. It isstrictly system-dependent. The value is that of the wavein=deviceconfiguration parameter of the sound bochsrc option.

  • rh is a pointer to the record handler method of the soundemulation. When sound recording is active, this handler is called periodicly tonotify the sound emulation about newly available data.

Note that only one wave input device will be used at any one time.device may not have the same value throughout one session,but it will be closed before it is changed.

2.9.6.2. int startwaverecord(bx_pcm_param_t *param)

This method receives a pointer to the required PCM parameters (samplerate,data format) as the argument and it should set up the input device for recording,calculate the size of the recording packet for 0.1 second and start the recordtimer.

2.9.6.3. int getwavepacket(int length, Bit8u data[])

This method is called from the record handler method of the sound emulation deviceto retrieve the recorded wave data packet.

2.9.6.4. int stopwaverecord()

This method is called to stop the wave recording. It deactivates the timer thatcalls the method to perform the recording.

2.9.7. The midiout base class bx_soundlow_midiout_c

The base class for MIDI output support is also derived from thelogfunctions class.

OS specific implementations should initialize required members in the constructor.

The destructor of the base class only calls closemidioutput().OS specific implementations should close the input device here if necessary.

2.9.7.1. int openmidioutput(char *device)
  • openmidioutput() is called when the first midi output starts.It is only called if the midi output to the driver is active (midimode 1). It shouldprepare the given MIDI hardware for receiving midi commands.

Description of the parameters:

  • mididev is a system-dependent variable.The value is that of the midiout=deviceconfiguration parameter of the sound bochsrc option.

  • Note that only one midi output device will be used at any one time.devicemay not have the same value throughout one session, but it will be closedbefore it is changed.

2.9.7.2. int midiready()

midiready() is called whenever the applications asks if themidi queue can accept more data.

Return values:

  • BX_SOUNDLOW_OK if the midi output device is ready.

  • BX_SOUNDLOW_ERR if it isn't ready.

Note: midiready() will be called a few timesbefore the device is opened. If this is the case, it shouldalways report that it is ready, otherwise the application (not Bochs)will hang.

2.9.7.3. int sendmidicommand(int delta, int command, int length, Bit8u data[])Drivers Bochs

sendmidicommand()is called whenever a complete midi command hasbeen written to the emulator. It should then send the given midi command to the midi hardware.It will only be called after the midi output has been opened. Note thatif at all possible it should not wait for the completion of the commandand instead indicate that the device is not ready during the executionof the command. This is to avoid delays in the program while it isgenerating midi output.

Description of the parameters:

  • delta is the number of delta ticks thathave passed since the last command has been issued. It is always zero forthe first command. There are 24 delta ticks per quarter, and 120 quartersper minute, thus 48 delta ticks per second.

  • command is the midi command byte (sometimescalled status byte), in the usual range of 0x80..0xff. For more informationplease see the midi standard specification.

  • length is the number of data bytes thatare contained in the data structure. This does not include the statusbyte which is not replicated in the data array. It can only be greaterthan 3 for SysEx messages (commands 0xF0 and 0xF7)

  • data[] is the array of these data bytes,in the order they have in the standard MIDI specification.Note, it might be NULL if length0.

Drivers Boost 8

2.9.7.4. int closemidioutput()

closemidioutput() is called before shutting down Bochs orwhen theemulator gets the stop_output command through the emulator port.After this, no more output will be necessary until openmidioutput()is called again, but midiready() might still be called. It shoulddo the following:

Drivers Boos

  • Wait for all remaining messages to be completed

  • Reset and close the midi output device

Bochs Drivers

PrevHomeNextSound Blaster 16 EmulationUpHarddisk Images based on redologs