AdPlug core library
*******************

This manual documents the AdPlug core library, version 2.3.1.

   Copyright (C) 2002 - 2017 Simon Peter <dn.tlp@gmx.net>

     Permission is granted to copy, distribute and/or modify this
     document under the terms of the GNU Free Documentation License,
     Version 1.1 or any later version published by the Free Software
     Foundation; with no Invariant Sections, with the Front-Cover texts
     being "A GNU Manual," and with the Back-Cover Texts as in (a)
     below.  A copy of the license is included in the section entitled
     "GNU Free Documentation License."

     (a) The FSF's Back-Cover Text is: "You have freedom to copy and
     modify this GNU Manual, like GNU software.  Copies published by the
     Free Software Foundation raise funds for GNU development."

1 Introduction
**************

AdPlug is a free, multi-platform, hardware independent AdLib sound
player library, mainly written in C++.  AdPlug plays sound data,
originally created for the AdLib and Sound Blaster (OPL2/OPL3) audio
boards, on top of an OPL emulator or by using the real hardware.  No OPL
chip is required for playback.

1.1 Supported Formats
=====================

AdPlug implements unique file replayers for each supported format in
order to achieve the best possible replay quality.  Below is a list of
all currently supported file formats along with information about
possible replay issues.  Players marked as "preliminary" aren't
considered final by the author(s) and may contain many replay issues,
but are included for testing purposes anyway.

   * 'A2M': AdLib Tracker 2 by subz3ro
        * File format versions 1, 4, 5 and 8 are supported
        * Unimplemented commands (versions 1-4): 'FF1 - FF9, FAx - FEx'
        * Unimplemented commands (versions 5-8): 'Gxy, Hxy, Kxy - &xy'
        * In version 5-8 files, some parts of the flags byte are ignored
        * Only SixPack compressed and uncompressed files are supported
   * 'ADL': Westwood ADL File Format
   * 'AGD': Herbulot AdLib System AGD *(preliminary)*
   * 'AMD': AMUSIC Adlib Tracker by Elyssis
   * 'BAM': Bob's Adlib Music Format by Bob
   * 'BMF': Easy AdLib 1.0 by The Brain
   * 'CFF': BoomTracker 4.0 by CUD
   * 'CMF': Creative Music File Format by Creative Technology
   * 'CMF': SoundFX Macs Opera tracker by Linel
   * 'D00': EdLib by Vibrants
        * Bugs: Hard restart SR sometimes sounds wrong
   * 'DFM': Digital-FM by R.Verhaag
   * 'DMO': Twin TrackPlayer by TwinTeam
   * 'DRO': DOSBox Raw OPL Format
   * 'DTM': DeFy Adlib Tracker by DeFy
   * 'GOT': God of Thunder Music by Roy Davis of Adept Software
   * 'HA2': Herbulot AdLib System (version 2) *(preliminary)*
   * 'HSC': HSC Adlib Composer by Hannes Seifert, HSC-Tracker by
     Electronic Rats
   * 'HSP': HSC Packed by Number Six / Aegis Corp.
   * 'HSQ': Herbulot AdLib System SDB/AGD (HSQ packed)
   * 'IMF': Apogee IMF File Format by Apogee
   * 'IMS': IMPlay Song Format
        * Needs file 'implay.bnk' or 'standard.bnk' or 'FILENAME.bnk' in
          the same directory as loaded file, where FILENAME is the name
          of music file without extension
   * 'KSM': Ken Silverman's Adlib Music Format by Ken Silverman
        * Needs file 'insts.dat' in the same directory as loaded file
   * 'LAA': LucasArts AdLib Audio File Format by LucasArts
        * Bugs: Some volumes are a bit off
   * 'LDS': LOUDNESS Music Format by Andras Molnar
   * 'M': Ultima 6 Music Format by Origin
   * 'MAD': Mlat Adlib Tracker
   * 'MDI': AdLib MIDIPlay File Format
   * 'MID': MIDI Audio File Format
   * 'MKJ': MKJamz by M \ K Productions *(preliminary)*
   * 'MSC': AdLib MSCplay
   * 'MTK': MPU-401 Trakker by SuBZeR0
   * 'MUS': AdLib MIDI Music Format
        * Needs file 'FILENAME.snd' or 'FILENAME.tim' or 'timbres.snd'
          in the same directory as loaded file, where FILENAME is the
          name of music file without extension
   * 'RAD': Reality ADlib Tracker by Reality
   * 'RAW': RdosPlay RAW file format by RDOS
   * 'RIX': Softstar RIX OPL Music Format
   * 'ROL': AdLib Visual Composer by AdLib Inc.
        * Needs file 'standard.bnk' in the same directory as loaded file
   * 'S3M': Scream Tracker 3 by Future Crew
        * Bugs: Extra Fine Slides ('EEx, FEx') & Fine Vibrato ('Uxy')
          are inaccurate
   * 'SA2': Surprise!  Adlib Tracker 2 by Surprise!  Productions
   * 'SAT': Surprise!  Adlib Tracker by Surprise!  Productions
   * 'SCI': Sierra's AdLib Audio File Format by Sierra On-Line Inc.
        * Needs file '???patch.003' in the same directory as loaded
          file, where ??? are the first 3 characters of the loaded
          file's filename
        * Bugs: Some instruments are messed up
   * 'SDB': Herbulot AdLib System SDB *(preliminary)*
   * 'SNG': SNGPlay by BUGSY of OBSESSION
   * 'SNG': Faust Music Creator by FAUST
   * 'SNG': Adlib Tracker 1.0 by TJ
        * Needs file 'SONGNAME.ins' in the same directory as loaded
          file, where SONGNAME is the song's filename without '.sng'
          extension.
   * 'SOP': Note Sequencer by Lee Ho Bum (sopepos)
   * 'SQX': Herbulot AdLib System SDB (SQX packed)
   * 'VGM': Video Game Music 1.51 by Valley Bell
        * Supports OPL2, Dual OPL2 and OPL3 playback.
   * 'XAD': eXotic ADlib Format by Riven the Mage
   * 'XMS': XMS-Tracker by MaDoKaN/E.S.G
   * 'XSM': eXtra Simple Music by Davey W Taylor

   Whenever a player requires more files to be present in a given
directory, be especially careful under UNIX systems, because all file
names are case-sensitive.

1.2 Concepts
============

All of AdPlug's header files are installed under the directory 'adplug'
inside your specified include path.  Whenever a specific header file in
this manual is referred to, the filename with the path 'adplug/'
prepended is meant.

   AdPlug can be divided into 2 sections and 3 layers of functionality.
These are the "Playback" and "Sound generation" sections and the
"Frontend", "Mid-End" and "Backend" layers.

   The Frontend layer is simply your application itself, using AdPlug.
It is above of it all and does not belong to any particular section.
Anything that provides the user-interface to AdPlug or an interface to
another application is in the Frontend layer.

1.2.1 Playback section
----------------------

The Playback section is divided into the Mid-End and the Backend layers.
As a whole, it is responsible for making the sound files play back.

   The Mid-End layer provides the glue between the Frontend and the
Backend layers.  It provides methods and classes for these layers to
communicate.  The headers 'adplug.h', 'fprovide.h', 'players.h' and
'database.h' belong to the Mid-End layer.  From your application's point
of view, you only have to include the file 'adplug.h' in your source
files, which automatically includes all the other Mid-End headers.

   The Backend layer is responsible for reading and decoding the sound
files into OPL command data.  It then passes this data to the sound
generation section, which generates the final audio data.  The header
'player.h' and all player header files belong to the Backend layer.

1.2.2 Sound generation section
------------------------------

The Sound generation section is responsible for generating the OPL's
sound, according to the input of the Playback section.  This sound is
either routed back to the application for it to do something with it or
routed directly to a specific audio hardware.

   The following headers provide the interface to the sound generation
section: 'emuopl.h', 'temuopl.h', 'kemuopl.h', 'realopl.h',
'silentopl.h', 'analopl.h' and 'diskopl.h'.  All classes inside these
headers are derived from the abstract base class 'Copl', declared inside
the file 'opl.h', which provides the common interface for the Backend
layer of the Playback section.  This interface is not meant for the
Frontend layer (i.e.  your application).  Your application, however, has
to call special methods of these classes in order to route the data
back, if there is any.

   'emuopl.h' provides the class 'CEmuopl', which implements a virtual
OPL emulator, which automatically selects the best available OPL chip
emulation and type for each replayer.

   'temuopl.h' provides the class 'CTEmuopl', which is a wrapper class
around Tatsuyuki Satoh's fmopl OPL2 emulator, which generates wave audio
data to be routed back to the application.

   'kemuopl.h' provides the class 'CKemuopl', which is a wrapper class
around Ken Silverman's adlibemu OPL2 emulator, which generates wave
audio data to be routed back to the application.

   'realopl.h' provides the class 'CRealopl', which outputs to a real
