dcca9d9a31
- added FIXME to all CVS-related sections that still need a rewrite
2558 lines
84 KiB
Plaintext
2558 lines
84 KiB
Plaintext
<!--
|
|
================================================================
|
|
doc/docbook/development/development.dbk
|
|
$Id$
|
|
|
|
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>
|
|
<author><firstname>Christophe</firstname><surname>Bothamy</surname></author>
|
|
<editor><firstname>Michael</firstname><surname>Calabrese</surname></editor>
|
|
</authorgroup>
|
|
</bookinfo>
|
|
|
|
<!-- *************************************************************** -->
|
|
<chapter id="resources"><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 id="svn-write-access-setup"><title>Setting up SVN write access</title>
|
|
<para>
|
|
&FIXME; Rewrite for SVN
|
|
</para>
|
|
<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>@bochs.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>@bochs.cvs.sourceforge.net:/cvsroot/bochs"
|
|
cvs -z3 checkout bochs
|
|
<replaceable>sfusername</replaceable>@bochs.cvs.sourceforge.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 id="using-svn-write-access"><title>Using SVN 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 SVN" 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>@bochs.cvs.sf.net's password: <replaceable><--type your password</replaceable>
|
|
$ cvs commit file.cc
|
|
<replaceable>sfusername</replaceable>@bochs.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>@bochs.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>@bochs.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 SVN write access" -->
|
|
|
|
<section id="trackers"><title>SourceForge bug, feature, and patch trackers</title>
|
|
<para>
|
|
&FIXME;
|
|
</para>
|
|
</section>
|
|
|
|
<section id="other"><title>Ideas for other sections</title>
|
|
<para>
|
|
<screen>
|
|
Ideas:
|
|
- how to browse code with viewvc
|
|
- how to find an identifier, variable, or specific text in the code
|
|
- how to make patches with SVN
|
|
</screen>
|
|
</para>
|
|
</section>
|
|
|
|
</chapter>
|
|
|
|
<chapter id="about-the-code"><title>About the code</title>
|
|
|
|
<section id="code-overview"><title>Overview</title>
|
|
<para>
|
|
The initial versions of some sections in this chapter are based on a document
|
|
written by Peter "Firefly" Lund. It was added and updated in January 2006.
|
|
</para>
|
|
<para>
|
|
The Bochs virtual PC consists of many pieces of hardware. At a bare minimum
|
|
there are always a CPU, a PIT (Programmable Interval Timer), a PIC
|
|
(Programmable Interrupt Controller), a DMA controller, some memory (this
|
|
includes both RAM and BIOS ROMs), a video card (usually VGA), a keyboard port
|
|
(also handles the mouse), an RTC with battery backed NVRAM, and some extra
|
|
motherboard circuitry.
|
|
</para>
|
|
<para>
|
|
There might also be a NE2K ethernet card, a PCI controller, a Sound Blaster 16,
|
|
an IDE controller (+ harddisks/CDROM), a SCSI controller (+ harddisks), a
|
|
floppy controller, an APIC ..
|
|
</para>
|
|
<para>
|
|
There may also be more than one CPU.
|
|
</para>
|
|
<para>
|
|
Most of these pieces of hardware have their own C++ class - and if Bochs is
|
|
configured to have more than one piece of a type of hardware, each will have
|
|
its own object.
|
|
</para>
|
|
<para>
|
|
The pieces of hardware communicates over a couple of buses with each other -
|
|
some of the things that the buses carry are reads and writes in memory space,
|
|
reads and writes in I/O space, interrupt requests, interrupt acknowledges, DMA
|
|
requests, DMA acknowledges, and NMI request/acknowledge. How that is simulated
|
|
is explained later.&FIXME;
|
|
</para>
|
|
<para>
|
|
Other important pieces of the puzzle are: the options object (reads/writes
|
|
configuration files, can be written to and queried while Bochs is running) and
|
|
the GUI object. There are many different but compatible implementations of the
|
|
GUI object, depending on whether you compile for X (Unix/Linux), Win32,
|
|
Macintosh (two versions: one for Mac OS X and one for older OS's), Amiga,
|
|
etc.
|
|
</para>
|
|
<para>
|
|
And then there is the supporting cast: debugger, config menu, panic handler,
|
|
disassembler, tracer, instrumentation.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="directory-structure"><title>Directory Structure</title>
|
|
<para>
|
|
<table>
|
|
<title>Directory structure</title>
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>Location</entry>
|
|
<entry>Meaning</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row><entry>bios</entry><entry>System and VGA BIOS images, system BIOS sources and makefile</entry></row>
|
|
<row><entry>build</entry><entry>additional stuff required for building Bochs on different platforms</entry></row>
|
|
<row><entry>bx_debug</entry><entry>the builtin Bochs debugger</entry></row>
|
|
<row><entry>cpu</entry><entry>the cpu emulation sources</entry></row>
|
|
<row><entry>disasm</entry><entry>the disassembler for the Bochs debugger</entry></row>
|
|
<row><entry>doc/docbook</entry><entry>the Bochs documentation in DocBook format</entry></row>
|
|
<row><entry>doc/man</entry><entry>Bochs manual pages</entry></row>
|
|
<row><entry>docs-html</entry><entry>old Bochs documentation in HTML (will be replaced by DocBook)</entry></row>
|
|
<row><entry>dynamic</entry><entry>empty directory (reserved for dynamic translation code)</entry></row>
|
|
<row><entry>font</entry><entry>the default VGA font used by most of the display libraries</entry></row>
|
|
<row><entry>fpu</entry><entry>the fpu emulation sources</entry></row>
|
|
<row><entry>gui</entry><entry>display libraries (guis), the simulator interface and text mode config interface</entry></row>
|
|
<row><entry>gui/bitmaps</entry><entry>bitmaps for the headerbar</entry></row>
|
|
<row><entry>gui/keymaps</entry><entry>keymaps for the keyboard mapping feature</entry></row>
|
|
<row><entry>host</entry><entry>host specific drivers (currently only used by the pcidev kernel module for Linux)</entry></row>
|
|
<row><entry>instrument</entry><entry>directory tree for the instrumentation feature</entry></row>
|
|
<row><entry>iodev</entry><entry>standard PC devices, PCI devices, lowlevel networking and sound drivers</entry></row>
|
|
<row><entry>memory</entry><entry>memory management and ROM loader</entry></row>
|
|
<row><entry>misc</entry><entry>useful utilities (e.g. bximage, bxcommit, niclist)</entry></row>
|
|
<row><entry>misc/sb16</entry><entry>tool to control the SB16 emulation from the guest side</entry></row>
|
|
<row><entry>patches</entry><entry>pending patches</entry></row>
|
|
<row><entry>plex86</entry><entry>plex86 directory structure (possibly outdated)</entry></row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</para>
|
|
</section>
|
|
|
|
<section id="emulator-objects"><title>Emulator Objects</title>
|
|
<section><title>Weird macros and other mysteries</title>
|
|
<para>
|
|
Bochs has many macros with inscrutable names. One might even go as far as to
|
|
say that Bochs is macro infested.
|
|
Some of them are gross speed hacks, to cover up the slow speed that C++ causes.
|
|
Others paper over differences between the simulated PC configurations.
|
|
Many of the macros exhibit the same problem as C++ does: too much stuff happens
|
|
behind the programmer's back. More explicitness would be a big win.
|
|
</para>
|
|
</section>
|
|
<section id="static-methods-hack"><title>Static methods hack</title>
|
|
<para>
|
|
C++ methods have an invisible parameter called the this pointer - otherwise the
|
|
method wouldn't know which object to operate on. In many cases in Bochs, there
|
|
will only ever be one object - so this flexibility is unnecessary. There is a
|
|
hack that can be enabled by #defining BX_USE_CPU_SMF to 1 in <filename>config.h
|
|
</filename> that makes most methods static, which means they have a "special
|
|
relationship" with the class they are declared in but apart from that are
|
|
normal C functions with no hidden parameters. Of course they still need access
|
|
to the internals of an object, so the single object of their class has a globally
|
|
visible name that these functions use. It is all hidden with macros.
|
|
</para>
|
|
<para>
|
|
Declaration of a class, from iodev/pic.h:
|
|
</para>
|
|
<screen>
|
|
...
|
|
#if BX_USE_PIC_SMF
|
|
# define BX_PIC_SMF static
|
|
# define BX_PIC_THIS thePic->
|
|
#else
|
|
# define BX_PIC_SMF
|
|
# define BX_PIC_THIS this->
|
|
#endif
|
|
...
|
|
class bx_pic_c : public bx_pic_stub_c {
|
|
|
|
public:
|
|
bx_pic_c(void);
|
|
~bx_pic_c(void);
|
|
...
|
|
BX_PIC_SMF void service_master_pic(void);
|
|
BX_PIC_SMF void service_slave_pic(void);
|
|
BX_PIC_SMF void clear_highest_interrupt(bx_pic_t *pic);
|
|
};
|
|
</screen>
|
|
<para>
|
|
And iodev/pic.cc:
|
|
</para>
|
|
<screen>
|
|
...
|
|
#define LOG_THIS thePic->
|
|
...
|
|
bx_pic_c *thePic = NULL;
|
|
...
|
|
void bx_pic_c::service_master_pic(void)
|
|
{
|
|
Bit8u unmasked_requests;
|
|
int irq;
|
|
Bit8u isr, max_irq;
|
|
Bit8u highest_priority = BX_PIC_THIS s.master_pic.lowest_priority + 1;
|
|
if(highest_priority > 7)
|
|
highest_priority = 0;
|
|
|
|
if (BX_PIC_THIS s.master_pic.INT) { /* last interrupt still not acknowleged */
|
|
return;
|
|
}
|
|
|
|
if (BX_PIC_THIS s.master_pic.special_mask) {
|
|
/* all priorities may be enabled. check all IRR bits except ones
|
|
* which have corresponding ISR bits set
|
|
*/
|
|
max_irq = highest_priority;
|
|
}
|
|
else { /* normal mode */
|
|
/* Find the highest priority IRQ that is enabled due to current ISR */
|
|
isr = BX_PIC_THIS s.master_pic.isr;
|
|
...
|
|
}
|
|
...
|
|
</screen>
|
|
<para>
|
|
Ugly, isn't it? If we use static methods, methods prefixed with BX_PIC_SMF are
|
|
declared static and references to fields inside the object, which are prefixed
|
|
with BX_PIC_THIS, will use the globally visible object, thePic->. If we don't
|
|
use static methods, BX_PIC_SMF evaluates to nothing and BX_PIC_THIS becomes this->.
|
|
Making it evaluate to nothing would be a lot cleaner, but then the scoping rules
|
|
would change slightly between the two Bochs configurations, which would be a load
|
|
of bugs just waiting to happen. Some classes use BX_SMF, others have their own
|
|
version of the macro, like BX_PIC_SMF above.
|
|
</para>
|
|
</section>
|
|
<section id="cpu-mem-objects"><title>CPU und memory objects in UP/SMP configurations</title>
|
|
<para>
|
|
The CPU class is a special case of the above: if Bochs is simulating a uni-
|
|
processor machine then there is obviously only one bx_cpu_c object and the
|
|
static methods trick can be used. If, on the other hand, Bochs is simulating an
|
|
smp machine then we can't use the trick. The same seems to be true for memory:
|
|
for some reason, we have a memory object for each CPU object. This might become
|
|
relevant for NUMA machines, but they are not all that common -- and even the
|
|
existing IA-32 NUMA machines bend over backwards to hide that fact: it should
|
|
only be visible in slightly worse timing for non-local memory and non-local
|
|
peripherals. Other than that, the memory map and device map presented to each
|
|
CPU will be identical.
|
|
</para>
|
|
<para>
|
|
In a UP configuration, the CPU object is declared as bx_cpu. In an SMP
|
|
configuration it will be an array of pointers to CPU objects (bx_cpu_array[]).
|
|
For memory that would be bx_mem and bx_mem_array[], respectively.
|
|
Each CPU object contains a pointer to its associated memory object.
|
|
Access of a CPU object often goes through the BX_CPU(x) macro, which either
|
|
ignores the parameter and evaluates to &bx_cpu, or evaluates to bx_cpu_array
|
|
[n], so the result will always be a pointer. The same goes for BX_MEM(x).
|
|
If static methods are used then BX_CPU_THIS_PTR evaluates to BX_CPU(0)->. Ugly,
|
|
isn't it?
|
|
</para>
|
|
</section>
|
|
<section id="config-parameter-tree"><title>The configuration parameter tree</title>
|
|
<para>
|
|
Starting with version 1.3, the Bochs configuration parameters are stored in parameter
|
|
objects. These objects have get/set methods with min/max checks and it is possible
|
|
to define parameter handlers to perform side effects and to override settings.
|
|
Each parameter type has it's own object type with specific features (numeric,
|
|
boolean, enum, string and file name). A special object type containing a list of
|
|
parameters is designed for building and managing configuration menus or dialogs
|
|
automatically. In the original implementation the parameters could be accessed
|
|
only with their unique id from a static list or a special structure containing
|
|
pointers to all parameters.
|
|
</para>
|
|
<para>
|
|
Starting with version 2.3, the Bochs parameter object handling has been rewritten
|
|
to a parameter tree. There is now a root list containing child lists, and these
|
|
lists can contain lists or parameters and so on. The parameters are now accessed
|
|
by a name build from all the list names in the path and finally the parameter
|
|
name separated by periods.
|
|
<screen>
|
|
Bit32u megs = SIM->get_param_num("memory.standard.ram.size")->get();
|
|
</screen>
|
|
</para>
|
|
<para>
|
|
The example above shows how to get the memory size in megabytes from the simulator
|
|
interface. In the root list (".") there is child list named "memory" containing
|
|
a child list "standard". It's child list "ram" contains the numeric parameter type
|
|
"size". The SIM->get_param_num() methods returns the object pointer and the get()
|
|
method returns the parameter value.
|
|
</para>
|
|
<para>
|
|
The table below shows all parameter types used by the Bochs configuration interface.
|
|
<table>
|
|
<title>Parameter types</title>
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>Type</entry>
|
|
<entry>Description</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>bx_object_c</entry>
|
|
<entry>Base class for all the other parameter types. It contains the unique parameter id and the object type value.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>bx_param_c</entry>
|
|
<entry>Generic parameter class. It contains the name, label, description and the input/output formats.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>bx_param_num_c</entry>
|
|
<entry>Numerical (decimal/hex) config settings are stored in this parameter type.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>bx_param_bool_c</entry>
|
|
<entry>This parameter type is based on bx_param_num_c, but it is designed for boolean values. A dependency
|
|
list can be defined to enable/disable other parameters depending on the value change.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>bx_param_enum_c</entry>
|
|
<entry>Based on bx_param_num_c this parameter type contains a list of valid values.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>bx_param_string_c</entry>
|
|
<entry>Configuration strings are stored in this type of parameter.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>bx_param_filename_c</entry>
|
|
<entry>Based on bx_param_string_c this parameter type is used for file names.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>bx_list_c</entry>
|
|
<entry>Contains a list of pointers to parameters (bx_param_*_c and bx_list_c).
|
|
In the config interface it is used for menus/dialogs.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</para>
|
|
</section>
|
|
<section id="save-restore"><title>The save/restore feature</title>
|
|
<para>
|
|
The save/restore feature is based on an extension to the parameter tree concept.
|
|
A subtree (list) called "bochs" appears in the root of the parameter tree
|
|
and some new "shadow" parameter types store pointers to values instead of the values
|
|
itself. All the hardware objects have register_state() methods to register pointers
|
|
to the device registers and switches that need to be saved. The simulator interface
|
|
saves the registered data in text format to the specified folder (usually one file
|
|
per item in the save/restore list). Large binary arrays are registered with a
|
|
special parameter type, so they are saved as separate files.
|
|
</para>
|
|
<para>
|
|
The table below shows the additional parameter types for save/restore.
|
|
<table>
|
|
<title>Save/restore parameter types</title>
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>Type</entry>
|
|
<entry>Description</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>bx_shadow_num_c</entry>
|
|
<entry>Based on bx_param_num_c this type stores a pointer to a numerical variable.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>bx_shadow_bool_c</entry>
|
|
<entry>This parameter type stores a pointer to a boolean variable.</entry>
|
|
</row>
|
|
<row>
|
|
<entry>bx_shadow_data_c</entry>
|
|
<entry>This special parameter type stores pointer size of a binary array.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
It is also possible to use the bx_param_num_c object with parameter save/restore
|
|
handlers. With this special way several device settings can be save to and restored
|
|
from one single parameter.
|
|
</para>
|
|
<para>
|
|
All devices can uses these two save/restore specific methods:
|
|
<itemizedlist>
|
|
<listitem><para>register_state() is called after the device init() to register the device members for save/restore</para></listitem>
|
|
<listitem><para>after_restore_state() is an optional method to do things directly after restore</para></listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="configure-scripting"><title>Configure Scripting</title>
|
|
<para>
|
|
&FIXME;
|
|
configure script, makefiles, header files
|
|
</para>
|
|
</section>
|
|
|
|
<section id="logfunctions"><title>Log Functions</title>
|
|
<para>
|
|
&FIXME;
|
|
log functions: what is a panic, what is an error, etc.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="timers"><title>timers</title>
|
|
<para>
|
|
&FIXME;
|
|
</para>
|
|
</section>
|
|
|
|
<section id="cmos-map"><title>Bochs's CMOS map</title>
|
|
<para>
|
|
In addition to the default CMOS RAM layout, the Bochs BIOS uses some additional
|
|
registers for harddisk parameters and the boot sequence. The following table
|
|
shows all CMOS registers and their meaning.
|
|
</para>
|
|
<para>
|
|
<screen>
|
|
Legend:
|
|
S - set by the emulator (Bochs)
|
|
Q - set by the emulator (Qemu)
|
|
B - set by the bios
|
|
U - unused by the bios
|
|
|
|
LOC NOTES MEANING
|
|
0x00 S rtc seconds
|
|
0x01 B second alarm
|
|
0x02 S rtc minutes
|
|
0x03 B minute alarm
|
|
0x04 S rtc hours
|
|
0x05 B hour alarm
|
|
|
|
0x06 S,U day of week
|
|
0x07 S,B date of month
|
|
0x08 S,B month
|
|
0x09 S,B year
|
|
|
|
0x0a S,B status register A
|
|
0x0b S,B status register B
|
|
0x0c S status register C
|
|
0x0d S status register D
|
|
|
|
0x0f S shutdown status
|
|
values:
|
|
0x00: normal startup
|
|
0x09: normal
|
|
0x0d+: normal
|
|
0x05: eoi ?
|
|
else: unimpl
|
|
|
|
0x10 S fd drive type (2 nibbles: high=fd0, low=fd1)
|
|
values:
|
|
1: 360K 5.25"
|
|
2: 1.2MB 5.25"
|
|
3: 720K 3.5"
|
|
4: 1.44MB 3.5"
|
|
5: 2.88MB 3.5"
|
|
|
|
!0x11 configuration bits!!
|
|
|
|
0x12 S how many disks first (hd type)
|
|
|
|
!0x13 advanced configuration bits!!
|
|
|
|
0x14 S,U equipment byte (?)
|
|
bits where what
|
|
7-6 floppy.cc
|
|
5-4 vga.cc 0 = vga
|
|
2 keyboard.cc 1 = enabled
|
|
0 floppy.cc
|
|
|
|
0x15 S,U base memory - low
|
|
0x16 S,U base memory - high
|
|
|
|
0x17 S,U extended memory in k - low
|
|
0x18 S,U extended memory in k - high
|
|
|
|
0x19 S hd0: extended type
|
|
0x1a S hd1: extended type
|
|
|
|
0x1b S,U hd0:cylinders - low
|
|
0x1c S,U hd0:cylinders - high
|
|
0x1d S,U hd0:heads
|
|
0x1e S,U hd0:write pre-comp - low
|
|
0x1f S,U hd0:write pre-comp - high
|
|
0x20 S,U hd0:retries/bad_map/heads>8
|
|
0x21 S,U hd0:landing zone - low
|
|
0x22 S,U hd0:landing zone - high
|
|
0x23 S,U hd0:sectors per track
|
|
|
|
0x24 S,U hd1:cylinders - low
|
|
0x25 S,U hd1:cylinders - high
|
|
0x26 S,U hd1:heads
|
|
0x27 S,U hd1:write pre-comp - low
|
|
0x28 S,U hd1:write pre-comp - high
|
|
0x29 S,U hd1:retries/bad_map/heads>8
|
|
0x2a S,U hd1:landing zone - low
|
|
0x2b S,U hd1:landing zone - high
|
|
0x2c S,U hd1:sectors per track
|
|
|
|
0x2d S boot from (bit5: 0:hd, 1:fd)
|
|
|
|
0x2e S,U standard cmos checksum (0x10->0x2d) - high
|
|
0x2f S,U standard cmos checksum (0x10->0x2d) - low
|
|
|
|
0x30 S extended memory in k - low
|
|
0x31 S extended memory in k - high
|
|
|
|
0x32 S rtc century
|
|
|
|
0x34 S extended memory in 64k - low
|
|
0x35 S extended memory in 64k - high
|
|
|
|
0x37 S ps/2 rtc century (copy of 0x32, needed for winxp)
|
|
|
|
0x38 S eltorito boot sequence + boot signature check
|
|
bits
|
|
0 floppy boot signature check (1: disabled, 0: enabled)
|
|
7-4 boot drive #3 (0: unused, 1: fd, 2: hd, 3:cd, else: fd)
|
|
|
|
0x39 S ata translation policy - ata0 + ata1
|
|
bits
|
|
1-0 ata0-master (0: none, 1: LBA, 2: LARGE, 3: R-ECHS)
|
|
3-2 ata0-slave
|
|
5-4 ata1-master
|
|
7-6 ata1-slave
|
|
|
|
0x3a S ata translation policy - ata2 + ata3 (see above)
|
|
|
|
0x3d S eltorito boot sequence (see above)
|
|
bits
|
|
3-0 boot drive #1
|
|
7-4 boot drive #2
|
|
0x5b S extra memory above 4GB
|
|
0x5c S extra memory above 4GB
|
|
0x5d S extra memory above 4GB
|
|
0x5f Q number of processors
|
|
</screen>
|
|
</para>
|
|
</section>
|
|
|
|
<section id="sb16-emulation-basics"> <!-- start of SB16 section-->
|
|
|
|
<title>Sound Blaster 16 Emulation</title>
|
|
<note><para>
|
|
A little more up-to-date version of the user related part of this section is
|
|
available in the <ulink url="../user/sb16-emulation.html">user guide</ulink>.
|
|
</para></note>
|
|
<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_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>
|
|
See the section "Sound Blaster 16 Emulation" in the user documentation for
|
|
information about the commands of SB16CTRL.
|
|
</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>
|
|
|
|
<para>
|
|
<table>
|
|
<title>format bits</title>
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>Bit number</entry>
|
|
<entry>Meaning</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row> <entry> 0 (LSB) </entry><entry><para> 0: unsigned data </para><para>
|
|
1: signed data </para></entry> </row>
|
|
<row> <entry> 1..6 </entry><entry> Type of codec (see below) </entry> </row>
|
|
<row> <entry> 7 </entry><entry><para> 0: no reference byte </para><para>
|
|
1: with reference byte </para></entry> </row>
|
|
<row> <entry> 8..x </entry><entry> reserved (0) </entry> </row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<table>
|
|
<title>codecs</title>
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>Value</entry>
|
|
<entry>Meaning</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row> <entry> 0 </entry><entry> PCM (raw data) </entry> </row>
|
|
<row> <entry> 1 </entry><entry> reserved </entry> </row>
|
|
<row> <entry> 2 </entry><entry> 2-bit ADPCM (Creative Labs format) </entry> </row>
|
|
<row> <entry> 3 </entry><entry> 2.4-bit (3-bit) ADPCM (Creative Labs format) </entry> </row>
|
|
<row> <entry> 4 </entry><entry> 4-bit ADPCM (Creative Labs format) </entry> </row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</para>
|
|
<para>
|
|
Other codecs are not supported by the SB hardware. In fact, most applications will
|
|
translate their data into raw data, so that in most cases the codec will be zero.
|
|
</para>
|
|
<para>
|
|
The number of bytes per sample can be calculated from this as (bits / 8) * (stereo + 1).
|
|
</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:
|
|
|
|
<table>
|
|
<title>wave output types</title>
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>Output type</entry>
|
|
<entry>Sequence of data bytes</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row> <entry> 8 bit mono </entry><entry> Sample 1; Sample 2; Sample 3; etc. </entry> </row>
|
|
<row> <entry> 8 bit stereo </entry><entry> Sample 1, Channel 0; Sample 1, Channel 1; Sample 2, Channel 0; Sample 2, Channel 1; etc. </entry> </row>
|
|
<row> <entry> 16 bit mono </entry><entry> Sample 1, LSB; Sample 1, MSB; Sample 2, LSB; Sample 2, MSB; etc. </entry> </row>
|
|
<row> <entry> 16 bit stereo </entry><entry> Sample 1, LSB, Channel 0; Sample 1, MSB, Channel 0; Sample 1, LSB, Channel 1; Sample 1, MSB, Channel 1; etc. </entry> </row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</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-->
|
|
|
|
<section id="harddisk-redologs"><title>Harddisk Images based on redologs</title>
|
|
<para>
|
|
This section describes how the three new disk images "undoable", "growing", and "volatile" are
|
|
implemented in Bochs 2.1. It also applies to the write support the "vvfat" disk
|
|
image mode in Bochs 2.4.6.
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
undoable -> flat file, plus growing, commitable, rollbackable redolog file
|
|
</para></listitem>
|
|
<listitem><para>
|
|
growing -> growing files, all previously unwritten sectors go to the end of file
|
|
</para></listitem>
|
|
<listitem><para>
|
|
volatile -> flat file, plus hidden growing redolog
|
|
</para></listitem>
|
|
<listitem><para>
|
|
vvfat -> virtual VFAT disk created from directory, plus hidden growing redolog
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
</para>
|
|
|
|
<section>
|
|
<title>
|
|
Description
|
|
</title>
|
|
<para>
|
|
The idea behind volatile and undoable disk images
|
|
is to have a flat file, associated with one redolog file.
|
|
In case of vvfat, a directory is associated with the redolog file.
|
|
</para>
|
|
<para>
|
|
Reading a sector is done from the redolog file if it contains
|
|
the sector, or from the flat file / vvfat directory otherwise.
|
|
</para>
|
|
<para>
|
|
Sectors written go to the redolog,
|
|
so flat files are opened in read only mode in this configuration.
|
|
</para>
|
|
<para>
|
|
The redolog is designed in a way so it starts as a small file
|
|
and grows with every new sectors written to it. Previously written
|
|
sectors are done in place. Redolog files can not shrink.
|
|
</para>
|
|
<para>
|
|
The redolog is a growing file that can be created on the fly.
|
|
</para>
|
|
<para>
|
|
Now, it turns out that if you only use a redolog without any
|
|
flat file, you get a "growing" disk image.
|
|
</para>
|
|
<para>
|
|
So "undoable", "volatile", "growing" and "vvfat" harddisk images classes
|
|
are implemented on top of a redolog class.
|
|
</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>
|
|
How redologs works ?
|
|
</title>
|
|
|
|
<para>
|
|
At the start of a redolog file, there is a header, so Bochs can check whether
|
|
a file is consistent.
|
|
This header could also be checked when we implement
|
|
automatic type and size detection.
|
|
</para>
|
|
<para>
|
|
The generic part of the header contains values like type of image, and
|
|
spec version number.
|
|
</para>
|
|
<para>
|
|
The header also has a specific part.
|
|
For redologs, the number
|
|
of entries of the catalog, the extent, bitmap and disk size are stored.
|
|
</para>
|
|
|
|
<para>
|
|
In a redolog, the disk image is divided in a number of equal size "extents".
|
|
Each extent is a collection of successive 512-bytes sectors of the disk image,
|
|
preceeded by a n*512bytes bitmap.
|
|
</para>
|
|
|
|
<para>
|
|
the n*512bytes bitmap defines the presence (data has been written to it)
|
|
of a specific sector in the extent, one bit for each sector.
|
|
Therefore with a 512bytes bitmap, each extent can hold up to 4k blocks
|
|
</para>
|
|
|
|
<para>
|
|
Typically the catalog can have 256k entries.
|
|
With a 256k entries catalog and 512bytes bitmaps, the redolog can hold up to 512GiB
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
All data is stored on images as little-endian values
|
|
</para>
|
|
</note>
|
|
<section>
|
|
<title>
|
|
Header
|
|
</title>
|
|
<para>
|
|
At the start of a redolog file, there is a header. This header is designed
|
|
to be reusable by other disk image types.
|
|
</para>
|
|
<para>
|
|
The header length is 512 bytes. It contains :
|
|
<table>
|
|
<title>Generic header description</title>
|
|
<tgroup cols="5">
|
|
<thead>
|
|
<row>
|
|
<entry>Start position in bytes</entry>
|
|
<entry>Length in bytes</entry>
|
|
<entry>Data type</entry>
|
|
<entry>Description</entry>
|
|
<entry>Possible values</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row> <entry> 0 </entry> <entry> 32 </entry> <entry> string </entry> <entry> magical value </entry> <entry> Bochs Virtual HD Image </entry> </row>
|
|
<row> <entry> 32 </entry> <entry> 16 </entry> <entry> string </entry> <entry> type of file </entry> <entry> Redolog </entry> </row>
|
|
<row> <entry> 48 </entry> <entry> 16 </entry> <entry> string </entry> <entry> subtype of file </entry> <entry> Undoable, Volatile, Growing </entry> </row>
|
|
<row> <entry> 64 </entry> <entry> 4 </entry> <entry> Bit32u </entry> <entry> version of used specification </entry> <entry> 0x00010000 </entry> </row>
|
|
<row> <entry> 68 </entry> <entry> 4 </entry> <entry> Bit32u </entry> <entry> header size </entry> <entry> 512 </entry> </row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
<table>
|
|
<title>Redolog specific header description</title>
|
|
<tgroup cols="5">
|
|
<thead>
|
|
<row>
|
|
<entry>Start position in bytes</entry>
|
|
<entry>Length in bytes</entry>
|
|
<entry>Data type</entry>
|
|
<entry>Description</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row> <entry> 72 </entry> <entry> 4 </entry> <entry> Bit32u </entry> <entry> number of entries in the catalog </entry> </row>
|
|
<row> <entry> 76 </entry> <entry> 4 </entry> <entry> Bit32u </entry> <entry> bitmap size in bytes </entry> </row>
|
|
<row> <entry> 80 </entry> <entry> 4 </entry> <entry> Bit32u </entry> <entry> extent size in bytes</entry> </row>
|
|
<row> <entry> 84 </entry> <entry> 8 </entry> <entry> Bit64u </entry> <entry> disk size in bytes </entry> </row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title>
|
|
Catalog
|
|
</title>
|
|
<para>
|
|
Immediately following the header, there is a catalog containing
|
|
the position number (in extents) where each extent is located in the file.
|
|
</para>
|
|
<para>
|
|
Each position is a Bit32u entity.
|
|
</para>
|
|
|
|
</section>
|
|
<section>
|
|
<title>
|
|
Extent
|
|
</title>
|
|
<para>
|
|
&FIXME;
|
|
</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Parameters
|
|
</title>
|
|
<para>
|
|
The following tables shows what parameters are used when creating redologs or creating "growing" images :
|
|
<table>
|
|
<title>
|
|
How number of entries in the catalog and number of blocks by extents are computed
|
|
</title>
|
|
<tgroup cols="5">
|
|
<thead>
|
|
<row>
|
|
<entry>Catalog entries</entry> <entry>Catalog size(KiB)</entry> <entry>Bitmap size (B)</entry> <entry>Extent size (KiB)</entry> <entry>Disk Max Size</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry>512</entry> <entry>2</entry> <entry>1</entry> <entry>4</entry> <entry>2MiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>512</entry> <entry>2</entry> <entry>2</entry> <entry>8</entry> <entry>4MiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>1k</entry> <entry>4</entry> <entry>2</entry> <entry>8</entry> <entry>8MiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>1k</entry> <entry>4</entry> <entry>4</entry> <entry>16</entry> <entry>16MiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>2k</entry> <entry>8</entry> <entry>4</entry> <entry>16</entry> <entry>32MiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>2k</entry> <entry>8</entry> <entry>8</entry> <entry>32</entry> <entry>64MiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>4k</entry> <entry>16</entry> <entry>8</entry> <entry>32</entry> <entry>128MiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>4k</entry> <entry>16</entry> <entry>16</entry> <entry>64</entry> <entry>256MiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>8k</entry> <entry>32</entry> <entry>16</entry> <entry>64</entry> <entry>512MiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>8k</entry> <entry>32</entry> <entry>32</entry> <entry>128</entry> <entry>1GiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>16k</entry> <entry>64</entry> <entry>32</entry> <entry>128</entry> <entry>2GiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>16k</entry> <entry>64</entry> <entry>64</entry> <entry>256</entry> <entry>4GiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>32k</entry> <entry>128</entry> <entry>64</entry> <entry>256</entry> <entry>8GiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>32k</entry> <entry>128</entry> <entry>128</entry> <entry>512</entry> <entry>16GiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>64k</entry> <entry>256</entry> <entry>128</entry> <entry>512</entry> <entry>32GiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>64k</entry> <entry>256</entry> <entry>256</entry> <entry>1024</entry> <entry>64GiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>128k</entry> <entry>512</entry> <entry>256</entry> <entry>1024</entry> <entry>128GiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>128k</entry> <entry>512</entry> <entry>512</entry> <entry>2048</entry> <entry>256GiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>256k</entry> <entry>1024</entry> <entry>512</entry> <entry>2048</entry> <entry>512GiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>256k</entry> <entry>1024</entry> <entry>1024</entry> <entry>4096</entry> <entry>1TiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>512k</entry> <entry>2048</entry> <entry>1024</entry> <entry>4096</entry> <entry>2TiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>512k</entry> <entry>2048</entry> <entry>2048</entry> <entry>8192</entry> <entry>4TiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>1024k</entry> <entry>4096</entry> <entry>2048</entry> <entry>8192</entry> <entry>8TiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>1024k</entry> <entry>4096</entry> <entry>4096</entry> <entry>16384</entry> <entry>16TiB</entry>
|
|
</row>
|
|
<row>
|
|
<entry>2048k</entry> <entry>8192</entry> <entry>4096</entry> <entry>16384</entry> <entry>32TiB</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</para>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>
|
|
Redolog class description
|
|
</title>
|
|
<para>
|
|
The class <emphasis>redolog_t();</emphasis> implements the necessary
|
|
methods to create, open, close, read and write data to a redolog.
|
|
Managment of header catalog and sector bitmaps is done internally
|
|
by the class.
|
|
</para>
|
|
<section>
|
|
<title>
|
|
Constants
|
|
</title>
|
|
<para>
|
|
<screen>
|
|
#define STANDARD_HEADER_MAGIC "Bochs Virtual HD Image"
|
|
#define STANDARD_HEADER_VERSION (0x00010000)
|
|
#define STANDARD_HEADER_SIZE (512)
|
|
</screen>
|
|
These constants are used in the generic part of the header.
|
|
</para>
|
|
|
|
<para>
|
|
<screen>
|
|
#define REDOLOG_TYPE "Redolog"
|
|
#define REDOLOG_SUBTYPE_UNDOABLE "Undoable"
|
|
#define REDOLOG_SUBTYPE_VOLATILE "Volatile"
|
|
#define REDOLOG_SUBTYPE_GROWING "Growing"
|
|
</screen>
|
|
These constants are used in the specific part of the header.
|
|
</para>
|
|
|
|
<para>
|
|
<screen>
|
|
#define REDOLOG_PAGE_NOT_ALLOCATED (0xffffffff)
|
|
</screen>
|
|
This constant is used in the catalog for an unwritten extent.
|
|
</para>
|
|
|
|
</section> <!-- Constants -->
|
|
|
|
<section> <title>Methods</title>
|
|
<para>
|
|
<emphasis>redolog_t();</emphasis> instanciates a new redolog.
|
|
</para>
|
|
<para>
|
|
<emphasis>int make_header (const char* type, Bit64u size);</emphasis> creates a header
|
|
structure in memory, and sets its <emphasis>type</emphasis> and parameters based on the
|
|
disk image <emphasis>size</emphasis>. Returns 0.
|
|
</para>
|
|
<para>
|
|
<emphasis>int create (const char* filename, const char* type, Bit64u size);</emphasis>
|
|
creates a new empty redolog file, with header and catalog, named <emphasis>filename</emphasis>
|
|
of type <emphasis>type</emphasis> for a <emphasis>size</emphasis> bytes image.
|
|
Returns 0 for OK or -1 if a problem occured.
|
|
</para>
|
|
<para>
|
|
<emphasis>int create (int filedes, const char* type, Bit64u size);</emphasis>
|
|
creates a new empty redolog file, with header and catalog, in a previously
|
|
opened file described by <emphasis>filedes</emphasis>, of type <emphasis>type</emphasis>
|
|
for a <emphasis>size</emphasis> bytes image.
|
|
Returns 0 for OK or -1 if a problem occured.
|
|
</para>
|
|
<para>
|
|
<emphasis>int open (const char* filename, const char* type, Bit64u size);</emphasis>
|
|
opens a redolog file named <emphasis>filename</emphasis>, and checks
|
|
for consistency of header values against a <emphasis>type</emphasis> and
|
|
<emphasis>size</emphasis>.
|
|
Returns 0 for OK or -1 if a problem occured.
|
|
</para>
|
|
<para>
|
|
<emphasis>void close ();</emphasis>
|
|
closes a redolog file.
|
|
</para>
|
|
<para>
|
|
<emphasis>off_t lseek (off_t offset, int whence);</emphasis>
|
|
seeks at logical data offset <emphasis>offset</emphasis> in a redolog.
|
|
<emphasis>offset</emphasis> must be a multiple of 512.
|
|
Only SEEK_SET is supported for <emphasis>whence</emphasis>.
|
|
Returns -1 if a problem occured, or the current logical offset in
|
|
the redolog.
|
|
</para>
|
|
<para>
|
|
<emphasis>ssize_t read (void* buf, size_t count);</emphasis>
|
|
reads <emphasis>count</emphasis> bytes of data of the redolog, from current logical offset,
|
|
and copies it into <emphasis>buf</emphasis>.
|
|
<emphasis>count</emphasis> must be 512.
|
|
Returns the number of bytes read, that can be 0 if the data
|
|
has not previously be written to the redolog.
|
|
</para>
|
|
<para>
|
|
<emphasis>ssize_t write (const void* buf, size_t count);</emphasis>
|
|
writes <emphasis>count</emphasis> bytes of data from <emphasis>buf</emphasis>
|
|
to the redolog, at current logical offset.
|
|
<emphasis>count</emphasis> must be 512.
|
|
Returns the number of bytes written.
|
|
</para>
|
|
|
|
</section>
|
|
|
|
</section> <!-- Redolog class description -->
|
|
|
|
<section>
|
|
<title>
|
|
Disk image classes description
|
|
</title>
|
|
<para>
|
|
"volatile" and "undoable" disk images are easily implemented
|
|
by instanciating a <emphasis>default_image_t</emphasis> object (flat image)
|
|
and a <emphasis>redolog_t</emphasis> object (redolog).
|
|
</para>
|
|
<para>
|
|
"growing" disk images only instanciates a <emphasis>redolog_t</emphasis> object.
|
|
</para>
|
|
<para>
|
|
Classe names are <emphasis>undoable_image_t</emphasis>, <emphasis>volatile_image_t</emphasis>
|
|
and <emphasis>growing_image_t</emphasis>.
|
|
</para>
|
|
<para>
|
|
When using these disk images, the underlying data structure and layout
|
|
is completely
|
|
hidden to the caller. Then, all offset and size values are "logical" values,
|
|
as if the disk was a flat file.
|
|
</para>
|
|
<section>
|
|
<title>
|
|
Constants
|
|
</title>
|
|
<para>
|
|
<screen>
|
|
#define UNDOABLE_REDOLOG_EXTENSION ".redolog"
|
|
#define UNDOABLE_REDOLOG_EXTENSION_LENGTH (strlen(UNDOABLE_REDOLOG_EXTENSION))
|
|
#define VOLATILE_REDOLOG_EXTENSION ".XXXXXX"
|
|
#define VOLATILE_REDOLOG_EXTENSION_LENGTH (strlen(VOLATILE_REDOLOG_EXTENSION))
|
|
</screen>
|
|
These constants are used when building redolog file names
|
|
</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>
|
|
undoable_image_t methods
|
|
</title>
|
|
<para>
|
|
<emphasis>
|
|
undoable_image_t(Bit64u size, const char* redolog_name);
|
|
</emphasis>
|
|
instanciates a new <emphasis>undoable_image_t</emphasis>
|
|
object. This disk image logical length is <emphasis>size</emphasis> bytes and
|
|
the redolog filename is <emphasis>redolog_name</emphasis>.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>
|
|
int open (const char* pathname);
|
|
</emphasis>
|
|
opens the flat disk image <emphasis>pathname</emphasis>,
|
|
as an undoable disk image. The associated redolog will
|
|
be named <emphasis>pathname</emphasis> with a
|
|
<emphasis>UNDOABLE_REDOLOG_EXTENSION</emphasis>
|
|
suffix, unless set in the constructor.
|
|
Returns 0 for OK or -1 if a problem occured.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>
|
|
void close ();
|
|
</emphasis>
|
|
closes the flat image and its redolog.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>
|
|
off_t lseek (off_t offset, int whence);
|
|
</emphasis>
|
|
seeks at logical data position <emphasis>offset</emphasis> in
|
|
the undoable disk image.
|
|
Only SEEK_SET is supported for <emphasis>whence</emphasis>.
|
|
Returns -1 if a problem occured, or the current logical
|
|
offset in the undoable disk image.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>
|
|
ssize_t read (void* buf, size_t count);
|
|
</emphasis>
|
|
reads <emphasis>count</emphasis> bytes of data
|
|
from the undoable disk image, from current logical offset,
|
|
and copies it into <emphasis>buf</emphasis>.
|
|
<emphasis>count</emphasis> must be 512.
|
|
Returns the number of bytes read.
|
|
Data will be read from the redolog if it has
|
|
been previously written or from the flat image
|
|
otherwise.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>
|
|
ssize_t write (const void* buf, size_t count);
|
|
</emphasis>
|
|
writes <emphasis>count</emphasis> bytes of data from <emphasis>buf</emphasis>
|
|
to the undoable disk image, at current logical offset.
|
|
<emphasis>count</emphasis> must be 512.
|
|
Returns the number of bytes written.
|
|
Data will always be written to the redolog.
|
|
</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>
|
|
volatile_image_t methods
|
|
</title>
|
|
<para>
|
|
<emphasis>
|
|
volatile_image_t(Bit64u size, const char* redolog_name);
|
|
</emphasis>
|
|
instanciates a new <emphasis>volatile_image_t</emphasis>
|
|
object. This disk image logical length is <emphasis>size</emphasis> bytes and
|
|
the redolog filename is <emphasis>redolog_name</emphasis> plus a
|
|
random suffix.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>
|
|
int open (const char* pathname);
|
|
</emphasis>
|
|
opens the flat disk image <emphasis>pathname</emphasis>,
|
|
as a volatile disk image. The associated redolog will
|
|
be named <emphasis>pathname</emphasis> with a
|
|
random suffix, unless set in the constructor.
|
|
Returns 0 for OK or -1 if a problem occured.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>
|
|
void close ();
|
|
</emphasis>
|
|
closes the flat image and its redolog.
|
|
The redolog is deleted/lost after close is called.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>
|
|
off_t lseek (off_t offset, int whence);
|
|
</emphasis>
|
|
seeks at logical data position <emphasis>offset</emphasis> in
|
|
the volatile disk image.
|
|
Only SEEK_SET is supported for <emphasis>whence</emphasis>.
|
|
Returns -1 if a problem occured, or the current logical offset in
|
|
the volatile disk image.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>
|
|
ssize_t read (void* buf, size_t count);
|
|
</emphasis>
|
|
reads <emphasis>count</emphasis> bytes of data
|
|
from the volatile disk image, from current logical offset,
|
|
and copies it into <emphasis>buf</emphasis>.
|
|
<emphasis>count</emphasis> must be 512.
|
|
Returns the number of bytes read.
|
|
Data will be read from the redolog if it has
|
|
been previously written or from the flat image
|
|
otherwise.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>
|
|
ssize_t write (const void* buf, size_t count);
|
|
</emphasis>
|
|
writes <emphasis>count</emphasis> bytes of data from <emphasis>buf</emphasis>
|
|
to the volatile disk image, at current logical offset.
|
|
<emphasis>count</emphasis> must be 512.
|
|
Returns the number of bytes written.
|
|
Data will always be written to the redolog.
|
|
</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>
|
|
growing_image_t methods
|
|
</title>
|
|
<para>
|
|
<emphasis>
|
|
growing_image_t(Bit64u size);
|
|
</emphasis>
|
|
instanciates a new <emphasis>growing_image_t</emphasis>
|
|
object. This disk image logical length is <emphasis>size</emphasis> bytes.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>
|
|
int open (const char* pathname);
|
|
</emphasis>
|
|
opens the growing disk image <emphasis>pathname</emphasis>,
|
|
Returns 0 for OK or -1 if a problem occured.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>
|
|
void close ();
|
|
</emphasis>
|
|
closes the growing disk image.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>
|
|
off_t lseek (off_t offset, int whence);
|
|
</emphasis>
|
|
seeks at logical data position <emphasis>offset</emphasis> in
|
|
the growable disk image.
|
|
Only SEEK_SET is supported for <emphasis>whence</emphasis>.
|
|
Returns -1 if a problem occured, or the current logical offset in
|
|
the grwoing image.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>
|
|
ssize_t read (void* buf, size_t count);
|
|
</emphasis>
|
|
reads <emphasis>count</emphasis> bytes of data
|
|
from the growing disk image, from current logical offset,
|
|
and copies it into <emphasis>buf</emphasis>.
|
|
<emphasis>count</emphasis> must be 512.
|
|
Returns the number of bytes read.
|
|
The buffer will be filled with null bytes if data
|
|
has not been previously written to the growing image.
|
|
</para>
|
|
|
|
<para>
|
|
<emphasis>
|
|
ssize_t write (const void* buf, size_t count);
|
|
</emphasis>
|
|
writes <emphasis>count</emphasis> bytes of data from <emphasis>buf</emphasis>
|
|
to the growing disk image, at current logical offset.
|
|
<emphasis>count</emphasis> must be 512.
|
|
Returns the number of bytes written.
|
|
</para>
|
|
</section>
|
|
|
|
</section>
|
|
|
|
</section>
|
|
|
|
<section id="add-keymapping"><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>
|
|
|
|
</chapter>
|
|
|
|
<chapter id="debugger"><title>Debugger</title>
|
|
<section><title>compile with debugger support</title>
|
|
<para>
|
|
&FIXME;
|
|
</para>
|
|
</section>
|
|
<section id="debugger-get-started"><title>get started in debugger</title>
|
|
<para>
|
|
&FIXME;
|
|
</para>
|
|
</section>
|
|
<section id="debugger-commands"><title>command reference</title>
|
|
<para>
|
|
&FIXME;
|
|
</para>
|
|
</section>
|
|
<section id="debugger-techniques"><title>techniques</title>
|
|
<para>
|
|
&FIXME;
|
|
</para>
|
|
</section>
|
|
<section id="iodebug"><title>I/O Interface to Bochs Debugger</title>
|
|
<para>
|
|
This device was added by Dave Poirier (eks@void-core.2y.net).
|
|
</para>
|
|
<para>
|
|
Compiling Bochs with iodebug support
|
|
<screen>
|
|
./configure --enable-iodebug
|
|
make
|
|
</screen>
|
|
Other optional fields may be added to the ./configure line, see Bochs documentation for all the information.
|
|
</para>
|
|
|
|
<para>
|
|
<screen>
|
|
Using the I/O Interface to the debugger
|
|
|
|
port range: 0x8A00 - 0x8A01
|
|
|
|
Port 0x8A00 servers as command register. You can use it to enable the i/o interface,
|
|
change which data register is active, etc.
|
|
|
|
Port 0x8A01 is used as data register for the memory monitoring.
|
|
</screen>
|
|
</para>
|
|
<section><title>Commands supported by port 0x8A00</title>
|
|
<para>
|
|
<screen>
|
|
|
|
0x8A00
|
|
|
|
Used to enable the device. Any I/O to the debug module before this command is sent
|
|
is sent will simply be ignored.
|
|
|
|
|
|
0x8A01
|
|
|
|
Selects register 0: Memory monitoring range start address (inclusive)
|
|
|
|
|
|
0x8A02
|
|
|
|
Selects register 1: Memory monitoring range end address (exclusive)
|
|
|
|
|
|
0x8A80
|
|
|
|
Enable address range memory monitoring as indicated by register 0 and 1 and
|
|
clears both registers
|
|
|
|
|
|
0x8AE0 - Return to Debugger Prompt
|
|
|
|
If the debugger is enabled (via --enable-debugger), sending 0x8AE0 to port 0x8A00
|
|
after the device has been enabled will return the Bochs to the debugger prompt.
|
|
Basically the same as doing CTRL+C.
|
|
|
|
|
|
0x8AE2 - Instruction Trace Disable
|
|
|
|
If the debugger is enabled (via --enable-debugger), sending 0x8AE2 to port 0x8A00
|
|
after the device has been enabled will disable instruction tracing
|
|
|
|
|
|
0x8AE3 - Instruction Trace Enable
|
|
|
|
If the debugger is enabled (via --enable-debugger), sending 0x8AE3 to port 0x8A00
|
|
after the device has been enabled will enable instruction tracing
|
|
|
|
|
|
0x8AE4 - Register Trace Disable
|
|
|
|
If the debugger is enabled (via --enable-debugger), sending 0x8AE4 to port 0x8A00
|
|
after the device has been enabled will disable register tracing.
|
|
|
|
|
|
0x8AE5 - Register Trace Enable
|
|
|
|
If the debugger is enabled (via --enable-debugger), sending 0x8AE5 to port 0x8A00
|
|
after the device has been enabled will enable register tracing. This currently
|
|
output the value of all the registers for each instruction traced.
|
|
Note: instruction tracing must be enabled to view the register tracing
|
|
|
|
|
|
0x8AFF
|
|
|
|
Disable the I/O interface to the debugger and the memory monitoring functions.
|
|
</screen>
|
|
<note><para>all accesses must be done using word</para></note>
|
|
<note><para>reading this register will return 0x8A00 if currently activated, otherwise 0</para></note>
|
|
</para>
|
|
</section>
|
|
<section><title>Access to port 0x8A01 (write-only)</title>
|
|
<para>
|
|
All accesses to this port must be done using words. Writing to this port will shift
|
|
to the left by 16 the current value of the register and add the provided value to it.
|
|
<screen>
|
|
Sample:
|
|
|
|
reg0 = 0x01234567
|
|
|
|
out port: 0x8A01 data: 0xABCD
|
|
|
|
reg0 = 0x4567ABCD
|
|
</screen>
|
|
</para>
|
|
</section>
|
|
<section><title>Sample</title>
|
|
<para>
|
|
Enable memory monitoring on first page of text screen (0xb8000-0xb8fa0):
|
|
add in bochrc file: <command>optromimage1: file="asmio.rom", address=0xd0000</command>
|
|
<screen>
|
|
/*
|
|
* Make asmio ROM file:
|
|
* gcc -c asmio.S
|
|
* objcopy -O binary asmio.o asmio.rom
|
|
*/
|
|
.text
|
|
.global start
|
|
.code16
|
|
|
|
/* ROM Header */
|
|
.byte 0x55
|
|
.byte 0xAA
|
|
.byte 1 /* 512 bytes long */
|
|
|
|
start:
|
|
/* Monitor memory access on first page of text screen */
|
|
mov $0x8A00,%dx /* Enable iodebug (0x8A00->0x8A00) */
|
|
mov %dx,%ax
|
|
out %ax,%dx
|
|
mov $0x8A01,%ax /* Select register 0 start addr (0x8A01->0x8A00) */
|
|
out %ax,%dx
|
|
mov $0x8A01,%dx /* Write start addr 0xB8000 (high word first) */
|
|
mov $0xB,%ax
|
|
out %ax,%dx
|
|
mov $0x8000,%ax /* Write start addr (low word) */
|
|
out %ax,%dx
|
|
|
|
mov $0x8A02,%ax /* Select register 1 end addr (0x8A02->0x8A00) */
|
|
mov $0x8A00,%dx
|
|
out %ax,%dx
|
|
mov $0x8A01,%dx /* Write end addr 0xB8FA0 (high word first) */
|
|
mov $0xB,%ax
|
|
out %ax,%dx
|
|
mov $0x8FA0,%ax /* Write end addr (low word) */
|
|
out %ax,%dx
|
|
|
|
mov $0x8A00,%dx /* Enable addr range memory monitoring (0x8A80->0x8A00) */
|
|
mov $0x8A80,%ax
|
|
out %ax,%dx
|
|
|
|
mov $0x8A00,%dx /* Return to Bochs Debugger Prompt (0x8AE0->0x8A00) */
|
|
mov $0x8AE0,%ax
|
|
out %ax,%dx
|
|
lret
|
|
|
|
.byte 0x6b /* Checksum (code dependent!, update it as needed) */
|
|
.align 512 /* NOP follow */
|
|
</screen>
|
|
</para>
|
|
</section>
|
|
</section>
|
|
</chapter>
|
|
|
|
<chapter id="coding"><title>Coding</title>
|
|
<section><title>Coding guidelines</title>
|
|
<para>
|
|
<itemizedlist>
|
|
<listitem><para><command>Don't make use of any external C++ classes.</command></para>
|
|
<para>They are not offered on all platforms and this would make Bochs non-portable.
|
|
There is use of such classes in the optional debugger. I plan on removing this use.
|
|
</para></listitem>
|
|
<listitem><para><command>Don't use fancy C++ features.</command></para>
|
|
<para>Bochs is incredibly performance sensitive, and will be increasingly so as
|
|
more speed enhancements are added. There's a time and place for most everything
|
|
and this is not it. Some advanced features create overhead in the generated code
|
|
that you don't see. They also convolute the code, and sometimes occlude that is
|
|
really going on.
|
|
<itemizedlist>
|
|
<listitem><para>Don't use templates</para></listitem>
|
|
<listitem><para>Don't use virtual functions if not strictly required</para></listitem>
|
|
<listitem><para>Don't use C++ exceptions</para></listitem>
|
|
<listitem><para>Don't use overloading of any kind</para></listitem>
|
|
</itemizedlist></para></listitem>
|
|
<listitem><para><command>Use soft tabs.</command></para>
|
|
<para>At least when you submit code, convert all hard tabs to spaces.
|
|
There is no uniform way to handle tabs properly.</para></listitem>
|
|
<listitem><para><command>Please do compile with all warnings turned on.</command></para>
|
|
<para>It's really difficult to spot interesting warnings when a compile is littered
|
|
with non-interesting ones.</para></listitem>
|
|
<listitem><para><command>Don't use signed ints where unsigned will do.</command></para></listitem>
|
|
<listitem><para><command>Make sure that contributed code / patches are LGPL compatible.</command></para></listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</section>
|
|
<section id="patches"><title>patches:</title>
|
|
<para>
|
|
&FIXME;
|
|
how to make, where to submit, what happens then?
|
|
</para>
|
|
</section>
|
|
<section id="svn-release"><title>Building a Bochs release</title>
|
|
<section><title>Preparing source files and SVN</title>
|
|
<para>
|
|
&FIXME; Rewrite for SVN
|
|
</para>
|
|
<para>
|
|
Update version number and strings in configure.in.
|
|
<screen>
|
|
VERSION="2.4"
|
|
VER_STRING="2.4"
|
|
REL_STRING="Build from CVS snapshot on June 7, 2009"
|
|
</screen>
|
|
In the README file you have to update version number and date. Add some
|
|
information about new features if necessary.
|
|
<screen>
|
|
Bochs x86 Pentium+ Emulator
|
|
Updated: Sat May 3 07:34:00 CEST 2009
|
|
Version: 2.4
|
|
</screen>
|
|
Check date, update/sumup info in CHANGES. Run autoconf to regenerate configure and check them in.
|
|
Create a CVS tag to mark which revision of each file was used in the release.
|
|
For prereleases I make a normal CVS tag like this:
|
|
<screen>
|
|
cvs tag REL_2_4_pre1
|
|
</screen>
|
|
But for a real release, I make a CVS branch tag AND a normal tag.
|
|
<screen>
|
|
cvs tag REL_2_4_BASE
|
|
cvs tag -b REL_2_4
|
|
</screen>
|
|
The base tag marks where the branch split off of the main trunk.
|
|
This is very useful in maintaining the branch since you can do diffs
|
|
against it.
|
|
<screen>
|
|
cvs diff -r REL_2_4_BASE -r HEAD
|
|
cvs diff -r REL_2_4_BASE -r REL_2_4
|
|
cvs upd -j REL_2_4_BASE -j HEAD file
|
|
etc.
|
|
</screen>
|
|
The release and all bugfix releases after it are on the REL_2_4 branch.
|
|
When the release is actually finalized, you can do this:
|
|
<screen>
|
|
cvs tag REL_2_4_FINAL
|
|
</screen>
|
|
Now you can start building packages based on the created release tag.
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>Building the release on win32</title>
|
|
<para>
|
|
These instructions require cygwin and MSVC++.
|
|
</para>
|
|
<para>
|
|
In Cygwin:
|
|
<screen>
|
|
sh .conf.win32-vcpp # runs configure
|
|
make win32_snap # unzip workspace, make a win32 source ZIP
|
|
</screen>
|
|
Copy the source ZIP to a windows machine, if necessary.
|
|
</para>
|
|
<para>
|
|
Open up Visual C++ and load the workspace file Bochs.dsw. Check
|
|
the Build:Set Active Project Configuration is set the way you want it.
|
|
For releases I use "Win32 Release".
|
|
</para>
|
|
<para>
|
|
To create "bochsdbg.exe" with Bochs debugger support, manually change two
|
|
lines in config.h to turn on the debugger.
|
|
<screen>
|
|
#define BX_DEBUGGER 1
|
|
#define BX_DISASM 1
|
|
</screen>
|
|
VC++ will rebuild Bochs with debugger and overwrite bochs.exe. To avoid
|
|
trashing the non-debug version, move it out of the way while the debugger
|
|
version is being built. Then rename the debugger version to bochsdbg.exe.
|
|
<screen>
|
|
cd obj-release
|
|
mv bochs.exe bochs-normal.exe
|
|
(build again with BX_DEBUGGER=1 this time)
|
|
mv bochs.exe bochsdbg.exe
|
|
mv bochs-normal.exe bochs.exe
|
|
</screen>
|
|
</para>
|
|
<para>
|
|
To get the docbook installed, you need to do something like this:
|
|
<itemizedlist>
|
|
<listitem> <para> make dl_docbook </para> </listitem>
|
|
<listitem> <para> copy up to date doc files </para> </listitem>
|
|
</itemizedlist>
|
|
Then you can do
|
|
<screen>
|
|
cd doc/docbook; touch */*.html
|
|
</screen>
|
|
Do make install_win32 into /tmp or someplace:
|
|
<screen>
|
|
make install_win32 prefix=/tmp/bochs-2.4
|
|
</screen>
|
|
This copies all the files into /tmp/bochs-2.4 and then creates a
|
|
binary ZIP at /tmp/bochs-2.4.zip. Rename that bochs-2.4.win32-bin.zip.
|
|
</para>
|
|
<para>
|
|
Now make the NSIS installer package (the current script is known to work with NSIS 2.44)
|
|
<screen>
|
|
cd build/win32/nsis
|
|
</screen>
|
|
Unzip the binary ZIP file into bochs-$VERSION (must match Makefile) and
|
|
then run make.
|
|
<screen>
|
|
unzip ~/bochs-2.4.zip
|
|
make
|
|
</screen>
|
|
That gives an installer called <filename>Bochs-2.4.exe</filename>. Test and upload it.
|
|
</para>
|
|
</section>
|
|
<section><title>Building the release on Linux</title>
|
|
<para>
|
|
&FIXME; Rewrite for SVN
|
|
</para>
|
|
<para>
|
|
Do a clean checkout using anonymous cvs, so that the source tarball
|
|
will be all set up for anonymous cvs. First I'll create a clean
|
|
directory called "clean-anon".
|
|
<screen>
|
|
cvs -d:pserver:anonymous@bochs.cvs.sourceforge.net:/cvsroot/bochs login
|
|
cvs -z3 -d:pserver:anonymous@bochs.cvs.sourceforge.net:/cvsroot/bochs \
|
|
checkout -d clean-anon bochs
|
|
</screen>
|
|
Start with clean-anon which tracks the CVS head. Change its sticky tag
|
|
so that it sticks to the release tag.
|
|
<screen>
|
|
cp -a clean-anon bochs-2.4
|
|
cd bochs-2.4
|
|
cvs upd -P -r REL_2_4_FINAL
|
|
cd ..
|
|
tar czvf bochs-2.4.tar.gz --exclude CVS --exclude .cvsignore bochs-2.4
|
|
</screen>
|
|
The source TAR file bochs-2.4.tar.gz is ready to upload.
|
|
</para>
|
|
<para>
|
|
The RPM will be building using the configuration in .conf.linux with
|
|
a few parameters from <command>build/redhat/make-rpm</command>. Make any last minute changes
|
|
to .conf.linux. Any changes will go into the source RPM. The DLX Linux demo package
|
|
will be downloaded to the Bochs root directory if it is not already present there.
|
|
<screen>
|
|
./build/redhat/make-rpm | tee ../build.txt
|
|
</screen>
|
|
This produces two rpm files in the current directory. Test and upload.
|
|
</para>
|
|
</section>
|
|
<section><title>Creating a file release and uploading files on SF</title>
|
|
<para>
|
|
When you are ready with creating release packages you have to upload them using
|
|
the SF file manager feature. Create a subdirectory with the version number in
|
|
the <filename>bochs</filename> directory. Point the download destination to the
|
|
new directory and start uploading packages. The top of the <filename>CHANGES</filename>
|
|
file should be used as the release notes. After setting up the file properties the
|
|
new release is ready for download.
|
|
</para>
|
|
</section>
|
|
|
|
</section>
|
|
|
|
</chapter>
|
|
|
|
<chapter id="webmastering"><title>Webmastering</title>
|
|
|
|
<section id="project-webspace"><title>Bochs project webspace</title>
|
|
<para>
|
|
The Bochs project webspace is stored under the SF directory <filename>/home/project-web/bochs</filename>.
|
|
It can be accessed from the SF shell using SSH or with the commands <command>sftp</command>,
|
|
<command>scp</command> and <command>rsync</command>. Some parts of the directory
|
|
structure must be updated from the local CVS repository, others from Bochs SVN
|
|
(directories <filename>bochs</filename> and <filename>sfsite</filename>).
|
|
The online documentation, disk images and screenshots must be uploaded manually.
|
|
<table>
|
|
<title>Directory structure</title>
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>Location</entry>
|
|
<entry>Meaning</entry>
|
|
<entry>Update</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row><entry>cgi-bin</entry><entry>CGI scripts for the website</entry></row>
|
|
<row><entry>htdocs</entry><entry>root directory of the website</entry></row>
|
|
<row><entry>htdocs/doc/docbook</entry><entry>Bochs online documentation</entry></row>
|
|
<row><entry>htdocs/docs-html</entry><entry>old Bochs documentation</entry></row>
|
|
<row><entry>htdocs/guestos</entry><entry>disk images directly stored on the Bochs website</entry></row>
|
|
<row><entry>htdocs/screenshot</entry><entry>screenshots of Bochs running several guest operating systems</entry></row>
|
|
<row><entry>htdocs/svn-snapshot</entry><entry>link to current snapshot</entry></row>
|
|
<row><entry>htdocs/techspec</entry><entry>technical specifications of several hardware components</entry></row>
|
|
<row><entry>lxr</entry><entry>Bochs source browser</entry></row>
|
|
<row><entry>sfsite-cvsroot</entry><entry>local CVS repository</entry></row>
|
|
<row><entry>sitebin</entry><entry>shell scripts (e.g. for snapshot generation)</entry></row>
|
|
<row><entry>siteman</entry><entry>website manual pages</entry></row>
|
|
<row><entry>snapshot</entry><entry>SVN snapshot storage area</entry></row>
|
|
<row><entry>tmp</entry><entry>temp directory for shell scripts</entry></row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</para>
|
|
</section>
|
|
|
|
<section id="update-website"><title>Updating the Bochs website content</title>
|
|
<para>
|
|
The main HTML content of the Bochs website (except online documentation) is stored
|
|
in the <filename>sfsite</filename> directory of the Bochs SVN repository. Unlike
|
|
other SF projects you don't need to upload these files to the Bochs project webspace.
|
|
Running a simple SVN update on the SF shell is enough after the files have been
|
|
updated in the repository. Please see <link linkend="svn-write-access-setup">Setting
|
|
up SVN write access</link> for general instructions. The only difference is the
|
|
directory name <filename>sfsite</filename> instead of <filename>bochs</filename>.
|
|
The example below shows how to start the SF shell with SSH and to update the
|
|
HTML files.
|
|
<screen>
|
|
ssh -t vruppert,bochs@shell.sourceforge.net create
|
|
vruppert,bochs@shell.sourceforge.net's password:
|
|
|
|
Requesting a new shell for "vruppert" and waiting for it to start.
|
|
queued... starting...
|
|
|
|
This is an interactive shell created for user vruppert,bochs.
|
|
Use the "timeleft" command to see how much time remains before shutdown.
|
|
Use the "shutdown" command to destroy the shell before the time limit.
|
|
For path information and login help, type "sf-help".
|
|
|
|
[vruppert@shell-24002 ~]$ cd /home/project-web/bochs/htdocs/
|
|
[vruppert@shell-24002 htdocs]$ svn update
|
|
U index.html
|
|
Updated to revision 10752
|
|
[vruppert@shell-24002 htdocs]$ shutdown
|
|
Requesting that your shell be shut down.
|
|
This request will be processed soon.
|
|
[vruppert@shell-24002 htdocs]$
|
|
Broadcast message from root (Mon Oct 31 09:45:04 2011):
|
|
|
|
The system is going down for system halt NOW!
|
|
Connection to shell-24002 closed by remote host.
|
|
Connection to shell-24002 closed.
|
|
Connection to shell.sourceforge.net closed.
|
|
</screen>
|
|
</para>
|
|
</section>
|
|
|
|
<section id="update-svn-snapshot"><title>Updating the SVN snapshot</title>
|
|
<para>
|
|
The SVN snapshot
|
|
<footnote>
|
|
<para>The SVN snapshot link can be found on the bottom of the page
|
|
<filename>getcurrent.html</filename>.</para>
|
|
</footnote>
|
|
can be updated with SF shell access using SSH. There is a script
|
|
called <command>update-svn-snapshot.sh</command> that can do all the required steps
|
|
(checking out SVN, packing the source tree into one archive, updating the website
|
|
link). See previous section how to create a shell.
|
|
<screen>
|
|
cd bochs-web/sitebin/
|
|
./update-svn-snapshot.sh
|
|
</screen>
|
|
</para>
|
|
</section>
|
|
|
|
<section id="update-online-docs"><title>Updating the online documentation</title>
|
|
<para>
|
|
To update the online documentation, a file called <filename>bochsdoc.tar.gz</filename>
|
|
must be generated with the <command>make</command>. This file must be uploaded
|
|
to the location of the online documentation on SF using <command>scp</command>.
|
|
<screen>
|
|
cd doc/docbook
|
|
make bochsdoc.tar.gz
|
|
scp bochsdoc.tar.gz vruppert,bochs@web.sf.net:htdocs/doc/docbook
|
|
</screen>
|
|
After a successful upload, the HTML files must be unpacked from the SF shell.
|
|
See section <link linkend="update-website">Updating the Bochs website content</link>
|
|
how to create a shell.
|
|
<screen>
|
|
cd /home/project-web/bochs/htdocs/doc/docbook
|
|
tar xvzf bochsdoc.tar.gz
|
|
</screen>
|
|
The updated files can be accessed from the sidebar of the Bochs website.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="other-content"><title>other content</title>
|
|
<para>
|
|
&FIXME; sources, tmp
|
|
</para>
|
|
</section>
|
|
|
|
<section id="available-tools"><title>available tools</title>
|
|
<para>
|
|
&FIXME; sources, tmp
|
|
</para>
|
|
</section>
|
|
|
|
</chapter>
|
|
</book>
|