999 lines
33 KiB
Plaintext
999 lines
33 KiB
Plaintext
<!--
|
|
================================================================
|
|
doc/docbook/development/development.dbk
|
|
$Id: development.dbk,v 1.6 2002-11-19 14:33:26 ndavidg Exp $
|
|
|
|
This is the top level file for the Bochs Developers Manual.
|
|
================================================================
|
|
-->
|
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
|
|
|
|
<!-- include definitions that are common to all bochs documentation -->
|
|
<!ENTITY % bochsdefs SYSTEM "../include/defs.sgm">
|
|
%bochsdefs;
|
|
|
|
]>
|
|
<book>
|
|
<bookinfo>
|
|
<title>Bochs Developers Guide</title>
|
|
<authorgroup>
|
|
<author><firstname>Kevin</firstname><surname>Lawton</surname></author>
|
|
<author><firstname>Bryce</firstname><surname>Denney</surname></author>
|
|
<editor><firstname>Michael</firstname><surname>Calabrese</surname></editor>
|
|
<editor><firstname>Vasudeva</firstname></editor>
|
|
</authorgroup>
|
|
</bookinfo>
|
|
|
|
<!-- *************************************************************** -->
|
|
<chapter><title>Resources for developers</title>
|
|
<para>
|
|
The development guide describes resources that are intended for developers
|
|
in particular. Many Bochs resources are also covered in the User Guide,
|
|
including compile instructions, bochsrc options, how to find the mailing
|
|
lists, etc.
|
|
</para>
|
|
|
|
|
|
<section><title>Setting up CVS write access</title>
|
|
<para>
|
|
If you are an official SourceForge developer, then you can use CVS with write
|
|
access. The CVS contains the most recent copy of the source code, and with
|
|
write access you can upload any changes you make to the CVS server for others
|
|
to use. A few extra steps are required the first time you use CVS write
|
|
access.
|
|
</para>
|
|
|
|
<section><title>Install ssh and cvs</title>
|
|
<para>
|
|
First you need to install both cvs (Concurrent Version System) and ssh (Secure
|
|
Shell). These are already installed on many UNIX systems and also Cygwin
|
|
(win32 platform). If not, you can install binaries or compile cvs and ssh
|
|
yourself. The links below should help you get going.
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem> <para> CVS software and instructions are available at <ulink url="http://www.cvshome.org">www.cvshome.org</ulink>. </para> </listitem>
|
|
<listitem> <para> A free version of secure shell called OpenSSH is at <ulink url="http://www.openssh.org">www.openssh.org</ulink>. </para> </listitem>
|
|
<listitem> <para> OpenSSH requires a library called OpenSSL from <ulink url="http://www.openssl.org">www.openssl.org</ulink>. Be sure to install OpenSSL before trying to compile OpenSSH. </para> </listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section><title>ssh to cvs.sf.net</title>
|
|
<para>
|
|
Next, you need to use secure shell to connect to cvs.sf.net. This step is a
|
|
little strange, because you can't actually log in and get a shell prompt. All
|
|
that will happen, when you get the username and password right, is that it
|
|
will create a home directory on that machine for you. That's it! If you try
|
|
it again, it will say "This is a restricted Shell Account. You cannot execute
|
|
anything here." At this point, you've succeeded and you never have to do
|
|
this step again, ever.
|
|
|
|
<screen>
|
|
ssh <replaceable>sfusername</replaceable>@cvs.sf.net
|
|
</screen>
|
|
</para>
|
|
|
|
<para>
|
|
Replace <replaceable>sfusername</replaceable> with your Source Forge username,
|
|
of course. The first time, you will probably get a message like
|
|
<screen>
|
|
The authenticity of host 'cvs.sf.net' can't be established.
|
|
Are you sure you want to continue?</screen>
|
|
|
|
Just type yes. When it asks for a password, be sure to type your source
|
|
forge password. If you have trouble logging in, be sure to use your SOURCE
|
|
FORGE username and password in the ssh line, which isn't necessarily the same
|
|
as your local username and password. Add the "-v" option to ssh to see more
|
|
information about what is failing. If you have ssh version 2, it is possible
|
|
that you might need to add "-1" to the ssh command to force it to use the
|
|
version 1 protocol. </para> </section>
|
|
|
|
<section><title>Set CVS_RSH environment variable to ssh</title>
|
|
<para>
|
|
Every time you connect to the Source Forge CVS server (including cvs update,
|
|
stat, commit, etc.), you must set the CVS_RSH environment variable to ssh. So
|
|
just take the time now to add one of these lines to your .bashrc/.cshrc, so
|
|
that the CVS_RSH setting will be there every time you log in.
|
|
</para>
|
|
|
|
<screen>
|
|
export CVS_RSH=ssh (bash syntax)
|
|
setenv CVS_RSH ssh (csh syntax)
|
|
</screen>
|
|
</section> <!--end of "Set environment variable"-->
|
|
|
|
<section><title>cvs checkout</title>
|
|
<para>
|
|
Finally, you should be able to do the checkout! If you already have a bochs
|
|
subdirectory directory, move it out of the way because the checkout will
|
|
overwrite it.
|
|
</para>
|
|
|
|
<screen>
|
|
export CVSROOT=":ext:<replaceable>sfusername</replaceable>@cvs.bochs.sourceforge.net:/cvsroot/bochs"
|
|
cvs -z3 checkout bochs
|
|
<replaceable>sfusername</replaceable>@cvs.sf.net's password: <replaceable><--type your password</replaceable>
|
|
</screen>
|
|
|
|
<para>
|
|
In the CVSROOT variable, replace <replaceable>sfusername</replaceable> with your SF username. There's
|
|
no need to add CVSROOT to your rc files because CVS will remember it
|
|
after the checkout. The -z3 (optional) just adds some compression to make
|
|
the checkout go faster. Once all the files have been downloaded, you will
|
|
have a bochs directory which is checked out with write access!
|
|
</para>
|
|
</section> <!-- end cvs checkout -->
|
|
|
|
</section> <!-- end setting up cvs write access -->
|
|
|
|
<section><title>Using CVS write access</title>
|
|
|
|
<section><title>Checking in files</title>
|
|
<para>
|
|
Once you have a bochs directory with cvs write access, you can compile the
|
|
files, edit them, test them, etc. See the documentation section, "Tracking
|
|
the source code with CVS" for more info on CVS, in the User Manual.
|
|
(FIXME: add cross reference) But what's new and different is that you can now
|
|
do cvs commits. When a file is all fixed and ready to share with the rest of
|
|
the world, you run a commit command to upload your version to the server.
|
|
First, it's good to do a cvs update to make sure nobody else has changed it
|
|
since you downloaded it last.
|
|
</para>
|
|
|
|
<screen>
|
|
$ cvs update file.cc
|
|
<replaceable>sfusername</replaceable>@cvs.sf.net's password: <replaceable><--type your password</replaceable>
|
|
$ cvs commit file.cc
|
|
<replaceable>sfusername</replaceable>@cvs.sf.net's password: <replaceable><--type your password</replaceable>
|
|
[editor opens. type log message, save, and exit.]
|
|
</screen>
|
|
|
|
<para>
|
|
When CVS starts an editor, The default is usually vi. If you want a different
|
|
editor, set the EDITOR environment variable to the name of your preferred
|
|
editor. When you're done, just save the file and quit the editor. Unless
|
|
there's some problem, you will see a message that says what the new revision
|
|
number for the file is, and then "done". If while you're editing the log
|
|
message, you decide that you don't want to commit after all, don't save the
|
|
file. Quit the editor, and when it asks where the log message went, tell it
|
|
to abort.
|
|
</para>
|
|
|
|
<para>
|
|
Here is an example of a successful checkin:
|
|
|
|
<screen>
|
|
$ cvs commit misc.txt
|
|
<replaceable>sfusername</replaceable>@cvs.sf.net's password: <replaceable><--type your password</replaceable>
|
|
[edit log msg]
|
|
Checking in misc.txt;
|
|
/cvsroot/bochs/bochs/doc/docbook/misc.txt,v <-- misc.txt
|
|
new revision: 1.6; previous revision: 1.5
|
|
done
|
|
</screen>
|
|
|
|
And here is an aborted one:
|
|
|
|
<screen>
|
|
$ cvs commit misc.txt
|
|
<replaceable>sfusername</replaceable>@cvs.sf.net's password: <replaceable><--type your password</replaceable>
|
|
[quit editor without saving]
|
|
Log message unchanged or not specified
|
|
a)bort, c)ontinue, e)dit, !)reuse this message unchanged for remaining dirs
|
|
Action: a
|
|
cvs [commit aborted]: aborted by user
|
|
</screen>
|
|
|
|
</para>
|
|
</section> <!--end of "Checking in Files" -->
|
|
|
|
</section> <!--end of "Using CVS write access" -->
|
|
|
|
<section><title>SourceForge bug, feature, and patch trackers</title>
|
|
<para>
|
|
&FIXME;
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>Ideas for other sections</title>
|
|
<para>
|
|
<screen>
|
|
Ideas:
|
|
- how to browse code with cvsweb
|
|
- how to find an identifier, variable, or specific text in the code
|
|
- write access CVS (must be an official developer on SF)
|
|
- how to make patches with CVS
|
|
</screen>
|
|
</para>
|
|
</section>
|
|
|
|
</chapter>
|
|
|
|
<chapter><title>About the code</title>
|
|
|
|
<section><title>How to add keymapping in a GUI client</title>
|
|
<para>
|
|
Christophe Bothamy, wrote the keymapping code for Bochs, provided these
|
|
instructions to help developers to add keymapping to a GUI.
|
|
</para>
|
|
|
|
<screen>
|
|
Bochs creates a bx_keymap_c object named bx_keymap.
|
|
This object allows you to :
|
|
- load the configuration specified keymap file
|
|
- get the translated BX_KEY_* from your GUI key
|
|
|
|
You have to provide a translation function from string to your Bit32u key
|
|
constant. Casting will be necessary if your key constants are not Bit32u typed.
|
|
The function must be "static Bit32u (*)(const char *)" typed, and must return
|
|
BX_KEYMAP_UNKNOWN if it can not translate the parameter string.
|
|
|
|
What you have to do is :
|
|
- call once "void loadKeymap(Bit32u (*)(const char*))",
|
|
providing your translation function, to load the keymap
|
|
- call "Bit32u getBXKey(Bit32u)" that returns the BX_KEY_*
|
|
constant, for each key you want to map.
|
|
|
|
The file gui/x.cc implements this architecture, so you can refer to it
|
|
as an example.
|
|
</screen>
|
|
|
|
</section>
|
|
|
|
<section><title>Directory Structure</title>
|
|
<para>
|
|
&FIXME;
|
|
cpu directory does this, iodev does that, gui does that
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>Configure Scripting</title>
|
|
<para>
|
|
&FIXME;
|
|
configure script, makefiles, header files
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>Log Functions</title>
|
|
<para>
|
|
&FIXME;
|
|
log functions: what is a panic, what is an error, etc.
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>Emulator Objects</title>
|
|
<para>
|
|
&FIXME;
|
|
objects that do all the work (cpu, mem)
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>timers</title>
|
|
<para>
|
|
&FIXME;
|
|
</para>
|
|
</section>
|
|
|
|
<section> <!-- start of SB16 section-->
|
|
|
|
<title>Sound Blaster 16 Emulation</title>
|
|
<para>
|
|
Sound Blaster 16 (SB16) emulation for Bochs was written and donated by
|
|
Josef Drexler, who has a
|
|
<ulink url="http://publish.uwo.ca/~jdrexler/bochs/">web page</ulink> on the topic.
|
|
The entire set of his SB16 patches have been integrated into
|
|
Bochs, however, so you can find everything you need here.
|
|
</para>
|
|
|
|
<para>
|
|
SB16 Emulation has been tested with several soundcards and versions of Linux. Please give
|
|
Josef <ulink url="mailto:jdrexler@julian.uwo.ca">feedback</ulink> on
|
|
whether is does or doesn't work on your combination of software and hardware.
|
|
</para>
|
|
|
|
<section><title>How well does it work?</title>
|
|
<para>
|
|
Right now, MPU401 emulation is next to perfect. It supports UART
|
|
and SBMIDI mode, because the SB16's MPU401 ports can't do anything else as well.
|
|
</para>
|
|
|
|
<para>
|
|
The digital audio basically works, but the emulation is too slow for fluent
|
|
output unless the application doesn't do much in the background (or the
|
|
foreground, really). The sound tends to looping or crackle on slower
|
|
computer, but the emulation appears to be correct. Even a MOD
|
|
player works, although only for lower sampling speeds.
|
|
</para>
|
|
<para>
|
|
Also, the MIDI data running through the MPU401 ports can be written
|
|
into a SMF, that is the standard midi file. The wave output
|
|
can be written into a VOC file, which has a format defined by
|
|
Creative Labs. This file format can be converted to WAV by
|
|
sox for example.
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>Output to a sound card</title>
|
|
|
|
<para>
|
|
Output is supported on Linux and Windows 95 at the moment.
|
|
On Linux, the output goes to any file or device. If you have a
|
|
wavetable synthesizer, midi can go to /dev/midi00, otherwise you may need
|
|
a midi interpreter. For example, the midid program from the
|
|
DosEmu project would work. Wave output should go to /dev/dsp.
|
|
These devices are assumed to be OSS devices, if they're not
|
|
some of the ioctl's might fail.
|
|
On Windows, midi and output goes to the midi mapper and the wave mapper,
|
|
respectively. A future version might have selectable output devices.
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>Installation on Linux</title>
|
|
|
|
<para>
|
|
<emphasis>Prerequisites:</emphasis>
|
|
</para>
|
|
|
|
<para>
|
|
A wavetable synthesizer on /dev/midi00 and a working /dev/dsp if you want real time music and sound, otherwise output to midi and wave files is also possible.
|
|
Optionally, you can use a software midi interpreter, such as the midid program from the DosEmu project instead of /dev/midi00.
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>Configuring bochs</title>
|
|
|
|
<para>
|
|
There are a few values in config.h that are relevant to the sound functions.
|
|
Edit config.h after running configure, but before compiling.
|
|
</para>
|
|
|
|
<para>
|
|
BX_USE_SB16_SMF should be 1 unless you intend to have several sound cards
|
|
running at the same time.
|
|
</para>
|
|
|
|
<para>
|
|
BX_USE_SOUND_VIRTUAL can be 0 or 1, and determines whether the output class
|
|
uses virtual functions or not. The former is more versatile and allows to
|
|
select the class at runtime (not supported at the moment), while the latter
|
|
is slightly faster.
|
|
</para>
|
|
|
|
<para>
|
|
BX_SOUND_OUTPUT_C is the name of the class used for output. The default is
|
|
to have no output functions, so you need to change this if you want any sound.
|
|
The following are supported at the moment:
|
|
</para>
|
|
|
|
<programlisting>
|
|
bx_sound_linux_c for output to /dev/dsp and /dev/midi00 on Linux
|
|
(and maybe other OSes that use the OSS driver)
|
|
bx_sound_windows_c for output to the midi and wave mapper of
|
|
Windows 3.1 and higher.
|
|
bx_sound_output_c for no output at all.
|
|
</programlisting>
|
|
|
|
<para>
|
|
Setup the SB16 emulation in your .bochsrc, according to instructions
|
|
in that file.
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>Runtime configuration</title>
|
|
|
|
<para>
|
|
The source for the SB16CTRL program that is used to modify
|
|
the runtime behaviour of the SB16 emulator is included in
|
|
misc/sb16. You can compile it or download the
|
|
<ulink url="http://publish.uwo.ca/~jdrexler/bochs/">executable</ulink>.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>misc/sb16/</emphasis> contains a C program that can be run inside the emulator, and the
|
|
executable for DOS. It currently supports the following commands:
|
|
</para>
|
|
|
|
<para>
|
|
&FIXME; number, six numbers, some numbers, and filename below should be in tags
|
|
</para>
|
|
|
|
<programlisting>
|
|
-i number: shows the selected emulator info string,
|
|
e.g. sb16ctrl -i 3 to show how many patch translations are active
|
|
|
|
-t six numbers: loads a translation into the translation table. The
|
|
numbers are:
|
|
OldBankMSB,OldBankLSB,OldProgram,NewBankMSB,NewBankLSB,NewProgram
|
|
All values can be 0..127 or 255. 255 for Old values means <emphasis>match
|
|
any</emphasis> and for New values means <emphasis>don't change</emphasis>,
|
|
e.g. sb16ctrl -t 255,255,0,255,255,32
|
|
to change patch 0 (Piano) to patch 32 (Acoustic Bass)
|
|
|
|
-r: Reset the patch translation table
|
|
e.g. sb16ctrl -r
|
|
|
|
-m some numbers: Upload the given numbers to the midi output device. Note
|
|
that it should be a complete midi message, and also that it is
|
|
subject to patch translation.
|
|
e.g. sb16ctrl -m 0x80,64,0
|
|
to send a note-off message to channel 0.
|
|
|
|
-f filename: Reads in a file and executes the commands in it. These have
|
|
the same format as the above commands, except that they don't have
|
|
the dash "-" in front of them.
|
|
Comment lines are supported and start with a hash sign "#".
|
|
|
|
-h: Show a brief summary of the commands.
|
|
</programlisting>
|
|
|
|
<para>
|
|
All numbers can be valid parameters to the strtol() function, so hex and
|
|
octal notation is fine. They have to be delimited by either commas "," or
|
|
slashes "/", spaces are not allowed.
|
|
</para>
|
|
|
|
<para>
|
|
The command line can have any number of commands. However, if none are given,
|
|
"-f -" is assumed, which means commands are taken from stdin.
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>Features planned for the future</title>
|
|
<itemizedlist>
|
|
<listitem><para>Ports to more OS's, but I can't do this myself</para></listitem>
|
|
<listitem><para>Finishing the OPL3 FM emulation by translating the music to midi data</para></listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Description of the sound output classes</title>
|
|
|
|
<para>
|
|
This file is intended for programmers who would like to port the sound
|
|
output routines to their platform. It gives a short outline what services
|
|
have to be provided.
|
|
</para>
|
|
<para>
|
|
You should also have a look at the exisiting files, <emphasis>SOUNDLNX.CC</emphasis>
|
|
for Linux and <emphasis>SOUNDWIN.CC</emphasis> for Windows and their respective
|
|
header files to get an idea about how these things really work.
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>Files</title>
|
|
|
|
<para>
|
|
The main include file is <emphasis>bochs.h</emphasis>. It has all definitions
|
|
for the system-independent functions that the SB16 emulation uses, which
|
|
are defined in <emphasis>sb16.h</emphasis>.
|
|
</para>
|
|
|
|
<para>
|
|
Additionally, every output driver will have an include file, which
|
|
should be included at the end of sb16.h to allow the emulator
|
|
to use that driver.
|
|
</para>
|
|
|
|
<para>
|
|
To actually make the emulator use any specific driver,
|
|
<emphasis>BX_SOUND_OUTPUT_C</emphasis> has to be set to the name of the respective
|
|
output class.
|
|
</para>
|
|
|
|
<para>
|
|
Note that if your class contains any system-specific statements,
|
|
include-files and so on, you should enclose both the include-file and
|
|
the CC-file in an <emphasis>#if defined</emphasis> (OS-define) construct.
|
|
Also don't forget to add your file to the object list in
|
|
iodev/Makefile and iodev/Makefile.in.
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>Classes</title>
|
|
|
|
<para>
|
|
The following classes are involved with the SB16 emulation:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
<emphasis>bx_sb16_c</emphasis> is the class containing the emulator itself, that
|
|
is the part acting on port accesses by the application, handling the
|
|
DMA transfers and so on. It also prepares the data for the output
|
|
classes.
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
<emphasis>bx_sound_output_c</emphasis> is the base output class. It has all
|
|
the methods used by the emulator, but only as stubs and does not
|
|
actually produce any output. These methods are then called by
|
|
the emulator whenever output is necessary.
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
<emphasis>bx_sound_OS_c</emphasis> is derived from
|
|
<emphasis>bx_sound_output_c</emphasis>. It contains the code to generate
|
|
output for the <emphasis>OS</emphasis> operating system.
|
|
It is necessary to override all
|
|
the methods defined in the base class, unless virtual functions
|
|
are used. Note that this should remain an option, so try to
|
|
override all methods, even if only as stubs. They should be
|
|
declared <emphasis>virtual</emphasis> if and only if <emphasis>BX_USE_SOUND_VIRTUAL</emphasis>
|
|
is defined, just as in the examples.
|
|
The constructor should call the inherited constructor
|
|
as usual, even though the current constructor does not do
|
|
anything yet.
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
|
|
<section><title>Methods</title>
|
|
<para>
|
|
The following are the methods that the output class has to override.
|
|
All but constructor and destructor have to return either
|
|
<emphasis>BX_SOUND_OUTPUT_OK</emphasis> <emphasis>(0)</emphasis> if the function was successful,
|
|
or <emphasis>BX_SOUND_OUTPUT_ERR</emphasis> <emphasis>(1)</emphasis> if not. If any of the initialization
|
|
functions fail, output to that device is disabled until the emulator is restarted.
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>bx_sound_OS_c(bx_sb16_c*sb16)</title>
|
|
|
|
<para>
|
|
The emulator instantiates the class at the initialization of Bochs.
|
|
</para>
|
|
|
|
<para>
|
|
Description of the parameter:
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
<emphasis>sb16</emphasis> is a pointer to the emulator class.
|
|
This pointer can then be used to access for example the <emphasis>writelog</emphasis> function to generate
|
|
sound-related log messages. Apart from that, no access to the emulator
|
|
should be necessary.
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
The constructor should <emphasis>not</emphasis> allocate the output devices.
|
|
This shouldn't be done until the actual output occurs; in either
|
|
<emphasis>initmidioutput()</emphasis> or <emphasis>initwaveoutput()</emphasis>.
|
|
Otherwise it would be impossible to have two copies of Bochs running
|
|
concurrently (if anybody ever wants to do this).
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section><title>~bx_sound_OS_c()</title>
|
|
|
|
<para>
|
|
The instance is destroyed just before Bochs ends.
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>int openmidioutput(char *device)</title>
|
|
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
<emphasis>openmidioutput()</emphasis> is called when the first midi output starts.
|
|
It is only called if the midi output mode is 1 (midimode 1). It should
|
|
prepare the given MIDI hardware for receiving midi commands.
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
<emphasis>openmidioutput()</emphasis> will always be called before <emphasis>openwaveoutput()</emphasis>,
|
|
and <emphasis>closemidioutput()</emphasis>will always be called before <emphasis>closewaveoutput()</emphasis>, but not in all cases will both functions be called.
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Description of the parameters:</title>
|
|
|
|
<itemizedlist>
|
|
|
|
<listitem><para>
|
|
<emphasis>device</emphasis> is a system-dependent variable.
|
|
It contains the value of the <emphasis>MIDI=device</emphasis> configuration option.
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
Note that only one midi output device will be used at any one time.
|
|
<emphasis>device</emphasis>
|
|
may not have the same value throughout one session, but it will be closed
|
|
before it is changed.
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section><title>int midiready()</title>
|
|
|
|
<para>
|
|
<emphasis>midiready()</emphasis> is called whenever the applications asks if the
|
|
midi queue can accept more data.
|
|
</para>
|
|
|
|
<para>
|
|
Return values:
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
<emphasis>BX_SOUND_OUTPUT_OK</emphasis> if the midi output device is ready.
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
<emphasis>BX_SOUND_OUTPUT_ERR</emphasis> if it isn't ready.
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
<emphasis>Note: </emphasis><emphasis>midiready()</emphasis> will be called a few times
|
|
<emphasis>before</emphasis> the device is opened. If this is the case, it should
|
|
always report that it is ready, otherwise the application (not Bochs)
|
|
will hang.
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>int sendmidicommand(int delta, int command, int length, Bit8u data[])</title>
|
|
|
|
<para>
|
|
<emphasis>sendmidicommand()</emphasis>is called whenever a complete midi command has
|
|
been 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 that
|
|
if at all possible it should not wait for the completion of the command
|
|
and instead indicate that the device is not ready during the execution
|
|
of the command. This is to avoid delays in the program while it is
|
|
generating midi output.
|
|
</para>
|
|
|
|
<para>
|
|
Description of the parameters:
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
<emphasis>delta</emphasis> is the number of delta ticks that
|
|
have passed since the last command has been issued. It is always zero for
|
|
the first command. There are 24 delta ticks per quarter, and 120 quarters
|
|
per minute, thus 48 delta ticks per second.
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
<emphasis>command</emphasis> is the midi command byte (sometimes
|
|
called status byte), in the usual range of 0x80..0xff. For more information
|
|
please see the midi standard specification.
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
<emphasis>length</emphasis> is the number of data bytes that
|
|
are contained in the data structure. This does <emphasis>not</emphasis> include the status
|
|
byte which is not replicated in the data array. It can only be greater
|
|
than 3 for SysEx messages (commands <emphasis>0xF0</emphasis> and <emphasis>0xF7</emphasis>)
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
<emphasis>data[]</emphasis> is the array of these data bytes,
|
|
in the order they have in the standard MIDI specification.
|
|
Note, it might be <emphasis>NULL</emphasis> if length==0.
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
|
|
<section><title>int closemidioutput()</title>
|
|
|
|
<para>
|
|
<emphasis>closemidioutput()</emphasis> is called before shutting down Bochs or
|
|
when the
|
|
emulator gets the <emphasis>stop_output</emphasis> command through the emulator port.
|
|
After this, no more output will be necessary until <emphasis>openmidioutput()</emphasis>
|
|
is called again, but <emphasis>midiready()</emphasis> might still be called. It should do the following:
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
Wait for all remaining messages to be completed
|
|
</para></listitem>
|
|
<listitem><para>
|
|
Reset and close the midi output device
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
|
|
<section><title>int openwaveoutput(char *device)</title>
|
|
|
|
<para>
|
|
<emphasis>openwaveoutput()</emphasis> is called when the first wave output occurs,
|
|
and only if the selected wavemode is 1. It should do the following:
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
Open the given device, and prepare it for wave output
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
<emphasis>or</emphasis>
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
Store the device name so that the device can be opened in <emphasis>startplayback()</emphasis>.
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
<emphasis>openmidioutput()</emphasis> will always be called before <emphasis>openwaveoutput()</emphasis>,
|
|
and <emphasis>closemidioutput()</emphasis>will always be called before <emphasis>closewaveoutput()</emphasis>, but not in all cases will both functions be called.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>openwaveoutput()</emphasis> will typically be called once, whereas
|
|
<emphasis>startplayback()</emphasis> is called for every new DMA transfer to the SB16 emulation. If feasible,
|
|
it could be useful to open and/or lock the output device in
|
|
<emphasis>startplayback()</emphasis> as opposed to <emphasis>openwaveoutput()</emphasis>
|
|
to ensure that it can be used by other applications while Bochs doesn't
|
|
need it.
|
|
</para>
|
|
|
|
<para>
|
|
However, many older applications don't use the auto-init DMA
|
|
mode, which means that they start a new DMA transfer for every single
|
|
block of output, which means usually for every 2048 bytes or so.
|
|
Unfortunately there is no way of knowing whether the application will
|
|
restart an expired DMA transfer soon, so that in these cases the
|
|
<emphasis>startwaveplayback</emphasis> function will be called very often, and it
|
|
isn't a good idea to have it reopen the device every time.
|
|
</para>
|
|
|
|
<para>The buffer when writing to the device should not be overly large.
|
|
Usually about four buffers of 4096 bytes produce best results. Smaller
|
|
buffers could mean too much overhead, while larger buffers contribute
|
|
to the fact that the actual output will always be late when the application
|
|
tries to synchronize it with for example graphics.
|
|
</para>
|
|
|
|
<para>The parameters are the following: </para>
|
|
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
<emphasis>device</emphasis> is the wave device selected by
|
|
the user. It is strictly system-dependent. The value is that of the
|
|
<emphasis>WAVE=device</emphasis>
|
|
configuration option.
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
Note that only one wave output device will be used at any one time.
|
|
<emphasis>device</emphasis> may not have the same value throughout one session, but it will be closed
|
|
before it is changed.
|
|
</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>int startwaveplayback(int frequency, int bits, int stereo, int format)</title>
|
|
|
|
<para>
|
|
This function is called whenever the application starts a new DMA transfer. It should do the following:
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
Open the wave output device, unless <emphasis>openwaveoutput()</emphasis> did that
|
|
already
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
Prepare the device for data and set the device parameters to those given
|
|
in the function call
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
The parameters are the following:
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
<emphasis>frequency</emphasis> is the desired frequency of the
|
|
output. Because of the capabities of the SB16, it can have any value between
|
|
5000 and 44,100.
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
<emphasis>bits</emphasis> is either 8 or 16, denoting the resolution
|
|
of one sample.
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
<emphasis>stereo</emphasis> is either 1 for stereo output, or 0 for mono output.
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
<emphasis>format</emphasis> is a bit-coded value (see below).
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Format Bits</title>
|
|
<para>
|
|
&FIXME; Insert FORMAT BITS table here
|
|
</para>
|
|
</section>
|
|
|
|
|
|
<section>
|
|
<title>int waveready()</title>
|
|
|
|
<para>
|
|
This is called whenever the emulator has another output buffer ready
|
|
and would like to pass it to the output class. This happens every
|
|
<emphasis>BX_SOUND_OUTPUT_WAVEPACKETSIZE</emphasis> bytes, or whenever a DMA transfer
|
|
is done or aborted.
|
|
</para>
|
|
|
|
<para>
|
|
It should return whether the output device is ready for another buffer
|
|
of <emphasis>BX_SOUND_OUTPUT_WAVEPACKETSIZE</emphasis> bytes.
|
|
If <emphasis>BX_SOUND_OUTPUT_ERR</emphasis>
|
|
is returned, the emulator waits about 1/(frequency * bytes per sample) seconds
|
|
and then asks again. The DMA transfer is stalled during that time, but
|
|
the application keeps running, until the output device becomes ready.
|
|
</para>
|
|
|
|
<para>
|
|
As opposed to <emphasis>midiready(), waveready()</emphasis> will <emphasis>not</emphasis> be
|
|
called unless the device is open.
|
|
</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>int sendwavepacket(int length, Bit8u data[])</title>
|
|
|
|
<para>
|
|
This function is called whenever a data packet of at most <emphasis>BX_SB16_WAVEPACKETSIZE</emphasis>
|
|
is ready at the SB16 emulator. It should then do the following:
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
Send this wave packet to the wave hardware
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
This function <emphasis>has</emphasis> to be synchronous, meaning that it <emphasis>has</emphasis>
|
|
to return immediately, and <emphasis>not</emphasis> wait until the output is done. Also,
|
|
this function might be called before the previous output is done. If your
|
|
hardware can't append the new output to the old one, you will have to implement
|
|
this yourself, or the output will be very chunky, with as much silence
|
|
between the blocks as the blocks take to play. This is not what you want.
|
|
Instead, <emphasis>waveready()</emphasis> should return <emphasis>BX_SOUND_OUTPUT_ERR</emphasis>
|
|
until the device accepts another block of data.
|
|
</para>
|
|
|
|
<para>
|
|
Parameters:
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
<emphasis>length</emphasis> is the number of data bytes in
|
|
the data stream. It will never be larger than <emphasis>BX_SB16_WAVEPACKETSIZE</emphasis>.
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
<emphasis>data</emphasis> is the array of data bytes.
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
The order of bytes in the data stream is the same as that in the Wave file format:
|
|
</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Sequences of Databytes Table</title>
|
|
<para>
|
|
&FIXME; Insert Sequences of Databytes table here
|
|
</para>
|
|
|
|
<para>
|
|
Typically 8 bit data will be unsigned with values from 0 to 255, and
|
|
16 bit data will be signed with values from -32768 to 32767, although the
|
|
SB16 is not limited to this. For further information on the codecs and
|
|
the use of reference bytes please refer to the Creative Labs Sound Blaster
|
|
Programmer's Manual, which can be downloaded from the Creative Labs web
|
|
site.
|
|
</para>
|
|
</section>
|
|
|
|
|
|
<section><title>int stopwaveplayback()</title>
|
|
|
|
<para>
|
|
This function is called at the end of a DMA transfer. It should do the following:
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
Close the output device if it was opened by <emphasis>startwaveplayback()</emphasis>.
|
|
and it's not going to be opened soon. Which is almost impossible to tell.
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section><title>int closewaveoutput()</title>
|
|
|
|
<para>
|
|
This function is called just before Bochs exits. It should do the following:
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
Close the output device, if this hasn't been done by <emphasis>stopwaveplayback()</emphasis>.
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
Typically, <emphasis>stopwaveplayback()</emphasis> will be called several times, whenever
|
|
a DMA transfer is done, where <emphasis>closewaveoutput()</emphasis> will only be called
|
|
once. However, in the future it might be possible that <emphasis>openwaveoutput()</emphasis>
|
|
is called again, for example if the user chose to switch devices while
|
|
Bochs was running. This is not supported at the moment, but might be in
|
|
the future.
|
|
</para>
|
|
</section>
|
|
|
|
</section> <!-- end of SB16 section-->
|
|
|
|
</chapter>
|
|
|
|
<chapter><title>Debugger</title>
|
|
<section><title>compile with debugger support</title>
|
|
<para>
|
|
&FIXME;
|
|
</para>
|
|
</section>
|
|
<section><title>get started in debugger</title>
|
|
<para>
|
|
&FIXME;
|
|
</para>
|
|
</section>
|
|
<section><title>command reference</title>
|
|
<para>
|
|
&FIXME;
|
|
</para>
|
|
</section>
|
|
<section><title>techniques</title>
|
|
<para>
|
|
&FIXME;
|
|
</para>
|
|
</section>
|
|
</chapter>
|
|
|
|
<chapter><title>Coding</title>
|
|
<section><title>coding conventions</title>
|
|
<para>
|
|
&FIXME;
|
|
</para>
|
|
</section>
|
|
<section><title>patches:</title>
|
|
<para>
|
|
&FIXME;
|
|
how to make, where to submit, what happens then?
|
|
</para
|
|
</section>
|
|
|
|
<section><title>life cycle of a CVS release</title>
|
|
<para>
|
|
&FIXME;
|
|
</para>
|
|
</section>
|
|
|
|
</chapter>
|
|
</book>
|