hardware OPL2 or OPL3 chip.  No data is routed back to the application.
This class is currently only working on x86 hardware.

   'silentopl.h' provides the class 'CSilentopl', which is a dummy
OPL2/3, which generates nothing.  All data sent to it is forgotten
immediately.  No data is routed back to the application.

   'analopl.h' provides the class 'CAnalopl', which is the same as
'CRealopl', but also provides a 9-channel loudness pseudo-analyzer
interface for the application.  The loudness data is the only data
routed back to the application.

   'diskopl.h' provides the class 'CDiskopl', which is an OPL3 emulator
that does not output any sound to the soundcard, but instead writes all
received OPL commands to a file in the RdosPlay RAW format.

2 Basic Usage
*************

AdPlug provides convenience methods and classes inside its Mid-End layer
that make generic usage in your applications pretty easy.  This is most
probably all that you need.  For very advanced usage of particular
features of AdPlug, please refer to Advanced Usage.

   For basic usage, you need to include the header 'adplug.h' inside
your application's source code.  In addition, you need one of the
headers from the sound generation section, if you want sound output.

   'adplug.h' provides the class 'CAdPlug', which in turn provides the
load and playback facilities for the song files.  'CAdPlug' is a static
class, you do not need to instantiate an object of it.

2.1 Loading
===========

To load a supported file for playback, you use the method
'CAdPlug::factory(const std::string &FILENAME, Copl *OPL, ...)'.  The
method takes more arguments, but we don't need them for basic usage.
They are explained in Advanced Usage.

   The first argument, FILENAME, is a string object, containing the
filename of the sound file to be loaded with AdPlug.  The second
argument, OPL, is a pointer to an already initialized object from the
sound generation section of the library.

   The method returns a pointer to an initialized player object from the
Backend layer, or the NULL pointer if the file couldn't be loaded for
any reason.

   I guess FILENAME does not need any more explanation, so i will just
explain how to get an instance of a 'Copl' derived class:

   If you want to use the OPL emulator class 'CEmuopl', you have to
include the header 'emuopl.h' inside your application's source code.
'CEmuopl''s constructor looks like this: 'CEmuopl::CEmuopl(int RATE,
bool BIT16, bool USESTEREO)'.  The RATE argument specifies the playback
frequency rate in Hz.  The BIT16 argument specifies whether to create 8
bit or 16 bit wave audio data.  If it is set, 16 bit data is created.
The USESTEREO argument specifies whether to create stereo or mono audio
data.  If it is set, stereo data is created.

   If you want to use real hardware OPL2 output, you have to include the
header 'realopl.h' inside your application and use the class 'CRealopl'.
Its constructor just takes one optional argument, specifying the
hardware OPL2's base port, which is '0x388' by default.  As an option,
you can include 'analopl.h' instead, using the class 'CAnalopl', and
also use the analyzer interface instead.  This is explained in
Audio output.

   For no audio generation at all, include the header 'silentopl.h'
inside your application and use the class 'CSilentopl'.  Its constructor
does not take any arguments.

2.2 Playback
============

On successful operation, 'CAdPlug''s 'factory()' method returns a
pointer to an initialized player object from the Backend layer.  You use
this object to do the main song playback.  The important methods for
song playback are:

'void seek(unsigned long ms)'
     Use this to seek inside the song.  The only argument specifies the
     number of milliseconds to seek from the beginning of the song.

'bool update()'
     The most important method of them all.  You have to call this
     method in a loop.  As long as it returns 'true', the song has not
     ended yet.  At some point, it will start to always return 'false'.
     When it does this, the song has ended.  The song will play on (and
     is maybe already automatically rewound by the player itself), but
     you should use the 'rewind()' method to rewind it or stop playing.

'void rewind(int subsong = -1)'
     This method rewinds the song to the beginning of the subsong,
     specified by the only argument.  If no argument or '-1' is given,
     the currently selected subsong will be rewound.  If the player does
     not support subsongs, just don't provide an argument.

'float getrefresh()'
     Returns a float containing the player object's idea of with what
     frequency its 'update()' method should be called, in Hz.  This can
     change at any time, so you have to poll it before every call to
     'update()'.

'unsigned int getsubsongs()'
     Returns the number of subsongs of the currently loaded song.  If
     the player doesn't support subsongs, '1' is returned, representing
     the only "subsong".

2.3 Audio output
================

To actually generate some sound, you probably additionally have to make
some calls to the OPL object.  While the two hardware OPL2 output and
the silent OPL2 classes do not need any additional calls, the 'CEmuopl'
class provides methods for your application's readback of the generated
wave audio data.

   To get a buffer of wave audio data from the emulator, you have to
call the 'void CEmuopl::update(short *BUF, int SAMPLES)' method.  The
BUF argument is a pointer to a previously allocated memory block of the
size specified by the SAMPLES argument, in samples.  The method will
fill the specified amount of samples into the buffer.  Multibyte samples
have the machine's byte ordering.

   For easier and more uniform handling of the different OPL classes,
the 'Copl' base class also provides the 'update()' method.  For
subclasses that do not support read back of the audio data (and for
which this is not necessary), the method is empty and does nothing.

   The volume analyzing hardware OPL class 'CAnalopl' also has some data
readback methods:

'int getcarriervol(unsigned int v)'
     Returns the carrier's current volume of the OPL2 channel given as
     the only argument.
'int getmodulatorvol(unsigned int v)'
     Returns the modulator's current volume of the OPL2 channel given as
     the only argument.
'bool getkeyon(unsigned int v)'
     Returns whether a key-on event just happened on the OPL2 channel
     given as the only argument.

2.4 Chip support selection
==========================

With some OPL classes, like 'CEmuopl' and 'CRealopl', it is also
possible to select the chip type to support.  The hardware OPL class
will of course only be able to support those chip types that are
available in the system.  The emulated OPL class will be able to support
all chip types that it can emulate, provided the corresponding emulators
are compiled in.

   Three different OPL chip configurations can be identified, which can
all be support by AdPlug.

   * Single OPL2: This is the classic configuration found on the
     standard AdLib boards.  One OPL2 chip is supported.
   * Dual OPL2: This configuration was first implemented on the Sound
     Blaster Pro II boards.  Two independant OPL2 chips are on this
     card.
   * OPL3: This is the configuration found on all newer sound cards.  An
     OPL3 chip is supported, which is capable of emulating the other two
     configurations.

   In accordance to this, AdPlug's 'Copl' base class defines the
enumeration type 'ChipType', containing the items 'TYPE_OPL2',
'TYPE_OPL3' and 'TYPE_DUAL_OPL2'.

   OPL classes supporting multiple OPL interfaces have the
'settype(TYPE)' method, which can be used to set the chip interface to
support, using the 'ChipType' enumeration type.

   The chip type needs not to be set, as all supporting classes
automatically set the best available chip type, they can support, but
you may like to provide your user with this selection to suite his
listenting preferences.

   You may retrieve the currently supported chip type of a class by
using the method 'Copl::gettype()', which returns a variable of type
'ChipType'.  This method is defined in the 'Copl' base class and thus
supported by all of the OPL classes.

2.5 Getting Playback Information
================================

During playback, it is possible to gain some replay statistics with some
players.  The following methods are for getting playback informations:

'std::string gettype()'
     Returns a descriptive string containing the current file's format
     type.  This is for user information only and cannot be interpreted
     by software.

'std::string gettitle()'
     Returns a string holding the current song's title.  An empty string
     is returned if the song's format does not support title
     information.

'std::string getauthor()'
     Returns a string containing the current song's author name.  An
     empty string is returned if the song's format doesn't support
     author information.

'std::string getdesc()'
     Returns a string with the current song's description.  An empty
     string is returned if the song's format doesn't support a
     description.

'unsigned int getpatterns()'
     Returns the number of patterns in the current song.  '0' is
     returned if the format isn't pattern-based.

'unsigned int getpattern()'
     Returns the number of the currently playing pattern.  '0' is
     returned if the format isn't pattern-based.

'unsigned int getorders()'
     Returns the length of the order list of the current song.  '0' is
     returned if the format doesn't have an order list.

'unsigned int getorder()'
     Returns the number of the currently playing order list entry.  '0'
     is returned if the format doesn't have an order list.

'unsigned int getrow()'
     Returns the number of the currently playing row inside the current
     pattern.  '0' is returned if the format isn't pattern-based.

'unsigned int getspeed()'
     Returns the current speed setting of the song.  '0' is returned if
     the format doesn't support Protracker-based speed settings.

'unsinged int getinstruments()'
     Returns the number of defined instruments in the song.  This does
     not necessarily mean that any of the defined instruments has an
     instrument name attached to it.  '0' is returned if the format
     doesn't define any instruments.

'std::string getinstrument(unsigned int n)'
     Returns a string with the name of the instrument, specified by the
     only argument.  If the specified instrument doesn't have a name, an
     empty string is returned instead.

   These methods may be called at any time on an initialized player
object (i.e.  a file has already been loaded).  If a player or song does
not support any of the above methods, or their values are not meaningful
for a format, reasonable bogus values are returned instead.

   Some informational methods may not be called while the song itself is
playing because they change the internal replay state and will destroy
the running playback.  These are:

'unsigned long songlength(int subsong = -1)'
     This method returns the total length in milliseconds of the subsong
     given as the only argument.  If it is omitted or '-1', the
     currently selected subsong's length will be returned.

2.6 Example
===========

This is an example of a minimal playback utility that reads the filename
to be played from the commandline, uses the emulator to generate the
sound and writes the raw wave audio data back to disk:

#include <stdlib.h>
#include <stdio.h>
#include <adplug/adplug.h>
#include <adplug/emuopl.h>

#define RATE	44100   // Output frequency in Hz
#define BIT16	true    // true when 16bit samples should be used
#define STEREO	false   // true when stereo samples should be used
#define BUFSIZE	512     // Sound buffer size in samples

bool play(const char *filename, const char *output)
/*
 * Main playback function. Returns true on successful playback.
 * false is returned otherwise.
 */
{
  CEmuopl	opl(RATE, BIT16, STEREO);
  CPlayer	*p = CAdPlug::factory(filename, &opl);
  FILE		*f;
  short		buf[BUFSIZE];
  unsigned long	towrite, write;

  if(!p) return false;		// File couldn't be loaded

  f = fopen(output, "wb");
  while(p->update())
    for(towrite = RATE / p->getrefresh(); towrite; towrite -= write) {
      write = (towrite > BUFSIZE ? BUFSIZE : towrite);
      opl.update(buf, write);
      fwrite(buf, write, 2, f);
    }

  fclose(f);
  return true;
}

int main(int argc, char **argv)
{
  if(argc < 3) {
    cout << "usage: " << argv[0] << " <filename> <output>" << endl;
    exit(EXIT_FAILURE);
  }

  if(play(argv[1], argv[2]))
    exit(EXIT_SUCCESS);
  else
    exit(EXIT_FAILURE);
}

3 Advanced Usage
****************

This chapter explains very advanced usage of AdPlug.  You do not
normally need to read this if you just want to write a usual frontend
application for AdPlug.

3.1 Player Lists
================

There is another argument to the 'CAdPlug::factory(const std::string
&fn, Copl *opl, const CPlayers &PL = players, ...)' method.  The
argument PL is a reference to an object holding a "Player List".

   A player list object is an instance of the 'CPlayers' class (not to
be confused with the 'CPlayer' class).  The object can be constant and
even static (so it is possible to pass a temporary object, created on
the fly).

   The 'CPlayers' class itself is not much more than a specialized
'std::list' from the STL, holding pointers to objects of type
'CPlayerDesc', which are explained below.  Look into the STL
documentation for more information on 'std::list' functionality.

   The 'CPlayerDesc' class is essentially an information-holder,
describing all needed characteristics of a player class, to create an
instance and load a supported file with it.  It has two public
attributes:

'Factory factory'
     The 'Factory' type defines a pointer to a static method inside a
     class, inherited from 'CPlayer', taking a pointer to a
     'Copl'-derived object as the sole argument.  The meaning of this
     attribute is to provide a pointer to the factory method of the
     player class, which takes a pointer to an initialized
     'Copl'-derived object and returns a pointer to an initialized
     instance of the same player class, this 'CPlayerDesc' object
     describes.

'std::string filetype'
     This is a string containing the unique file type identifier of the
     player class, this 'CPlayerDesc' object describes.  The string
     normally contains the name of the file format, which the belonging
     player class handles.  This string should be unique.

   In addition, 'CPlayerDesc' has the following methods:

'CPlayerDesc(Factory f, const std::string &type, const char *ext)'
     A specialized constructor, which initializes the whole object at
     once.  The first argument is the pointer to the factory method of
     the accompanying player class.  The second argument is a string
     with the unique file type description, this player class handles.
     The last argument is a pseudo ASCIIZ string, holding many ASCIIZ
     strings with all file extensions to be associated with the
     accompanying player class.  To create such a string, include the
     leading '.' with all file extensions and terminate any file
     extension entry with a '\0' character.  Concatenate all entries one
     after the other, forming a string of strings.  Terminate the last
     entry with another '\0' character, so the final string is doubly
     terminated.

'void add_extension(const std::string &ext)'
     Adds the single file extension, passed as the only argument, to the
     list of file extensions, the accompanying player class handles.

'const char *get_extension(unsigned int n)'
     Returns a pointer to the N-th file extension string in the file
     extension list.  If N is out of range, a 'NULL'-pointer is returned
     instead.

   The 'CPlayers' class itself adds two more methods to the inherited
'std::list' interface:

'const CPlayerDesc *lookup_filetype(const std::string &ftype)'
     Returns a pointer to the first occurence of a 'CPlayerDesc' object
     with a file type of FTYPE, passed as the only argument.  This
     should also be the only object with that file type in the list.  If
     an object with the given file type is not found, a 'NULL'-pointer
     if returned instead.

'const CPlayerDesc *lookup_extension(const std::string &extension)'
     Returns a pointer to the first occurence of a 'CPlayerDesc' object,
     defining a file extension of EXTENSION, passed as the only
     argument.  Since file extensions are not necessarily unique in a
     'CPlayers' list, it is often much more efficient to use the search
     facilities provided by the STL.  If no object, specifying the given
     file extension, could be found, a 'NULL'-pointer is returned
     instead.

   Thus, the 'CPlayers' class holds a list of player descriptions.  This
list is used by the 'CAdPlug::factory()' method for the list of players
to try out on a given filename.  If no list is passed to the method, it
is 'CAdPlug::players' by default.  This list always holds all players
compiled into the AdPlug library and is also your starting point for
generating lists of your own.

3.2 File Providers
==================

"File Providers" are special classes that provide abstracted access to
files.  AdPlug's player classes request files using a file provider, in
their 'load()' methods.  This system is necessary because some players
require multiple files in their load stage and these files cannot all be
passed to their 'load()' method because the application's programmer
would have to be aware of each of the player's characteristics to know
which files to pass.

   A file provider class is derived from the abstract base class
'CFileProvider', which is declared in the header 'fprovide.h'.  This
class defines the following methods:

'binistream *open(std::string) const'
     An abstract virtual method that takes a string containing a
     filename as the only argument and returns an initialized input-only
     binary stream to that file.  The stream is always created with x86
     capabilities (i.e.  Little-Endian, IEEE-754 floating-point
     numbers).  If the file could not be opened, the 'NULL'-pointer is
     returned instead.

'void close(binistream *) const'
     An abstract virtual method that takes an input-only binary stream,
     which was formerly created with the 'open()' method, and closes
     this stream.

'bool extension(const std::string &filename, const std::string &extension)'
     This static method takes a string holding a filename as its first
     and another string holding a file extension as its last argument.
     It does a caseless compare of the given file extension to the
     extension of the given filename and returns 'true' if they match.
     'false' is returned otherwise.

'unsigned long filesize(binistream *f)'
     This static method takes an input-only binary stream, previously
     returned by the 'open()' method, and returns the total size, in
     bytes, of the associated file.  The stream's state is not altered.

   If you like to create your own file provider, you have to inherit
from this class and implement the methods 'open()' and 'close()'.
Remember to open the stream with x86 capabilites!  One situation in
which you would have to create your own file provider is when your
application doesn't load the files from the machine's local filesystem.
For example, when it supports reading from archives, you would use your
file provider to fetch and depack the file from the archive first,
before passing it to AdPlug.

   One derived file provider class is already defined in 'fprovide.h':
'CProvider_Filesystem'.  This file provider supports loading from the
machine's local filesystem.  File names are normal paths in the
operating system's common notation.

   A file provider object can also be passed to the 'CAdPlug::factory()'
method as last argument.  If it is not provided, it is a temporary
instance of 'CProvider_Filesystem' by default.  The method passes this
object on to all player objects' 'load()' methods, it tries to open the
file with.  The player objects' 'load()' methods also take the file
provider object as their last argument and default to
'CProvider_Filesystem' if none is given.

3.3 Using the Database
======================

AdPlug recently features a full-blown database, specialized for storing
information relevant to the replay of AdLib-specific music data.

   The database can be maintained by using the 'adplugdb' command.
Usage of this command is explained in its own manual page.

   The application's interface to the database is defined through the
'CAdPlugDatabase' class, residing in the header file 'database.h'.

   If you just want to pass a database for AdPlug to make use of it,
reading Usage with CAdPlug is sufficient.  If you want to write
a complete database manipulation application, you have to read the other
subsections as well.

3.3.1 Usage with CAdPlug
------------------------

You can pass AdPlug a database for it to get specific information about
a file.  Some file formats store insufficient information within
themselves and AdPlug uses the database to get the missing data.  You do
not need to include any more header files other than 'adplug.h' within
your application to do this.

   To hand a database to AdPlug, you have to initialize an instance of
'CAdPlugDatabase' first.  To do this, you just have to declare an object
of this class.  This creates an empty database for you.

   Additionally, for the database to be of any use to AdPlug, you have
to fill it with some records (see Records).  This is most
preferably done by loading an already existing database from a file.  To
do this, you use the 'load(std::string DB_NAME)' method of the class.
This will merge any records in the database file DB_NAME into your
database object.  You can merge any more database files, if you wish.
Only new records will be merged.  Duplicate records will be ignored.

   To hand your database to AdPlug, you simply call
'CAdPlug::set_database(CAdPlugDatabase *db)' and pass a pointer to your
database object as the only argument.  From now on, AdPlug will use your
database to do lookups for special information about some file types.
You have to keep your instance of the database until you close AdPlug
and free it by yourself after that.

3.3.2 Records
-------------

"Records" are the primary data containers in the database.  A record is
a very flexible object.  It can store virtually any number of different
data types, you can think of.

   All record classes are derived from the common abstract base class
'CAdPlugDatabase::CRecord'.  All records have at least three common
attributes:

'RecordType type'
     Specifies what type of data this record holds.  'RecordType' is an
     enumeration variable with the following values:

     'Plain'
          This record doesn't store any more information than the three
          standard attributes.
     'SongInfo'
          This record additionally stores song name and author
          information.
     'ClockSpeed'
          This record additionally stores timer clock speed information.

'CKey key'
     This is the unique key, allocated for any record in the database.
     See Keys.

'std::string filetype'
     Holds the unique file type of the file associated with the record.
     This value is taken from the player list (see Player Lists).

   The common base class 'CAdPlugDatabase::CRecord' defines a static
method 'factory(RecordType type)' for application usage that returns a
pointer to a newly allocated 'CRecord' object, or the 'NULL'-pointer if
an error occured.  You pass the type of the record to be created as the
only argument.

   All other public methods are meant for internal use of the database
only and should not be called from an application.  They are explained
here anyway, for informational purposes:

'CRecord *factory(binistream &in)'
     Another factory method that takes a reference to an input-only
     binary stream as the only argument.  It tries to extract a record
     from the stream's current position, initializes a new record object
     with the data and returns a pointer to that record object.  The
     'NULL'-pointer is returned if the record type couldn't be
     determined from the stream's data.

'void write(binostream &out)'
     Writes the record's contents to the output-only binary stream,
     referenced by the only argument.

'bool user_read(std::istream &in, std::ostream &out)'
     Attaches to the input and output streams, referenced by the first
     and second arguments and tries to prompt an apparent user for the
     relevant data input.

'bool user_write(std::ostream &out)'
     Attaches to the output stream, referenced by the only argument and
     writes the record's contents in human-readable form to it.

'void read_own(binistream &in)'
'void write_own(binostream &out)'
'bool user_read_own(std::istream &in, std::ostream &out)'
'bool user_write_own(std::ostream &out)'
     Abstract virtual base methods to be inherited by the real record
     classes to read and write their own data, in both binary and
     human-readable ways.

'unsigned long get_size()'
     Abstract virtual base method to be inherited by the real record
     classes to report the size of the extra data defined by them.

3.3.3 Keys
----------

"Keys" are CRC32:CRC16 pairs that uniquely identify a file's contents
and are used to associate a record with a file.  Only if the file's key
match with the record key, that record is actually used for that file.

   Keys are stored in key objects, which are instances of the
'CAdPlugDatabase::CKey' class.  The class has two attributes, 'crc16'
and 'crc32' which store the two CRC values, respectively.  It also has
the following methods:

'CKey()'
     A constructor that creates an empty key object.
'CKey(binistream &in)'
     A constructor that creates a key from the contents of the
     input-only binary stream, referenced by the only argument.

'bool operator==(const CKey &key)'
     Operator that compares two key objects and returns 'true' when they
     are equal.  'false' is returned otherwise.

3.3.4 Players using the Database
--------------------------------

The following players make active use of the database:

Apogee IMF
     The IMF player uses the database to find out about the timer clock
     speed of a file, since this data is not stored in the file itself.

3.3.5 Direct Usage
------------------

The following methods are for application usage of the database:

'bool load(std::string db_name)'
'bool load(binistream &f)'
     Two versions to load a database.  The first method takes a string
     containing a file name of a file from which the database is loaded.
     The second method takes a reference to an input-only binary stream
     to load the database from.

'bool save(std::string db_name)'
'bool save(binostream &f)'
     Two versions to save the database.  These work analogous to the
     'load()' methods, above.

'bool insert(CRecord *record)'
     Inserts the record object, pointed to by the only argument, into
     the database and returns 'true' on successful operation.  'false'
     is returned otherwise.  Duplicate record entries (i.e.  records
     that have the same key) cannot be inserted into the database and
     old ones will not automatically be overwritten by the new ones with
     this method.  'false' is returned in this case.

'void wipe(CRecord *record)'
'void wipe()'
     Two versions of a method to remove (wipe) a record from the
     database.  The first version takes a pointer to a record object as
     the only argument and removes exactly this record from the
     database.  The record object itself is deallocated, too.  Do not
     reference it again!  If the record object is not in the database,
     nothing is done.  The second version removes the record at the
     current position in the database.

'CRecord *search(CKey const &key)'
     Takes a reference to a key object, searches for a record with the
     same key value in the database and returns a pointer to this
     record.  The 'NULL'-pointer is returned if the record could not be
     found.

'bool lookup(CKey const &key)'
     The same as 'search()', but instead of returning a pointer to the
     record, it just positions the internal database pointer to the
     corresponding record.  Returns 'true' if the record could be found
     and 'false' otherwise.

'CRecord *get_record()'
     Returns a pointer to the record at the current position in the
     database.  The 'NULL'-pointer is returned if an error occured.

'bool go_forward()'
     Advances the internal position in the database by one record.
     Returns 'true' on success, 'false' otherwise.
'bool go_backward()'
     The same as 'go_forward()', but goes backward by one record.
'void goto_begin()'
     Goes to the beginning (i.e.  the first record) of the database.
'void goto_end()'
     Goes to the end (i.e.  the last record) of the database.

3.4 Without CAdPlug
===================

It is also possible to only use specific players from the AdPlug
library, without using the 'CAdPlug' class to cycle through them all.

   If you just want to use a single player class from the library, you
only include that player's header file in your application's source
code.

   You can construct an instance of that player by either using its
constructor or by using the 'factory()' method of that class.  Both have
the same syntax and take a pointer to an initialized 'Copl'-derived
object.

   Use the player's 'load()' method to load a file.  It takes a filename
as the first argument and, optionally, a file provider class as its last
argument.

   All other methods have already been explained in the text above.

4 Hacking
*********

This chapter gives some coding guidelines for people wishing to hack
around in AdPlug.  Be sure to also read the overall and system-specific
'INSTALL' files in the distribution's base directory to learn more about
the build systems.

4.1 Coding Style
================

I do not really enforce any coding style guidelines (i don't adhere to
any style guidelines myself, so...  ;) ), but it would be nice if you
follow the overall coding style, used throughout most of AdPlug's source
files.  If you don't, that's perfectly okay, too.

   Most of today's "super-intelligent" editors, like MSVC's one or GNU
Emacs' cc-mode, have their own idea of what the code has to look like,
anyway.  And since most people tend to use these, there's no point in
torturing them to always having to change anything their editor thinks
it knows better.  ;)

4.2 Debug Logging
=================

AdPlug recently offers centralized debug log management.  If you like to
implement debug logging inside your code, please follow these
guidelines:

   To implement debug logging, '#include "debug.h"' in your code (this
header is _not_ being installed with the rest of the AdPlug header files
into your standard include directory!  It is only available in AdPlug's
'src/' subdirectory!).

   'debug.h' is C code, so it is useable from both C and C++ sources.
The only function you have to use is the 'LogWrite(fmt, ...)' function.
'LogFile()' is used by AdPlug internally.  'LogWrite()' works exactly
like 'printf()', instead that it writes to a logfile, rather than on the
console.

   Please format your log messages like this:

   * If your method/function is going to output a lot of debug info
     (i.e.  more than one line), please put a 'LogWrite()' directly at
     the beginning of your function, which looks like this:

          LogWrite("*** yourclass::yourmethod(PARAM1, PARAM2, ...) ***\n");

     And put the following line before every return from your function:

          LogWrite("--- yourclass::yourmethod ---\n");

     This way, one can easily inspect the logfile and know to which
     function every logfile-line belongs.  The '***' lines mark the
     start of a function, and the '---' lines mark the end.

     Please substitute PARAM* with the corresponding parameter values of
     your function, if that is reasonable.  For example, it won't help
     much to log a pointer value -- just put something bogus or helpful
     there, or noting (i.e.  just a comma, so the logfile reader knows,
     to which parameters the other values correspond).  But logging the
     values of passed ints or strings could be very helpful.

   * If your method/function is going to output just one line, format
     the line something like this:

          LogWrite("yourclass::yourmethod(PARAM1, PARAM2): your message\n");

     You don't need the '***' and '---' beginning and end markers then.

   * For threads, there is no way but to prefix any line with the
     function name, because these messages will be sprayed throughout
     the logfile.

5 Player development
********************

Before you try to write a new player for AdPlug, be sure to also read
through Hacking.

5.1 Before the work
===================

Your player normally consists of two files (the '.h' & '.cpp' files) and
you normally name them by the file extensions, your player handles.  For
example, the HSC player consists of the files 'hsc.cpp' & 'hsc.h',
because it handles '.hsc' files.  This is the same with your player
class name.  Thus, the HSC player's class is called 'ChscPlayer'.  If
any of these names happens to be already taken for other purposes, just
name your player something else, appropriately.

   'player.h' contains the abstract player interface.  You have to
include it in your player to communicate with AdPlug.  It also contains
some very helpful structures for use in your player.  You don't need to
use the structs, but you have to use the methods provided by the 'opl'
object (declared in 'opl.h', but automatically included from 'player.h')
inside the player class to do the OPL I/O and initialization work.

5.2 Main work
=============

All you have to do now is to inherit the 'CPlayer' class into your own
player class and fill the abstract methods with code.  You at least have
to fill in the following methods:

     bool load(const std::string &filename, const CFileProvider &fp);
     bool update();
     void rewind(int subsong);
     float getrefresh();
     std::string gettype();

   The other methods from 'CPlayer' just serve informational purposes
(as does 'gettype()', but it's required anyway) for AdPlug's info box
and needn't to be filled.  It would be nice if you fill them anyway, if
that's reasonable for your player.

   There's one more public method you have to define in your player
class:

     static CPlayer *factory(Copl *newopl);

   Since it is static, it isn't already virtually defined in the
'CPlayer' class and you have to add it manually.  This method should
return a pointer to a freshly initialized object of your player class.
If any errors occured (e.g.  not enough memory), return '0' instead.

   Return true from your 'load()' method, if the file was loaded
successfully, or false if it couldn't be loaded for any reason (e.g.
because AdPlug passed a wrong file to your player).  Your 'update()'
method will be called with the frequency, you return from your
'getrefresh()' method, in Hz.  Return true from 'update()' if your
module hasn't ended yet.  If it looped or ended, return false from that
point, but play further for any subsequent calls to 'update()'.  AdPlug
will rewind or stop your player by itself, using the 'rewind()' method,
when necessary.

   AdPlug passes the number of the subsong, it wants to play next, to
the 'rewind()' method of your player.  This can be any value from '0' to
the value returned by 'getsubsongs()'.  If you haven't provided your own
'getsubsongs()', AdPlug will presume your player doesn't have support
for subsongs.  In that case, AdPlug will always 'rewind(0)'.  Please
ignore any value passed to 'rewind()' that is out of spec for your
player.  This should virtually never happen, but who knows.  If a value
of '-1' is given as an argument, you should rewind the currently playing
subsong.

   After initializing your player (either by a call to 'factory()' or by
creating an instance by itself), AdPlug normally first calls 'load()'
and then 'getrefresh()' and 'update()' in a loop until something happens
(i.e.  the user stops playback or the song ends).  'rewind()' and all
the informational methods can be called anytime in between the other
calls, but of course only after 'load()' has been called.

   You can add your own constructors, destructors and methods to your
player object, as you like.  AdPlug won't care in any way.

5.3 Loading and File Providers
==============================

The 'load(const std::string &filename, const CFileProvider &fp)' method
needs some special explanation.  This method takes two arguments.  The
first is a reference to a string containing the filename of the main
file for your player to load.  This is the filename the user selected in
the frontend (maybe altered by the frontend, but not by AdPlug) and does
not need to have any meaning to your player.

   To finally load your files to get to their data, you have to request
them.  This is done through a "File Provider".  A reference to a file
provider is always passed as the second argument to your 'load()'
method.  You will most likely want to load the file, using the filename
passed as the first argument.  To do this, you simply call 'binistream
*f = fp.open(filename)'.  This method returns a pointer to an open,
input-only binary stream of the requested file.  You can now operate on
this stream, using its standard interface (refer to the manual of the
binary I/O stream class library for further information).  When you're
done loading your file, don't forget to call 'fp.close(f)' to close it
again.  It is very important to do this anytime you leave your 'load()'
method!  Any streams not closed will be left open for the whole lifetime
of the controlling process!

   Don't worry about the passed filename.  It normally doesn't need to
have any meaning to your player.  The file provider will know how and
from where to open the file.

   'fp.open()' returns a null-pointer if something went wrong (e.g.
file not found or access denied, etc.).  If this happens, return 'false'
from your 'load()' method immediately.  You do not have to call
'fp.close()' in this case.

   The 'CFileProvider' class offers two convenience methods.  These are
'unsigned long filesize(binistream *f)' and 'bool extension(const
std::string &filename, const std::string &extension)'.

   'filesize()' returns the size in bytes of the stream, pointed to by
'f', without altering it otherwise.  'extension()' does a filename
extension check as follows: The first argument is a reference to a
string containing a filename.  The second argument is a reference to a
string containing a file extension to check for.  If the passed filename
has got exactly this extension (caselessly), the method returns 'true'.
'false' is returned otherwise.

5.4 Sound generation
====================

You generate sound by using the 'Copl::write(REG, VAL)' method of the
'Copl' class, which has been passed to your constructor.

   REG is the number of the register of the OPL chip, you want to write
data into.  VAL is the value to write into it.  There is no method to
read back written data from an OPL chip, as this also was not possible
with the original hardware.  Log all data into an array if you have to
remember written values.

   If your player supports the dual-OPL2 or OPL3 configurations, you can
use the method 'Copl::setchip(N)' to set the output chip number, all
subsequent 'write()' methods will write to.  As two chips can be
supported at maximum, the value of N may only be 0 or 1 for the first or
the second chip, respectively.

   Before switching to another chip, your player always has to make sure
that the configuration, you are going to address, is supported by the
current OPL class.  This can be done by calling the 'Copl::gettype()'
method, which will return the currently supported OPL chip type as an
enumeration of type 'Copl::ChipType'.

   If the desired configuration is not supported, your player should
support playback on any of the other configurations.  Your player should
never switch to another OPL chip when this is not actually supported by
the OPL class!  The sound will be totally messed up.

6 Protracker based players
**************************

If you want to create a player for a Protracker-derivative format, the
generic Protracker player 'CmodPlayer' that comes with AdPlug can be of
great help.  It supports all standard Protracker features, plus a good
set of extensions to cope with most derivative formats.

   When writing a player for a Protracker-derivative format, it is
almost always better to use and extend the 'CmodPlayer' class, instead
of writing a whole new player.

6.1 Features
============

In addition to handling your data just like the original Protracker
would, AdPlug's generic Protracker player has the following extra
features:

   * Special Arpeggio lists, compatible with the SA2 format.
   * Extendable set of up to 256 note commands.
   * Simulates many different tracker flavors.
   * Arbitrary numbers of rows, patterns, tracks, instruments and
     orderlist entries.

   The only current limitation is that it has a maximum 9 voice
polyphony, which isn't really a limitation, since the OPL2 is just 9
voices, anyway.

6.2 Defaults
============

For historical reasons, 'CmodPlayer' sets defaults to some values, so
they need not be initialized.  These are:

   * The orderlist is preallocated to 128 entries.
   * The patterndata is preinitialized to 64 patterns with 9 channels
     and 64 rows each.
   * The instruments array is preallocated to 250 instruments.
   * All flags are cleared (simulates Protracker flavor).

   These are mostly standard Protracker limits.  They stem from the
original SA2 defaults, for which this was once the player.  Look at the
'CmodPlayer' constructor for info on which variables are involved.

6.3 Protracker Loaders
======================

When you decided to extend the 'CmodPlayer' class, instead of writing a
whole new player, you do this by writing a loader for it.  This is done
very similarily to writing a unique player for AdPlug.  Thus, reading
the Player development chapter is recommended for this task,
too.

   Instead of naming your player class 'CxxxPlayer', you should name it
'CxxxLoader' or something appropriate if the name is already taken.  You
then publicly inherit the 'CmodPlayer' class and fill the missing
methods with code.  These are now:

     static CPlayer *factory(Copl *newopl);
     bool load(const std::string &filename, const CFileProvider &fp);
     float getrefresh();
     std::string gettype();

   Plus maybe some (or all) of the other informational methods, listed
in the Player development chapter.  Refer also to that chapter
to see what the above methods are about.

6.4 Designing your Loader
=========================

File validation and initial loading is the same as it would be with any
other player.  One speciality is that you have to call 'rewind(0)'
whenever you completely loaded a valid file.  Don't call it when you
just exit your loader because the file was invalid!

   The Protracker player needs at least an orderlist, the patterns and
the instruments to function.  Most of the time, you have to convert
these between your file's ordering and 'CmodPlayer''s internal ordering.
Look in the file 'protrack.cpp', 'CmodPlayer''s actual sources, for a
list on how these constructs are ordered internally.

   Also, please look up the Defaults section to see if you need
to reallocate any of the defaults.

   There are some variables that you have automatically inherited with
your new loader and that you have to set in order to tell the Protracker
player something about your loaded module.  These are the following:

'length'
     The orderlist length.  When 'CmodPlayer''s orderlist pointer equals
     or is bigger than this length, it is automatically wrapped around
     to 'restartpos'.  This variable has no default.

'trackord'
     Refer to Loading Patterns below on this one.  This variable
     defaults to '0'.

'restartpos'
     The restarting position in the orderlist, when 'length' is
     exceeded.  This variable has no default.

'activechan'
     A flag array, telling the player which channels in every pattern
     are actually active and to be played.  The ordering of this
     variable is a bit awkward, so be careful!  It is a 32-bit 'unsigned
     long', holding the activeness of a channel in each of its bits,
     _starting at the highest order bit_.  It can hold values for up to
     32 channels.  So, to set channel 0 active, you have to set bit 31
     (counting from bit 0) to '1' and so on.  Setting any bits for
     channels that are not defined has no effect.  This variable
     defaults to all bits set to 1, meaning all channels are enabled.

'initspeed'
     Initial protracker-compatible speed setting.  This variable
     defaults to '6', the standard Protracker speed setting.

'bpm'
     Initial protracker-compatible bpm (sometimes called tempo) setting.
     This variable has no default.

'flags'
     Refer to Special Flags below.  This variable defaults to
     'Standard', which sets standard Protracker defaults and imposes no
     specialities.

'nop'
     The number of patterns in your module.  You don't need to set this
     value.  If you leave it at '0', 'CmodPlayer' will automatically
     determine the number of _accessed_ patterns (which need not be the
     same as the actual number of patterns in your module) from the
     orderlist, in the 'rewind()' method.  The value serves only
     informational purposes, anyway.  It is not needed for the actual
     playback.  If you think you know better than 'CmodPlayer', feel
     free to set it to something else and 'CmodPlayer' won't touch it
     anymore and display your value instead.  This variable defaults to
     '0'.

6.5 Loading Patterns
====================

AdPlug's Protracker player stores the tracks (or channels, as some may
call them), that make up a pattern, in a way that makes it possible for
you to reorder and reuse them in an easy way.  This also makes storing
patterns in the classic way a bit awkward.

   If you just want to store your tracks the classic Protracker way
(usually the case), first use the 'CmodPlayer::init_trackord()' method
to do an initial setup.  Then store your tracks in a sequential manner,
counting from 0, in the 'tracks' array.  That is, for the first 9
channels of your first pattern, use 'tracks[0..9]'.  The second
dimension of this array holds the rows of each channel.  For the next 9
channels, you use 'tracks[10..19]', and so on.

   If you want to make use of the reorder/reuse feature of the
'trackord' array, please refer to the 'sa2.cpp' source file.  This
player utilizes this method.  Basically, the 'trackord' array tells the
player which track out of the 'tracks' array it has to insert for each
of the 9 tracks of a pattern.  Thus, the first dimension of this array
stands for the corresponding pattern and the next dimension holds the
entries for all the 9 tracks.

   'CmodPlayer' orders its note data, in the 'Tracks' struct, the
following way:

   'note' holds the note value.  A value of '0' means 'no note'.  A
value of '127' means 'key off'.  Values from '1' to '96' are actual
notes to be played.  Everything else is ignored.  The octaves are
encoded with the actual note values.  Thus, notes from '1' to '12' are
the 12 halftone-steps of the first, lowest octave, '13' to '24' are
those of the next lowest octave, and so on.  Refer to the source code to
see which frequencies are actually associated with the note values.

   'inst' holds the instrument to be played with this note.  Again, a
'0' value means no instrument is associated with this note and the last
active instrument is taken instead.  Otherwise, the instrument with the
number 'inst' minus 1 is fetched from the 'inst' array (it's 0 based).

   'command' holds the command to be issued with this note.  All
available commands are listed in the following table:

Value     Command description               Parameters                 Range
----------------------------------------------------------------------------------------
'  0xy'   Arpeggio                          'xy'=1st note,2nd note     '[0-F]'
'  1xx'   Frequency slide up                'xx'=sliding speed         '[0-FF]'
'  2xx'   Frequency slide down              'xx'=sliding speed         '[0-FF]'
'  3xx'   Tone portamento                   'xx'=sliding speed         '[0-FF]'
'  4xy'   Vibrato                           'xx'=speed,depth           '[0-F]'
'  5xy'   Tone portamento & volume slide    'xy'=vol up|vol down       '[0-FF]'
'  6xy'   Vibrato & volume slide            'xy'=vol up|vol down       '[0-FF]'
'  7xx'   Set tempo                         'xx'=new tempo             '[0-FF]'
'  8--'   Release sustaining note
'  9xy'   Set carrier/modulator volume      'xy'=car vol|mod vol       '[0-F]'
' 10xy'   SA2 volume slide                  'xy'=vol up|vol down       '[0-F]'
' 11xx'   Position jump                     'xx'=new position          '[0-FF]'
' 12xx'   Set carr.  & mod.  volume         'xx'=new volume            '[0-3F]'
' 13xx'   Pattern break                     'xx'=new row               '[0-FF]'
' 14??'   Extended command:
'   0y'   Set chip tremolo                  'y'=new depth              '[0-1]'
'   1y'   Set chip vibrato                  'y'=new depth              '[0-1]'
'   3y'   Retrig note                       'y'=retrig speed           '[0-F]'
'   4y'   Fine volume slide up              'y'=vol up                 '[0-F]'
'   5y'   Fine volume slide down            'y'=vol down               '[0-F]'
'   6y'   Fine frequency slide up           'y'=freq up                '[0-F]'
'   7y'   Fine frequency slide down         'y'=freq down              '[0-F]'
'   8y'   Pattern delay (rows)              'y'=rows to delay          '[0-F]'
' 15xx'   SA2 set speed                     'xx'=new speed             '[0-FF]'
' 16xy'   AMD volume slide                  'xy'=vol up|vol down       '[0-F]'
' 17xx'   Set instrument volume             'xx'=new volume            '[0-3F]'
' 18xx'   AMD set speed                     'xx'=new speed             '[0-FF]'
' 19xx'   RAD set speed                     'xx'=new speed             '[0-FF]'
' 20xx'   RAD volume slide                  'xx'=vol up/down           '[0-FF]'
' 21xx'   Set modulator volume              'xx'=new volume            '[0-3F]'
' 22xx'   Set carrier volume                'xx'=new volume            '[0-3F]'
' 23xx'   Fine frequency slide up           'xx'=freq up               '[0-FF]'
' 24xx'   Fine frequency slide down         'xx'=freq down             '[0-FF]'
' 25xy'   Set carrier/modulator waveform    'xy'=carr wav|mod wav      '[0-3,F]'
' 26xy'   Volume slide                      'xy'=vol up|vol down       '[0-F]'
' 27xy'   Set chip tremolo/vibrato          'xy'=tr depth|vb depth     '[0-1]'
' 28xy'   DTM frequency slide               'xy'=frames up|down        '[0-F]'
' 29xx'   Pattern delay (frames)            'xx'=frames to delay       '[0-FF]'
'255--'   No operation (NOP)

   The 'param1' and 'param2' variables hold the command's parameters.
These are command-dependant.  Refer to the table above to see what they
do with each of the commands and their value ranges.  An 'xx' in the
_Parameters_ column means that 'param1' and 'param2' form one 2-digit
parameter, with 'param1' being the leftmost decimal.  Otherwise, 'x'
refers to 'param1' and 'y' to 'param2'.

6.6 Loading Instruments
=======================

For the instrument data, 'CmodPlayer' stores it in the 'inst[].data[]'
array, in the following way:

Index   Operator    Description                                        Register
--------------------------------------------------------------------------------
0       Channel     (Panning) / Feedback strength / Connection type    '0xc0'
1       Modulator   Tremolo / Vibrato / Sustain / KSR / Multiple       '0x20'
2       Carrier     Tremolo / Vibrato / Sustain / KSR / Multiple       '0x23'
3       Modulator   Attack Rate / Decay Rate                           '0x60'
4       Carrier     Attack Rate / Decay Rate                           '0x63'
5       Modulator   Sustain Level / Release Rate                       '0x80'
6       Carrier     Sustain Level / Release Rate                       '0x83'
7       Modulator   Wave Select                                        '0xe0'
8       Carrier     Wave Select                                        '0xe3'
9       Modulator   Key scaling level / Operator output level          '0x40'
10      Carrier     Key scaling level / Operator output level          '0x43'

   There are three extensions to the standard instrument data.  These
are also stored within the 'inst[]' array.

  1. The _Special Arpeggio_.  This is explained in the Special Arpeggio
     section, below.

  2. The 'slide' variable.  This is a pre-slide value that is always
     added to the frequency of the note, whenever this instrument is to
     be played.

  3. The 'misc' variable.  This is just the holder for the value of the
     0xbd register (i.e.  the "drums'n'misc" register) of the OPL.

6.7 Special Flags
=================

The 'flags' variable holds special flags to change the behaviour of the
player.  These are:

'Standard'
     Act like standard Protracker would.  This is the default.

'Decimal'
     Command parameters are decimal values, not hexadecimal.  For split
     parameter commands (i.e.  commands with two parameters, like
     '0xy'), this has no effect, since decimal values would be from '0'
     to '9', anyway.  But commands that take both parameters as one
     value (i.e.  like '1xx') now take values from '0' to '99' and
     handle them properly (i.e.  decimal wrap-around is now at '9' to
     '10' and not at 'F' to '10').

'Faust'
     Treat the files like _Faust Music Creator_ does.  This tracker uses
     a different volume handling scheme.  In standard Protracker, the
     volume is computed as follows:

          final volume = channel volume = instrument volume

     In _Faust Music Creator_, it is done like this:

          final volume = (channel volume + instrument volume) / 2

'NoKeyOn'
     This prevents the OPL key off/on toggle on every newly played note.
     Some trackers require it that way...

'Opl3'
     Sets the player into OPL3 mode.  Extended register settings of the
     OPL3 become effective and the player initializes the OPL chip to
     OPL3 mode.  This has no effect if the hardware does not support
     OPL3 features.  Be careful to set panning information in register
     '0xc0' or else no sound will appear.

'Tremolo'
     Sets tremolo depth to 4.8dB upon each 'rewind()'.

'Vibrato'
     Sets Vibrato depth to 14 cents upon each 'rewind()'.

'Percussion'
     Enables the OPL percussion mode.

   These flags can be set and unset at any time.  To set a flag, just
binary _OR_ it with the 'flags' variable.  Use the 'enum Flags' data
type, defined in the 'CmodPlayer' class for this purpose.

6.8 Special Arpeggio
====================

To use the _Special Arpeggio_ facility, you have to initalize it first.
Use the 'init_specialarp()' method for this purpose.  'CmodPlayer''s
deconstructor automatically handles the deinit for you.

   The special arpeggio uses the 4 variables 'arpstart', 'arpspeed',
'arppos' and 'arpspdcnt' of the 'Instrument' struct.

   [TODO: actually explain.  Refer to sa2.[cpp,h] and the original SA2
docs in the meantime.  The following table summarizes the special
commands.]

Value   Command description
------------------------------------
'252'   Set carr.  & mod.  volume
'253'   Release sustaining note
'254'   Arpeggio loop
'255'   End of special arpeggio

Appendix A Copying This Manual
******************************

A.1 GNU Free Documentation License
==================================

                        Version 1.1, March 2000

     Copyright (C) 2000 Free Software Foundation, Inc.
     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA

     Everyone is permitted to copy and distribute verbatim copies
     of this license document, but changing it is not allowed.

  0. PREAMBLE

     The purpose of this License is to make a manual, textbook, or other
     written document "free" in the sense of freedom: to assure everyone
     the effective freedom to copy and redistribute it, with or without
     modifying it, either commercially or noncommercially.  Secondarily,
     this License preserves for the author and publisher a way to get
     credit for their work, while not being considered responsible for
     modifications made by others.

     This License is a kind of "copyleft", which means that derivative
     works of the document must themselves be free in the same sense.
     It complements the GNU General Public License, which is a copyleft
     license designed for free software.

     We have designed this License in order to use it for manuals for
     free software, because free software needs free documentation: a
     free program should come with manuals providing the same freedoms
     that the software does.  But this License is not limited to
     software manuals; it can be used for any textual work, regardless
     of subject matter or whether it is published as a printed book.  We
     recommend this License principally for works whose purpose is
     instruction or reference.

  1. APPLICABILITY AND DEFINITIONS

     This License applies to any manual or other work that contains a
     notice placed by the copyright holder saying it can be distributed
     under the terms of this License.  The "Document", below, refers to
     any such manual or work.  Any member of the public is a licensee,
     and is addressed as "you".

     A "Modified Version" of the Document means any work containing the
     Document or a portion of it, either copied verbatim, or with
     modifications and/or translated into another language.

     A "Secondary Section" is a named appendix or a front-matter section
     of the Document that deals exclusively with the relationship of the
     publishers or authors of the Document to the Document's overall
     subject (or to related matters) and contains nothing that could
     fall directly within that overall subject.  (For example, if the
     Document is in part a textbook of mathematics, a Secondary Section
     may not explain any mathematics.)  The relationship could be a
     matter of historical connection with the subject or with related
     matters, or of legal, commercial, philosophical, ethical or
     political position regarding them.

     The "Invariant Sections" are certain Secondary Sections whose
     titles are designated, as being those of Invariant Sections, in the
     notice that says that the Document is released under this License.

     The "Cover Texts" are certain short passages of text that are
     listed, as Front-Cover Texts or Back-Cover Texts, in the notice
     that says that the Document is released under this License.

     A "Transparent" copy of the Document means a machine-readable copy,
     represented in a format whose specification is available to the
     general public, whose contents can be viewed and edited directly
     and straightforwardly with generic text editors or (for images
     composed of pixels) generic paint programs or (for drawings) some
     widely available drawing editor, and that is suitable for input to
     text formatters or for automatic translation to a variety of
     formats suitable for input to text formatters.  A copy made in an
     otherwise Transparent file format whose markup has been designed to
     thwart or discourage subsequent modification by readers is not
     Transparent.  A copy that is not "Transparent" is called "Opaque".

     Examples of suitable formats for Transparent copies include plain
     ASCII without markup, Texinfo input format, LaTeX input format,
     SGML or XML using a publicly available DTD, and standard-conforming
     simple HTML designed for human modification.  Opaque formats
     include PostScript, PDF, proprietary formats that can be read and
     edited only by proprietary word processors, SGML or XML for which
     the DTD and/or processing tools are not generally available, and
     the machine-generated HTML produced by some word processors for
     output purposes only.

     The "Title Page" means, for a printed book, the title page itself,
     plus such following pages as are needed to hold, legibly, the
     material this License requires to appear in the title page.  For
     works in formats which do not have any title page as such, "Title
     Page" means the text near the most prominent appearance of the
     work's title, preceding the beginning of the body of the text.

  2. VERBATIM COPYING

     You may copy and distribute the Document in any medium, either
     commercially or noncommercially, provided that this License, the
     copyright notices, and the license notice saying this License
     applies to the Document are reproduced in all copies, and that you
     add no other conditions whatsoever to those of this License.  You
     may not use technical measures to obstruct or control the reading
     or further copying of the copies you make or distribute.  However,
     you may accept compensation in exchange for copies.  If you
     distribute a large enough number of copies you must also follow the
     conditions in section 3.

     You may also lend copies, under the same conditions stated above,
     and you may publicly display copies.

  3. COPYING IN QUANTITY

     If you publish printed copies of the Document numbering more than
     100, and the Document's license notice requires Cover Texts, you
     must enclose the copies in covers that carry, clearly and legibly,
     all these Cover Texts: Front-Cover Texts on the front cover, and
     Back-Cover Texts on the back cover.  Both covers must also clearly
     and legibly identify you as the publisher of these copies.  The
     front cover must present the full title with all words of the title
     equally prominent and visible.  You may add other material on the
     covers in addition.  Copying with changes limited to the covers, as
     long as they preserve the title of the Document and satisfy these
     conditions, can be treated as verbatim copying in other respects.

     If the required texts for either cover are too voluminous to fit
     legibly, you should put the first ones listed (as many as fit
     reasonably) on the actual cover, and continue the rest onto
     adjacent pages.

     If you publish or distribute Opaque copies of the Document
     numbering more than 100, you must either include a machine-readable
     Transparent copy along with each Opaque copy, or state in or with
     each Opaque copy a publicly-accessible computer-network location
     containing a complete Transparent copy of the Document, free of
     added material, which the general network-using public has access
     to download anonymously at no charge using public-standard network
     protocols.  If you use the latter option, you must take reasonably
     prudent steps, when you begin distribution of Opaque copies in
     quantity, to ensure that this Transparent copy will remain thus
     accessible at the stated location until at least one year after the
     last time you distribute an Opaque copy (directly or through your
     agents or retailers) of that edition to the public.

     It is requested, but not required, that you contact the authors of
     the Document well before redistributing any large number of copies,
     to give them a chance to provide you with an updated version of the
     Document.

  4. MODIFICATIONS

     You may copy and distribute a Modified Version of the Document
     under the conditions of sections 2 and 3 above, provided that you
     release the Modified Version under precisely this License, with the
     Modified Version filling the role of the Document, thus licensing
     distribution and modification of the Modified Version to whoever
     possesses a copy of it.  In addition, you must do these things in
     the Modified Version:

       A. Use in the Title Page (and on the covers, if any) a title
          distinct from that of the Document, and from those of previous
          versions (which should, if there were any, be listed in the
          History section of the Document).  You may use the same title
          as a previous version if the original publisher of that
          version gives permission.

       B. List on the Title Page, as authors, one or more persons or
          entities responsible for authorship of the modifications in
          the Modified Version, together with at least five of the
          principal authors of the Document (all of its principal
          authors, if it has less than five).

       C. State on the Title page the name of the publisher of the
          Modified Version, as the publisher.

       D. Preserve all the copyright notices of the Document.

       E. Add an appropriate copyright notice for your modifications
          adjacent to the other copyright notices.

       F. Include, immediately after the copyright notices, a license
          notice giving the public permission to use the Modified
          Version under the terms of this License, in the form shown in
          the Addendum below.

       G. Preserve in that license notice the full lists of Invariant
          Sections and required Cover Texts given in the Document's
          license notice.

       H. Include an unaltered copy of this License.

       I. Preserve the section entitled "History", and its title, and
          add to it an item stating at least the title, year, new
          authors, and publisher of the Modified Version as given on the
          Title Page.  If there is no section entitled "History" in the
          Document, create one stating the title, year, authors, and
          publisher of the Document as given on its Title Page, then add
          an item describing the Modified Version as stated in the
          previous sentence.

       J. Preserve the network location, if any, given in the Document
          for public access to a Transparent copy of the Document, and
          likewise the network locations given in the Document for
          previous versions it was based on.  These may be placed in the
          "History" section.  You may omit a network location for a work
          that was published at least four years before the Document
          itself, or if the original publisher of the version it refers
          to gives permission.

       K. In any section entitled "Acknowledgments" or "Dedications",
          preserve the section's title, and preserve in the section all
          the substance and tone of each of the contributor
          acknowledgments and/or dedications given therein.

       L. Preserve all the Invariant Sections of the Document, unaltered
          in their text and in their titles.  Section numbers or the
          equivalent are not considered part of the section titles.

       M. Delete any section entitled "Endorsements".  Such a section
          may not be included in the Modified Version.

       N. Do not retitle any existing section as "Endorsements" or to
          conflict in title with any Invariant Section.

     If the Modified Version includes new front-matter sections or
     appendices that qualify as Secondary Sections and contain no
     material copied from the Document, you may at your option designate
     some or all of these sections as invariant.  To do this, add their
     titles to the list of Invariant Sections in the Modified Version's
     license notice.  These titles must be distinct from any other
     section titles.

     You may add a section entitled "Endorsements", provided it contains
     nothing but endorsements of your Modified Version by various
     parties--for example, statements of peer review or that the text
     has been approved by an organization as the authoritative
     definition of a standard.

     You may add a passage of up to five words as a Front-Cover Text,
     and a passage of up to 25 words as a Back-Cover Text, to the end of
     the list of Cover Texts in the Modified Version.  Only one passage
     of Front-Cover Text and one of Back-Cover Text may be added by (or
     through arrangements made by) any one entity.  If the Document
     already includes a cover text for the same cover, previously added
     by you or by arrangement made by the same entity you are acting on
     behalf of, you may not add another; but you may replace the old
     one, on explicit permission from the previous publisher that added
     the old one.

     The author(s) and publisher(s) of the Document do not by this
     License give permission to use their names for publicity for or to
     assert or imply endorsement of any Modified Version.

  5. COMBINING DOCUMENTS

     You may combine the Document with other documents released under
     this License, under the terms defined in section 4 above for
     modified versions, provided that you include in the combination all
     of the Invariant Sections of all of the original documents,
     unmodified, and list them all as Invariant Sections of your
     combined work in its license notice.

     The combined work need only contain one copy of this License, and
     multiple identical Invariant Sections may be replaced with a single
     copy.  If there are multiple Invariant Sections with the same name
     but different contents, make the title of each such section unique
     by adding at the end of it, in parentheses, the name of the
     original author or publisher of that section if known, or else a
     unique number.  Make the same adjustment to the section titles in
     the list of Invariant Sections in the license notice of the
     combined work.

     In the combination, you must combine any sections entitled
     "History" in the various original documents, forming one section
     entitled "History"; likewise combine any sections entitled
     "Acknowledgments", and any sections entitled "Dedications".  You
     must delete all sections entitled "Endorsements."

  6. COLLECTIONS OF DOCUMENTS

     You may make a collection consisting of the Document and other
     documents released under this License, and replace the individual
     copies of this License in the various documents with a single copy
     that is included in the collection, provided that you follow the
     rules of this License for verbatim copying of each of the documents
     in all other respects.

     You may extract a single document from such a collection, and
     distribute it individually under this License, provided you insert
     a copy of this License into the extracted document, and follow this
     License in all other respects regarding verbatim copying of that
     document.

  7. AGGREGATION WITH INDEPENDENT WORKS

     A compilation of the Document or its derivatives with other
     separate and independent documents or works, in or on a volume of a
     storage or distribution medium, does not as a whole count as a
     Modified Version of the Document, provided no compilation copyright
     is claimed for the compilation.  Such a compilation is called an
     "aggregate", and this License does not apply to the other
     self-contained works thus compiled with the Document, on account of
     their being thus compiled, if they are not themselves derivative
     works of the Document.

     If the Cover Text requirement of section 3 is applicable to these
     copies of the Document, then if the Document is less than one
     quarter of the entire aggregate, the Document's Cover Texts may be
     placed on covers that surround only the Document within the
     aggregate.  Otherwise they must appear on covers around the whole
     aggregate.

  8. TRANSLATION

     Translation is considered a kind of modification, so you may
     distribute translations of the Document under the terms of section
     4.  Replacing Invariant Sections with translations requires special
     permission from their copyright holders, but you may include
     translations of some or all Invariant Sections in addition to the
     original versions of these Invariant Sections.  You may include a
     translation of this License provided that you also include the
     original English version of this License.  In case of a
     disagreement between the translation and the original English
     version of this License, the original English version will prevail.

  9. TERMINATION

     You may not copy, modify, sublicense, or distribute the Document
     except as expressly provided for under this License.  Any other
     attempt to copy, modify, sublicense or distribute the Document is
     void, and will automatically terminate your rights under this
     License.  However, parties who have received copies, or rights,
     from you under this License will not have their licenses terminated
     so long as such parties remain in full compliance.

  10. FUTURE REVISIONS OF THIS LICENSE

     The Free Software Foundation may publish new, revised versions of
     the GNU Free Documentation License from time to time.  Such new
     versions will be similar in spirit to the present version, but may
     differ in detail to address new problems or concerns.  See
     <http://www.gnu.org/copyleft/>.

     Each version of the License is given a distinguishing version
     number.  If the Document specifies that a particular numbered
     version of this License "or any later version" applies to it, you
     have the option of following the terms and conditions either of
     that specified version or of any later version that has been
     published (not as a draft) by the Free Software Foundation.  If the
     Document does not specify a version number of this License, you may
     choose any version ever published (not as a draft) by the Free
     Software Foundation.

A.1.1 ADDENDUM: How to use this License for your documents
----------------------------------------------------------

To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and license
notices just after the title page:

       Copyright (C)  YEAR  YOUR NAME.
       Permission is granted to copy, distribute and/or modify this document
       under the terms of the GNU Free Documentation License, Version 1.1
       or any later version published by the Free Software Foundation;
       with the Invariant Sections being LIST THEIR TITLES, with the
       Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
       A copy of the license is included in the section entitled ``GNU
       Free Documentation License''.

   If you have no Invariant Sections, write "with no Invariant Sections"
instead of saying which ones are invariant.  If you have no Front-Cover
Texts, write "no Front-Cover Texts" instead of "Front-Cover Texts being
LIST"; likewise for Back-Cover Texts.

   If your document contains nontrivial examples of program code, we
recommend releasing these examples in parallel under your choice of free
software license, such as the GNU General Public License, to permit
their use in free software.