changeset 359:8df427a314a8 trunk

[svn] Adlib synthesizer (AdPlug) support.
author chainsaw
date Fri, 30 Dec 2005 16:31:39 -0800
parents 70075730e187
children 222a0d71cbcf
files Plugins/Input/Makefile.am Plugins/Input/adplug/Makefile.am Plugins/Input/adplug/adplug-xmms.cc Plugins/Input/adplug/core/Makefile.am Plugins/Input/adplug/core/Makefile.bt Plugins/Input/adplug/core/a2m.cpp Plugins/Input/adplug/core/a2m.h Plugins/Input/adplug/core/adlibemu.c Plugins/Input/adplug/core/adlibemu.h Plugins/Input/adplug/core/adplug.cpp Plugins/Input/adplug/core/adplug.dsp Plugins/Input/adplug/core/adplug.h Plugins/Input/adplug/core/adtrack.cpp Plugins/Input/adplug/core/adtrack.h Plugins/Input/adplug/core/amd.cpp Plugins/Input/adplug/core/amd.h Plugins/Input/adplug/core/analopl.cpp Plugins/Input/adplug/core/analopl.h Plugins/Input/adplug/core/bam.cpp Plugins/Input/adplug/core/bam.h Plugins/Input/adplug/core/bmf.cpp Plugins/Input/adplug/core/bmf.h Plugins/Input/adplug/core/cff.cpp Plugins/Input/adplug/core/cff.h Plugins/Input/adplug/core/d00.cpp Plugins/Input/adplug/core/d00.h Plugins/Input/adplug/core/database.cpp Plugins/Input/adplug/core/database.h Plugins/Input/adplug/core/debug.c Plugins/Input/adplug/core/debug.h Plugins/Input/adplug/core/dfm.cpp Plugins/Input/adplug/core/dfm.h Plugins/Input/adplug/core/diskopl.cpp Plugins/Input/adplug/core/diskopl.h Plugins/Input/adplug/core/dmo.cpp Plugins/Input/adplug/core/dmo.h Plugins/Input/adplug/core/dro.cpp Plugins/Input/adplug/core/dro.h Plugins/Input/adplug/core/dtm.cpp Plugins/Input/adplug/core/dtm.h Plugins/Input/adplug/core/emuopl.cpp Plugins/Input/adplug/core/emuopl.h Plugins/Input/adplug/core/flash.cpp Plugins/Input/adplug/core/flash.h Plugins/Input/adplug/core/fmc.cpp Plugins/Input/adplug/core/fmc.h Plugins/Input/adplug/core/fmopl.c Plugins/Input/adplug/core/fmopl.h Plugins/Input/adplug/core/fprovide.cpp Plugins/Input/adplug/core/fprovide.h Plugins/Input/adplug/core/hsc.cpp Plugins/Input/adplug/core/hsc.h Plugins/Input/adplug/core/hsp.cpp Plugins/Input/adplug/core/hsp.h Plugins/Input/adplug/core/hybrid.cpp Plugins/Input/adplug/core/hybrid.h Plugins/Input/adplug/core/hyp.cpp Plugins/Input/adplug/core/hyp.h Plugins/Input/adplug/core/imf.cpp Plugins/Input/adplug/core/imf.h Plugins/Input/adplug/core/kemuopl.h Plugins/Input/adplug/core/ksm.cpp Plugins/Input/adplug/core/ksm.h Plugins/Input/adplug/core/lds.cpp Plugins/Input/adplug/core/lds.h Plugins/Input/adplug/core/mad.cpp Plugins/Input/adplug/core/mad.h Plugins/Input/adplug/core/mid.cpp Plugins/Input/adplug/core/mid.h Plugins/Input/adplug/core/mididata.h Plugins/Input/adplug/core/mkj.cpp Plugins/Input/adplug/core/mkj.h Plugins/Input/adplug/core/mtk.cpp Plugins/Input/adplug/core/mtk.h Plugins/Input/adplug/core/opl.h Plugins/Input/adplug/core/player.cpp Plugins/Input/adplug/core/player.h Plugins/Input/adplug/core/players.cpp Plugins/Input/adplug/core/players.h Plugins/Input/adplug/core/protrack.cpp Plugins/Input/adplug/core/protrack.h Plugins/Input/adplug/core/psi.cpp Plugins/Input/adplug/core/psi.h Plugins/Input/adplug/core/rad.cpp Plugins/Input/adplug/core/rad.h Plugins/Input/adplug/core/rat.cpp Plugins/Input/adplug/core/rat.h Plugins/Input/adplug/core/raw.cpp Plugins/Input/adplug/core/raw.h Plugins/Input/adplug/core/realopl.cpp Plugins/Input/adplug/core/realopl.h Plugins/Input/adplug/core/rol.cpp Plugins/Input/adplug/core/rol.h Plugins/Input/adplug/core/s3m.cpp Plugins/Input/adplug/core/s3m.h Plugins/Input/adplug/core/sa2.cpp Plugins/Input/adplug/core/sa2.h Plugins/Input/adplug/core/silentopl.h Plugins/Input/adplug/core/sng.cpp Plugins/Input/adplug/core/sng.h Plugins/Input/adplug/core/u6m.cpp Plugins/Input/adplug/core/u6m.h Plugins/Input/adplug/core/xad.cpp Plugins/Input/adplug/core/xad.h Plugins/Input/adplug/core/xsm.cpp Plugins/Input/adplug/core/xsm.h configure.ac
diffstat 107 files changed, 20478 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/Plugins/Input/Makefile.am	Fri Dec 30 14:17:35 2005 -0800
+++ b/Plugins/Input/Makefile.am	Fri Dec 30 16:31:39 2005 -0800
@@ -1,2 +1,2 @@
-ALL_PLUGINS = mpg123 aac modplug vorbis tonegen cdaudio sid wav flac console wma timidity musepack sexypsf
+ALL_PLUGINS = mpg123 aac modplug vorbis tonegen cdaudio sid wav flac console wma timidity musepack sexypsf adplug
 SUBDIRS = $(INPUT_PLUGINS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/Makefile.am	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,14 @@
+if HAVE_ADPLUG
+
+SUBDIRS = core
+lib_LTLIBRARIES = libadplug.la
+
+endif
+
+libdir = $(plugindir)/$(INPUT_PLUGIN_DIR)
+
+libadplug_la_LDFLAGS = -lstdc++ -lbinio $(PLUGIN_LDFLAGS) ./core/libadplugcore.la
+
+libadplug_la_SOURCES = adplug-xmms.cc
+
+INCLUDES = $(GTK_CFLAGS) -I$(top_builddir)/intl -I$(top_srcdir) -I./core
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/adplug-xmms.cc	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,937 @@
+/*
+   AdPlug/XMMS - AdPlug XMMS Plugin
+   Copyright (C) 2002, 2003 Simon Peter <dn.tlp@gmx.net>
+
+   AdPlug/XMMS is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This plugin is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this plugin; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <algorithm>
+#include <sstream>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <gtk/gtk.h>
+#include "adplug.h"
+#include "emuopl.h"
+#include "silentopl.h"
+#include "players.h"
+#include "audacious/plugin.h"
+#include "libaudacious/util.h"
+#include "libaudacious/configdb.h"
+
+/***** Defines *****/
+
+// Version string
+#define ADPLUG_NAME	"AdPlug"
+
+// Sound buffer size in samples
+#define SNDBUFSIZE	512
+
+// AdPlug's 8 and 16 bit audio formats
+#define FORMAT_8	FMT_U8
+#define FORMAT_16	FMT_S16_NE
+
+// Default file name of AdPlug's database file
+#define ADPLUGDB_FILE		"adplug.db"
+
+// Default AdPlug user's configuration subdirectory
+#define ADPLUG_CONFDIR		".adplug"
+
+/***** Global variables *****/
+
+extern "C" InputPlugin	adplug_ip;
+static gboolean		audio_error = FALSE;
+
+// Configuration (and defaults)
+static struct {
+  gint		freq;
+  gboolean	bit16, stereo, endless, quickdetect;
+  CPlayers	players;
+} cfg = { 44100l, true, false, false, true, CAdPlug::players };
+
+// Player variables
+static struct {
+  CPlayer		*p;
+  CAdPlugDatabase	*db;
+  unsigned int		subsong, songlength;
+  int			seek;
+  char			filename[PATH_MAX];
+  char			*songtitle;
+  float			time_ms;
+  bool			playing;
+  GThread		*play_thread;
+  GtkLabel		*infobox;
+  GtkDialog		*infodlg;
+} plr = { 0, 0, 0, 0, -1, "", NULL, 0.0f, false, 0, NULL, NULL };
+
+/***** Debugging *****/
+
+#ifdef DEBUG
+
+#include <stdarg.h>
+
+static void dbg_printf(const char *fmt, ...)
+{
+  va_list argptr;
+
+  va_start(argptr, fmt);
+  vfprintf(stderr, fmt, argptr);
+  va_end(argptr);
+}
+
+#else
+
+static void dbg_printf(const char *fmt, ...)
+{ }
+
+#endif
+
+/***** [Dialog]: Utility functions *****/
+
+static GtkWidget *make_framed(GtkWidget *what, const gchar *label)
+{
+  GtkWidget *framebox = gtk_frame_new(label);
+
+  gtk_container_add(GTK_CONTAINER(framebox), what);
+  return framebox;
+}
+
+static GtkWidget *print_left(const gchar *text)
+{
+  GtkLabel *label = GTK_LABEL(gtk_label_new(text));
+
+  gtk_label_set_justify(label, GTK_JUSTIFY_LEFT);
+  gtk_misc_set_padding(GTK_MISC(label), 2, 2);
+  return GTK_WIDGET(label);
+}
+
+static void MessageBox(const char *title, const char *text, const char *button)
+{
+  char *tmptitle = (char *)malloc(strlen(title) + 1),
+    *tmptxt = (char *)malloc(strlen(text) + 1),
+    *tmpbutton = (char *)malloc(strlen(button) + 1);
+
+  strcpy(tmptitle, title); strcpy(tmptxt, text); strcpy(tmpbutton, button);
+
+  GtkWidget *msgbox = xmms_show_message(tmptitle, tmptxt, tmpbutton, FALSE,
+					GTK_SIGNAL_FUNC(gtk_widget_destroyed), &msgbox);
+
+  free(tmptitle); free(tmptxt); free(tmpbutton);
+}
+
+/***** Dialog boxes *****/
+
+static void adplug_about(void)
+{
+  std::ostringstream text;
+
+  text << ADPLUG_NAME "\n"
+    "Copyright (C) 2002, 2003 Simon Peter <dn.tlp@gmx.net>\n\n"
+    "This plugin is released under the terms and conditions of the GNU LGPL.\n"
+    "See http://www.gnu.org/licenses/lgpl.html for details."
+    "\n\nThis plugin uses the AdPlug library, which is copyright (C) Simon Peter, et al.\n"
+    "Linked AdPlug library version: " << CAdPlug::get_version() << std::ends;
+
+  MessageBox("About " ADPLUG_NAME, text.str().c_str(), "Ugh!");
+}
+
+static void close_config_box_ok(GtkButton *button, GPtrArray *rblist)
+{
+  // Apply configuration settings
+  cfg.bit16 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_ptr_array_index(rblist, 0)));
+  cfg.stereo = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_ptr_array_index(rblist, 1)));
+
+  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_ptr_array_index(rblist, 2)))) cfg.freq = 11025;
+  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_ptr_array_index(rblist, 3)))) cfg.freq = 22050;
+  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_ptr_array_index(rblist, 4)))) cfg.freq = 44100;
+  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_ptr_array_index(rblist, 5)))) cfg.freq = 48000;
+
+  cfg.endless = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_ptr_array_index(rblist, 6)));
+  cfg.quickdetect = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_ptr_array_index(rblist, 7)));
+
+  cfg.players = *(CPlayers *)g_ptr_array_index(rblist, 8);
+  delete (CPlayers *)g_ptr_array_index(rblist, 8);
+
+  g_ptr_array_free(rblist, FALSE);
+}
+
+static void close_config_box_cancel(GtkButton *button, GPtrArray *rblist)
+{
+  delete (CPlayers *)g_ptr_array_index(rblist, 8);
+  g_ptr_array_free(rblist, FALSE);
+}
+
+static void config_fl_row_select(GtkCList *fl, gint row, gint col,
+				 GdkEventButton *event, CPlayers *pl)
+{
+  pl->push_back((CPlayerDesc *)gtk_clist_get_row_data(fl, row));
+  pl->unique();
+}
+
+static void config_fl_row_unselect(GtkCList *fl, gint row, gint col,
+				   GdkEventButton *event, CPlayers *pl)
+{
+  pl->remove((CPlayerDesc *)gtk_clist_get_row_data(fl, row));
+}
+
+static void adplug_config(void)
+{
+  GtkDialog *config_dlg = GTK_DIALOG(gtk_dialog_new());
+  GtkNotebook *notebook = GTK_NOTEBOOK(gtk_notebook_new());
+  GtkTable *table;
+  GtkTooltips *tooltips = gtk_tooltips_new();
+  GPtrArray *rblist = g_ptr_array_new();
+
+  gtk_window_set_title(GTK_WINDOW(config_dlg), "AdPlug :: Configuration");
+  gtk_window_set_policy(GTK_WINDOW(config_dlg), FALSE, FALSE, TRUE); // Window is auto sized
+  gtk_window_set_modal(GTK_WINDOW(config_dlg), TRUE);
+  gtk_container_add(GTK_CONTAINER(config_dlg->vbox), GTK_WIDGET(notebook));
+
+  // Add Ok & Cancel buttons
+  {
+    GtkWidget *button;
+
+    button = gtk_button_new_with_label("Ok");
+    gtk_signal_connect(GTK_OBJECT(button), "clicked",
+		       GTK_SIGNAL_FUNC(close_config_box_ok),
+		       (gpointer)rblist);
+    gtk_signal_connect_object_after(GTK_OBJECT(button), "clicked",
+				    GTK_SIGNAL_FUNC(gtk_widget_destroy),
+				    GTK_OBJECT(config_dlg));
+    gtk_container_add(GTK_CONTAINER(config_dlg->action_area), button);
+
+    button = gtk_button_new_with_label("Cancel");
+    gtk_signal_connect(GTK_OBJECT(button), "clicked",
+		       GTK_SIGNAL_FUNC(close_config_box_cancel),
+		       (gpointer)rblist);
+    gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
+			      GTK_SIGNAL_FUNC(gtk_widget_destroy),
+			      GTK_OBJECT(config_dlg));
+    gtk_container_add(GTK_CONTAINER(config_dlg->action_area), button);
+  }
+
+  /***** Page 1: General *****/
+
+  table = GTK_TABLE(gtk_table_new(1, 2, TRUE));
+  gtk_table_set_row_spacings(table, 5); gtk_table_set_col_spacings(table, 5);
+  gtk_notebook_append_page(notebook, GTK_WIDGET(table), print_left("General"));
+
+  // Add "Sound quality" section
+  {
+    GtkTable *sqt = GTK_TABLE(gtk_table_new(2, 2, FALSE));
+    GtkVBox *fvb;
+    GtkRadioButton *rb;
+
+    gtk_table_set_row_spacings(sqt, 5);
+    gtk_table_set_col_spacings(sqt, 5);
+    gtk_table_attach_defaults(table, make_framed(GTK_WIDGET(sqt), "Sound quality"),
+			      0, 1, 0, 1);
+
+    // Add "Resolution" section
+    fvb = GTK_VBOX(gtk_vbox_new(TRUE, 0));
+    gtk_table_attach_defaults(sqt, make_framed(GTK_WIDGET(fvb), "Resolution"),
+			      0, 1, 0, 1);
+    rb = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label(NULL, "8bit"));
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), !cfg.bit16);
+    gtk_container_add(GTK_CONTAINER(fvb), GTK_WIDGET(rb));
+    rb = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label_from_widget(rb, "16bit"));
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), cfg.bit16);
+    gtk_container_add(GTK_CONTAINER(fvb), GTK_WIDGET(rb));
+    g_ptr_array_add(rblist, (gpointer)rb);
+
+    // Add "Channels" section
+    fvb = GTK_VBOX(gtk_vbox_new(TRUE, 0));
+    gtk_table_attach_defaults(sqt, make_framed(GTK_WIDGET(fvb), "Channels"),
+			      0, 1, 1, 2);
+    rb = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label(NULL, "Mono"));
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), !cfg.stereo);
+    gtk_container_add(GTK_CONTAINER(fvb), GTK_WIDGET(rb));
+    rb = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label_from_widget(rb, "Stereo"));
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), cfg.stereo);
+    gtk_container_add(GTK_CONTAINER(fvb), GTK_WIDGET(rb));
+    gtk_tooltips_set_tip(tooltips, GTK_WIDGET(rb),
+			 "Setting stereo is not recommended, unless you need to. "
+			 "This won't add any stereo effects to the sound - OPL2 "
+			 "is just mono - but eats up more CPU power!", NULL);
+    g_ptr_array_add(rblist, (gpointer)rb);
+
+    // Add "Frequency" section
+    fvb = GTK_VBOX(gtk_vbox_new(TRUE, 0));
+    gtk_table_attach_defaults(sqt, make_framed(GTK_WIDGET(fvb), "Frequency"),
+			      1, 2, 0, 2);
+    rb = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label(NULL, "11025"));
+    if(cfg.freq == 11025) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), TRUE);
+    gtk_container_add(GTK_CONTAINER(fvb), GTK_WIDGET(rb));
+    g_ptr_array_add(rblist, (gpointer)rb);
+    rb = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label_from_widget(rb, "22050"));
+    if(cfg.freq == 22050) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), TRUE);
+    gtk_container_add(GTK_CONTAINER(fvb), GTK_WIDGET(rb));
+    g_ptr_array_add(rblist, (gpointer)rb);
+    rb = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label_from_widget(rb, "44100"));
+    if(cfg.freq == 44100) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), TRUE);
+    gtk_container_add(GTK_CONTAINER(fvb), GTK_WIDGET(rb));
+    g_ptr_array_add(rblist, (gpointer)rb);
+    rb = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label_from_widget(rb, "48000"));
+    if(cfg.freq == 48000) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), TRUE);
+    gtk_container_add(GTK_CONTAINER(fvb), GTK_WIDGET(rb));
+    g_ptr_array_add(rblist, (gpointer)rb);
+  }
+
+  // Add "Playback" section
+  {
+    GtkVBox *vb = GTK_VBOX(gtk_vbox_new(FALSE, 0));
+    GtkCheckButton *cb;
+
+    gtk_table_attach_defaults(table, make_framed(GTK_WIDGET(vb), "Playback"),
+			      1, 2, 0, 1);
+
+    cb = GTK_CHECK_BUTTON(gtk_check_button_new_with_label("Detect songend"));
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cb), !cfg.endless);
+    gtk_container_add(GTK_CONTAINER(vb), GTK_WIDGET(cb));
+    gtk_tooltips_set_tip(tooltips, GTK_WIDGET(cb),
+			 "If enabled, XMMS will detect a song's ending, stop "
+			 "it and advance in the playlist. If disabled, XMMS "
+			 "won't take notice of a song's ending and loop it all "
+			 "over again and again.", NULL);
+    g_ptr_array_add(rblist, (gpointer)cb);
+
+    cb = GTK_CHECK_BUTTON(gtk_check_button_new_with_label("Quick file detection"));
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cb), cfg.quickdetect);
+    gtk_container_add(GTK_CONTAINER(vb), GTK_WIDGET(cb));
+    gtk_tooltips_set_tip(tooltips, GTK_WIDGET(cb),
+			 "If enabled, we'll try to determine a file's type by "
+			 "only looking at the file extension, instead of "
+			 "processing the file's contents. This speeds up the "
+			 "load time of files a lot, but can be inaccurate if "
+			 "the file has the wrong extension.", NULL);
+    g_ptr_array_add(rblist, (gpointer)cb);
+  }
+
+  /***** Page 2: Formats *****/
+
+  table = GTK_TABLE(gtk_table_new(1, 1, TRUE));
+  gtk_notebook_append_page(notebook, GTK_WIDGET(table), print_left("Formats"));
+
+  // Add "Format selection" section
+  {
+    GtkHBox *vb = GTK_HBOX(gtk_hbox_new(FALSE, 0));
+    gtk_table_attach_defaults(table, make_framed(GTK_WIDGET(vb), "Format selection"),
+			      0, 1, 0, 1);
+    // Add scrollable list
+    {
+      gchar *rowstr[] = {"Format", "Extension"};
+      GtkEventBox *eventbox = GTK_EVENT_BOX(gtk_event_box_new());
+      GtkScrolledWindow *formatswnd = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL));
+      GtkCList *fl = GTK_CLIST(gtk_clist_new_with_titles(2, rowstr));
+      CPlayers::const_iterator i;
+      unsigned int j;
+      gtk_clist_set_selection_mode(fl, GTK_SELECTION_MULTIPLE);
+
+      // Build list
+      for(i = CAdPlug::players.begin(); i != CAdPlug::players.end(); i++) {
+	gint rownum;
+
+	gchar *rws[2];
+	rws[0] = g_strdup((*i)->filetype.c_str());
+	rws[1] = g_strdup((*i)->get_extension(0));
+	for(j = 1; (*i)->get_extension(j); j++)
+	  rws[1] = g_strjoin(", ", rws[1], (*i)->get_extension(j), NULL);
+	rownum = gtk_clist_append(fl, rws);
+	g_free(rws[0]); g_free(rws[1]);
+	gtk_clist_set_row_data(fl, rownum, (gpointer)(*i));
+	if(find(cfg.players.begin(), cfg.players.end(), *i) != cfg.players.end())
+	  gtk_clist_select_row(fl, rownum, 0);
+      }
+
+      gtk_clist_columns_autosize(fl);
+      gtk_scrolled_window_set_policy(formatswnd, GTK_POLICY_AUTOMATIC,
+				     GTK_POLICY_AUTOMATIC);
+      gpointer pl = (gpointer)new CPlayers(cfg.players);
+      gtk_signal_connect(GTK_OBJECT(fl), "select-row",
+			 GTK_SIGNAL_FUNC(config_fl_row_select), pl);
+      gtk_signal_connect(GTK_OBJECT(fl), "unselect-row",
+			 GTK_SIGNAL_FUNC(config_fl_row_unselect), pl);
+      gtk_container_add(GTK_CONTAINER(formatswnd), GTK_WIDGET(fl));
+      gtk_container_add(GTK_CONTAINER(eventbox), GTK_WIDGET(formatswnd));
+      gtk_container_add(GTK_CONTAINER(vb), GTK_WIDGET(eventbox));
+      gtk_tooltips_set_tip(tooltips, GTK_WIDGET(eventbox),
+			   "Selected file types will be recognized and played "
+			   "back by this plugin. Deselected types will be "
+			   "ignored to make room for other plugins to play "
+			   "these files.", NULL);
+      g_ptr_array_add(rblist, pl);
+    }
+  }
+
+  // Show window
+  gtk_widget_show_all(GTK_WIDGET(config_dlg));
+}
+
+static void add_instlist(GtkCList *instlist, const char *t1, const char *t2)
+{
+  gchar *rowstr[2];
+
+  rowstr[0] = g_strdup(t1); rowstr[1] = g_strdup(t2);
+  gtk_clist_append(instlist, rowstr);
+  g_free(rowstr[0]); g_free(rowstr[1]);
+}
+
+static CPlayer *factory(const std::string &filename, Copl *newopl)
+/* Wrapper factory method that implements the "quick detect" feature. */
+{
+  CPlayer			*p;
+  CPlayers::const_iterator	i;
+  unsigned int			j;
+
+  dbg_printf("factory(\"%s\",opl): ", filename.c_str());
+  if(cfg.quickdetect) {
+    // Quick detect! Just check according to file extensions.
+    dbg_printf("quick detect: ");
+    for(i = cfg.players.begin(); i != cfg.players.end(); i++)
+      for(j = 0; (*i)->get_extension(j); j++)
+	if(CFileProvider::extension(filename, (*i)->get_extension(j)))
+	  if((p = (*i)->factory(newopl)))
+	    if(p->load(filename)) {
+	      dbg_printf("%s\n", (*i)->filetype.c_str());
+	      return p;
+	    } else
+	      delete p;
+
+    dbg_printf("failed!\n");
+    return 0;	// quick detect failed.
+  } else {	// just call AdPlug's original factory()
+    dbg_printf("asking AdPlug...\n");
+    return CAdPlug::factory(filename, newopl, cfg.players);
+  }
+}
+
+static void adplug_stop(void);
+static void adplug_play(char *filename);
+
+static void subsong_slider(GtkAdjustment *adj)
+{
+  adplug_stop();
+  plr.subsong = (unsigned int)adj->value - 1;
+  adplug_play(plr.filename);
+}
+
+#if 0
+static void close_infobox(GtkDialog *infodlg)
+{
+  // Forget our references to the instance of the "currently playing song" info
+  // box. But only if we're really destroying that one... ;)
+  if(infodlg == plr.infodlg) {
+    plr.infobox = NULL;
+    plr.infodlg = NULL;
+  }
+}
+
+static void adplug_info_box(char *filename)
+{
+  CSilentopl tmpopl;
+  CPlayer *p = (strcmp(filename, plr.filename) || !plr.p) ?
+    factory(filename, &tmpopl) : plr.p;
+
+  if(!p) return; // bail out if no player could be created
+  if(p == plr.p && plr.infodlg) return; // only one info box for active song
+
+  std::ostringstream infotext;
+  unsigned int i;
+  GtkDialog *infobox = GTK_DIALOG(gtk_dialog_new());
+  GtkButton *okay_button = GTK_BUTTON(gtk_button_new_with_label("Ok"));
+  GtkPacker *packer = GTK_PACKER(gtk_packer_new());
+  GtkHBox *hbox = GTK_HBOX(gtk_hbox_new(TRUE, 2));
+
+  // Build file info box
+  gtk_window_set_title(GTK_WINDOW(infobox), "AdPlug :: File Info");
+  gtk_window_set_policy(GTK_WINDOW(infobox), FALSE, FALSE, TRUE); // Window is auto sized
+  gtk_container_add(GTK_CONTAINER(infobox->vbox), GTK_WIDGET(packer));
+  gtk_packer_set_default_border_width(packer, 2);
+  gtk_box_set_homogeneous(GTK_BOX(hbox), FALSE);
+  gtk_signal_connect_object(GTK_OBJECT(okay_button), "clicked",
+			    GTK_SIGNAL_FUNC(gtk_widget_destroy),
+			    GTK_OBJECT(infobox));
+  gtk_signal_connect(GTK_OBJECT(infobox), "destroy",
+		     GTK_SIGNAL_FUNC(close_infobox), 0);
+  gtk_container_add(GTK_CONTAINER(infobox->action_area), GTK_WIDGET(okay_button));
+
+  // Add filename section
+  gtk_packer_add_defaults(packer, make_framed(print_left(filename), "Filename"),
+			  GTK_SIDE_TOP, GTK_ANCHOR_CENTER, GTK_FILL_X);
+
+  // Add "Song info" section
+  infotext << "Title: " << p->gettitle() << std::endl <<
+    "Author: " << p->getauthor() << std::endl <<
+    "File Type: " << p->gettype() << std::endl <<
+    "Subsongs: " << p->getsubsongs() << std::endl <<
+    "Instruments: " << p->getinstruments();
+  if(plr.p == p)
+    infotext << std::ends;
+  else {
+    infotext << std::endl << "Orders: " << p->getorders() << std::endl <<
+      "Patterns: " << p->getpatterns() << std::ends;
+  }
+  gtk_container_add(GTK_CONTAINER(hbox),
+		    make_framed(print_left(infotext.str().c_str()), "Song"));
+
+  // Add "Playback info" section if currently playing
+  if(plr.p == p) {
+    plr.infobox = GTK_LABEL(gtk_label_new(""));
+    gtk_label_set_justify(plr.infobox, GTK_JUSTIFY_LEFT);
+    gtk_misc_set_padding(GTK_MISC(plr.infobox), 2, 2);
+    gtk_container_add(GTK_CONTAINER(hbox),
+		      make_framed(GTK_WIDGET(plr.infobox), "Playback"));
+  }
+  gtk_packer_add_defaults(packer, GTK_WIDGET(hbox), GTK_SIDE_TOP,
+			  GTK_ANCHOR_CENTER, GTK_FILL_X);
+
+  // Add instrument names section
+  if(p->getinstruments()) {
+    GtkScrolledWindow *instwnd = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL));
+    GtkCList *instnames;
+    gchar tmpstr[10];
+
+    {
+      gchar *rowstr[] = {"#","Instrument name"};
+      instnames = GTK_CLIST(gtk_clist_new_with_titles(2, rowstr));
+    }
+    gtk_clist_set_column_justification(instnames, 0, GTK_JUSTIFY_RIGHT);
+
+    for(i=0;i<p->getinstruments();i++) {
+      sprintf(tmpstr, "%d", i + 1);
+      add_instlist(instnames, tmpstr, p->getinstrument(i).c_str());
+    }
+
+    gtk_clist_columns_autosize(instnames);
+    gtk_scrolled_window_set_policy(instwnd, GTK_POLICY_AUTOMATIC,
+				   GTK_POLICY_AUTOMATIC);
+    gtk_container_add(GTK_CONTAINER(instwnd), GTK_WIDGET(instnames));
+    gtk_packer_add(packer, GTK_WIDGET(instwnd), GTK_SIDE_TOP,
+		   GTK_ANCHOR_CENTER, GTK_FILL_X, 0, 0, 0, 0, 50);
+  }
+
+  // Add "Song message" section
+  if(!p->getdesc().empty()) {
+    GtkScrolledWindow *msgwnd = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL));
+    GtkText *msg = GTK_TEXT(gtk_text_new(NULL, NULL));
+    gint pos = 0;
+
+    gtk_scrolled_window_set_policy(msgwnd, GTK_POLICY_AUTOMATIC,
+				   GTK_POLICY_AUTOMATIC);
+    gtk_text_set_editable(msg, FALSE);
+    gtk_text_set_word_wrap(msg, TRUE);
+    //    gtk_text_set_line_wrap(msg, TRUE);
+    gtk_editable_insert_text(GTK_EDITABLE(msg), p->getdesc().c_str(),
+			     p->getdesc().length(), &pos);
+
+    gtk_container_add(GTK_CONTAINER(msgwnd), GTK_WIDGET(msg));
+    gtk_packer_add(packer, make_framed(GTK_WIDGET(msgwnd), "Song message"),
+		   GTK_SIDE_TOP, GTK_ANCHOR_CENTER, GTK_FILL_X, 2, 0, 0, 200, 50);
+  }
+
+  // Add subsong slider section
+  if(p == plr.p && p->getsubsongs() > 1) {
+    GtkAdjustment *adj = GTK_ADJUSTMENT(gtk_adjustment_new(plr.subsong + 1, 1,
+							   p->getsubsongs() + 1,
+							   1, 5, 1));
+    GtkHScale *slider = GTK_HSCALE(gtk_hscale_new(adj));
+
+    gtk_signal_connect(GTK_OBJECT(adj), "value_changed",
+		       GTK_SIGNAL_FUNC(subsong_slider), NULL);
+    gtk_range_set_update_policy(GTK_RANGE(slider), GTK_UPDATE_DISCONTINUOUS);
+    gtk_scale_set_digits(GTK_SCALE(slider), 0);
+    gtk_packer_add_defaults(packer, make_framed(GTK_WIDGET(slider), "Subsong selection"),
+			    GTK_SIDE_TOP, GTK_ANCHOR_CENTER, GTK_FILL_X);
+  }
+
+  // Show dialog box
+  gtk_widget_show_all(GTK_WIDGET(infobox));
+  if(p == plr.p) { // Remember widget, so we could destroy it later
+    plr.infodlg = infobox;
+  } else // Delete temporary player
+    delete p;
+}
+
+/***** Main player (!! threaded !!) *****/
+
+static void update_infobox(void)
+{
+  std::ostringstream infotext;
+
+  // Recreate info string
+  infotext << "Order: " << plr.p->getorder() << " / " << plr.p->getorders() <<
+    std::endl << "Pattern: " << plr.p->getpattern() << " / " <<
+    plr.p->getpatterns() << std::endl << "Row: " << plr.p->getrow() <<
+    std::endl << "Speed: " << plr.p->getspeed() << std::endl << "Timer: " <<
+    plr.p->getrefresh() << "Hz" << std::ends;
+
+  GDK_THREADS_ENTER();
+  gtk_label_set_text(plr.infobox, infotext.str().c_str());
+  GDK_THREADS_LEAVE();
+}
+#endif
+
+// Define sampsize macro (only usable inside play_loop()!)
+#define sampsize ((bit16 ? 2 : 1) * (stereo ? 2 : 1))
+
+static void *play_loop(void *filename)
+/* Main playback thread. Takes the filename to play as argument. */
+{
+  dbg_printf("play_loop(\"%s\"): ", (char *)filename);
+  CEmuopl opl(cfg.freq, cfg.bit16, cfg.stereo);
+  long toadd = 0, i, towrite;
+  char *sndbuf, *sndbufpos;
+  bool playing = true,		// Song self-end indicator.
+    bit16 = cfg.bit16,		// Duplicate config, so it doesn't affect us if
+    stereo = cfg.stereo;	// the user changes it while we're playing.
+  unsigned long freq = cfg.freq;
+
+  // Try to load module
+  dbg_printf("factory, ");
+  if(!(plr.p = factory((char *)filename, &opl))) {
+    dbg_printf("error!\n");
+    MessageBox("AdPlug :: Error", "File could not be opened!", "Ok");
+    plr.playing = false;
+    g_thread_exit(NULL);
+  }
+
+  // Cache song length
+  dbg_printf("length, ");
+  plr.songlength = plr.p->songlength(plr.subsong);
+
+  // cache song title
+  dbg_printf("title, ");
+  if(!plr.p->gettitle().empty()) {
+    plr.songtitle = (char *)malloc(plr.p->gettitle().length() + 1);
+    strcpy(plr.songtitle, plr.p->gettitle().c_str());
+  }
+
+  // reset to first subsong on new file
+  dbg_printf("subsong, ");
+  if(strcmp((char *)filename, plr.filename)) {
+    strcpy(plr.filename, (char *)filename);
+    plr.subsong = 0;
+  }
+
+  // Allocate audio buffer
+  dbg_printf("buffer, ");
+  sndbuf = (char *)malloc(SNDBUFSIZE * sampsize);
+
+  // Set XMMS main window information
+  dbg_printf("xmms, ");
+  adplug_ip.set_info(plr.songtitle, plr.songlength, freq * sampsize * 8,
+		     freq, stereo ? 2 : 1);
+
+  // Rewind player to right subsong
+  dbg_printf("rewind, ");
+  plr.p->rewind(plr.subsong);
+
+  // main playback loop
+  dbg_printf("loop.\n");
+  while((playing || cfg.endless) && plr.playing) {
+    // seek requested ?
+    if(plr.seek != -1) {
+      // backward seek ?
+      if(plr.seek < plr.time_ms) {
+        plr.p->rewind(plr.subsong);
+        plr.time_ms = 0.0f;
+      }
+
+      // seek to requested position
+      while((plr.time_ms < plr.seek) && plr.p->update())
+        plr.time_ms += 1000 / plr.p->getrefresh();
+
+      // Reset output plugin and some values
+      adplug_ip.output->flush((int)plr.time_ms);
+      plr.seek = -1;
+    }
+
+    // fill sound buffer
+    towrite = SNDBUFSIZE; sndbufpos = sndbuf;
+    while (towrite > 0) {
+      while (toadd < 0) {
+        toadd += freq;
+	playing = plr.p->update();
+        plr.time_ms += 1000 / plr.p->getrefresh();
+      }
+      i = MIN(towrite, (long)(toadd / plr.p->getrefresh() + 4) & ~3);
+      opl.update((short *)sndbufpos, i);
+      sndbufpos += i * sampsize; towrite -= i;
+      toadd -= (long)(plr.p->getrefresh() * i);
+    }
+
+    // write sound buffer and update vis
+    adplug_ip.add_vis_pcm(adplug_ip.output->written_time(),
+			  bit16 ? FORMAT_16 : FORMAT_8,
+			  stereo ? 2 : 1, SNDBUFSIZE * sampsize, sndbuf);
+    while(adplug_ip.output->buffer_free() < SNDBUFSIZE * sampsize) xmms_usleep(10000);
+    adplug_ip.output->write_audio(sndbuf, SNDBUFSIZE * sampsize);
+
+#if 0
+    // update infobox, if necessary
+    if(plr.infobox && plr.playing) update_infobox();
+#endif
+  }
+
+  // playback finished - deinit
+  dbg_printf("play_loop(\"%s\"): ", (char *)filename);
+  if(!playing) { // wait for output plugin to finish if song has self-ended
+    dbg_printf("wait, ");
+    while(adplug_ip.output->buffer_playing()) xmms_usleep(10000);
+  } else { // or else, flush its output buffers
+    dbg_printf("flush, ");
+    adplug_ip.output->buffer_free(); adplug_ip.output->buffer_free();
+  }
+
+  // free everything and exit
+  dbg_printf("free");
+  delete plr.p; plr.p = 0;
+  if(plr.songtitle) { free(plr.songtitle); plr.songtitle = NULL; }
+  free(sndbuf);
+  plr.playing = false; // important! XMMS won't get a self-ended song without it.
+  dbg_printf(".\n");
+  g_thread_exit(NULL);
+}
+
+// sampsize macro not useful anymore.
+#undef sampsize
+
+/***** Informational *****/
+
+static int adplug_is_our_file(char *filename)
+{
+  CSilentopl tmpopl;
+  CPlayer *p = factory(filename,&tmpopl);
+
+  dbg_printf("adplug_is_our_file(\"%s\"): returned ",filename);
+
+  if(p) {
+    delete p;
+    dbg_printf("TRUE\n");
+    return TRUE;
+  }
+
+  dbg_printf("FALSE\n");
+  return FALSE;
+}
+
+static int adplug_get_time(void)
+{
+  if(audio_error) { dbg_printf("adplug_get_time(): returned -2\n"); return -2; }
+  if(!plr.playing) { dbg_printf("adplug_get_time(): returned -1\n"); return -1; }
+  return adplug_ip.output->output_time();
+}
+
+static void adplug_song_info(char *filename, char **title, int *length)
+{
+  CSilentopl tmpopl;
+  CPlayer *p = factory(filename, &tmpopl);
+
+  dbg_printf("adplug_song_info(\"%s\", \"%s\", %d): ", filename, *title, *length);
+
+  if(p) {
+    // allocate and set title string
+    if(p->gettitle().empty())
+      *title = 0;
+    else {
+      *title = (char *)malloc(p->gettitle().length() + 1);
+      strcpy(*title, p->gettitle().c_str());
+    }
+
+    // get song length
+    *length = p->songlength(plr.subsong);
+
+    // delete temporary player object
+    delete p;
+  }
+
+  dbg_printf("title = \"%s\", length = %d\n", *title, *length);
+}
+
+/***** Player control *****/
+
+static void adplug_play(char *filename)
+{
+  dbg_printf("adplug_play(\"%s\"): ", filename);
+  audio_error = FALSE;
+
+#if 0
+  // On new song, re-open "Song info" dialog, if open
+  dbg_printf("dialog, ");
+  if(plr.infobox && strcmp(filename, plr.filename))
+    gtk_widget_destroy(GTK_WIDGET(plr.infodlg));
+#endif
+
+  // open output plugin
+  dbg_printf("open, ");
+  if (!adplug_ip.output->open_audio(cfg.bit16 ? FORMAT_16 : FORMAT_8, cfg.freq, cfg.stereo ? 2 : 1)) {
+    audio_error = TRUE;
+    return;
+  }
+
+  // Initialize global player data (this is here to prevent a race condition
+  // between adplug_get_time() returning the playback state and adplug_loop()
+  // initializing the playback state)
+  dbg_printf("init, ");
+  plr.playing = true; plr.time_ms = 0.0f; plr.seek = -1;
+
+  // start player thread
+  dbg_printf("create");
+  plr.play_thread = g_thread_create(play_loop, filename, TRUE, NULL);
+  dbg_printf(".\n");
+}
+
+static void adplug_stop(void)
+{
+  dbg_printf("adplug_stop(): join, ");
+  plr.playing = false; g_thread_join(plr.play_thread); // stop player thread
+  dbg_printf("close"); adplug_ip.output->close_audio();
+  dbg_printf(".\n");
+}
+
+static void adplug_pause(short paused)
+{
+  dbg_printf("adplug_pause(%d)\n", paused);
+  adplug_ip.output->pause(paused);
+}
+
+static void adplug_seek(int time)
+{
+  dbg_printf("adplug_seek(%d)\n", time);
+  plr.seek = time * 1000; // time is in seconds, but we count in ms
+}
+
+/***** Configuration file handling *****/
+
+#define CFG_VERSION "AdPlug"
+
+static void adplug_init(void)
+{
+  dbg_printf("adplug_init(): open, ");
+  ConfigDb *db = bmp_cfg_db_open();
+
+  // Read configuration
+  dbg_printf("read, ");
+  bmp_cfg_db_get_bool(db, CFG_VERSION, "16bit", (gboolean *)&cfg.bit16);
+  bmp_cfg_db_get_bool(db, CFG_VERSION, "Stereo", (gboolean *)&cfg.stereo);
+  bmp_cfg_db_get_int(db, CFG_VERSION, "Frequency", (gint *)&cfg.freq);
+  bmp_cfg_db_get_bool(db, CFG_VERSION, "Endless", (gboolean *)&cfg.endless);
+  bmp_cfg_db_get_bool(db, CFG_VERSION, "QuickDetect", (gboolean *)&cfg.quickdetect);
+
+  // Read file type exclusion list
+  dbg_printf("exclusion, ");
+  {
+    gchar *cfgstr = "", *exclude;
+    gboolean cfgread;
+
+    cfgread = bmp_cfg_db_get_string(db, CFG_VERSION, "Exclude", &cfgstr);
+    exclude = (char *)malloc(strlen(cfgstr) + 2); strcpy(exclude, cfgstr);
+    exclude[strlen(exclude) + 1] = '\0';
+    if(cfgread) free(cfgstr);
+    g_strdelimit(exclude, ":", '\0');
+    for(gchar *p = exclude; *p; p += strlen(p) + 1)
+      cfg.players.remove(cfg.players.lookup_filetype(p));
+    free(exclude);
+  }
+  bmp_cfg_db_close(db);
+
+  // Load database from disk and hand it to AdPlug
+  dbg_printf("database");
+  plr.db = new CAdPlugDatabase;
+
+  {
+    const char *homedir = getenv("HOME");
+
+    if(homedir) {
+      char *userdb = (char *)malloc(strlen(homedir) + strlen(ADPLUG_CONFDIR) +
+				    strlen(ADPLUGDB_FILE) + 3);
+      strcpy(userdb, homedir); strcat(userdb, "/" ADPLUG_CONFDIR "/");
+      strcat(userdb, ADPLUGDB_FILE);
+      plr.db->load(userdb);		// load user's database
+      dbg_printf(" (userdb=\"%s\")", userdb);
+    }
+  }
+  CAdPlug::set_database(plr.db);
+  dbg_printf(".\n");
+}
+
+static void adplug_quit(void)
+{
+  dbg_printf("adplug_quit(): open, ");
+  ConfigDb *db = bmp_cfg_db_open();
+
+  // Close database
+  dbg_printf("db, ");
+  if(plr.db) delete plr.db;
+
+  // Write configuration
+  dbg_printf("write, ");
+  bmp_cfg_db_set_bool(db, CFG_VERSION, "16bit", cfg.bit16);
+  bmp_cfg_db_set_bool(db, CFG_VERSION, "Stereo", cfg.stereo);
+  bmp_cfg_db_set_int(db, CFG_VERSION, "Frequency", cfg.freq);
+  bmp_cfg_db_set_bool(db, CFG_VERSION, "Endless", cfg.endless);
+  bmp_cfg_db_set_bool(db, CFG_VERSION, "QuickDetect", cfg.quickdetect);
+
+  dbg_printf("exclude, ");
+  std::string exclude;
+  for(CPlayers::const_iterator i = CAdPlug::players.begin();
+      i != CAdPlug::players.end(); i++)
+    if(find(cfg.players.begin(), cfg.players.end(), *i) == cfg.players.end()) {
+      if(!exclude.empty()) exclude += ":";
+      exclude += (*i)->filetype;
+    }
+  gchar *cfgval = g_strdup(exclude.c_str());
+  bmp_cfg_db_set_string(db, CFG_VERSION, "Exclude", cfgval);
+  free(cfgval);
+
+  dbg_printf("close");
+  bmp_cfg_db_close(db);
+  dbg_printf(".\n");
+}
+
+/***** Plugin (exported) *****/
+
+InputPlugin adplug_ip =
+  {
+    NULL,                       // handle (filled by XMMS)
+    NULL,                       // filename (filled by XMMS)
+    ADPLUG_NAME,        // plugin description
+    adplug_init,                // plugin functions...
+    adplug_about,
+    adplug_config,
+    adplug_is_our_file,
+    NULL, // scan_dir (look in Input/cdaudio/cdaudio.c)
+    adplug_play,
+    adplug_stop,
+    adplug_pause,
+    adplug_seek,
+    NULL, // set_eq
+    adplug_get_time,
+    NULL,                       // get_volume (handled by output plugin)
+    NULL,                       // set_volume (...)
+    adplug_quit,
+    NULL,                       // OBSOLETE - DO NOT USE!
+    NULL,                       // add_vis_pcm (filled by XMMS)
+    NULL,                       // set_info (filled by XMMS)
+    NULL,                       // set_info_text (filled by XMMS)
+    adplug_song_info,
+    NULL,                       // adplug_info_box was here (but it used deprecated GTK+ functions)
+    NULL                        // output plugin (filled by XMMS)
+  };
+
+extern "C" InputPlugin *get_iplugin_info(void)
+{
+  return &adplug_ip;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/Makefile.am	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,21 @@
+noinst_LTLIBRARIES = libadplugcore.la
+
+libadplugcore_la_SOURCES = adplug.cpp emuopl.cpp fmopl.c diskopl.cpp debug.c \
+debug.h fprovide.cpp player.cpp database.cpp hsc.cpp sng.cpp imf.cpp \
+players.cpp protrack.cpp a2m.cpp adtrack.cpp amd.cpp bam.cpp d00.cpp dfm.cpp \
+hsp.cpp ksm.cpp mad.cpp mid.cpp mkj.cpp cff.cpp dmo.cpp s3m.cpp dtm.cpp \
+fmc.cpp mtk.cpp rad.cpp raw.cpp sa2.cpp xad.cpp flash.cpp bmf.cpp hybrid.cpp \
+hyp.cpp psi.cpp rat.cpp u6m.cpp rol.cpp mididata.h xsm.cpp adlibemu.c dro.cpp \
+lds.cpp
+
+# This is a hack. Throughout AdPlug, stricmp() is used to do caseless string
+# comparations. UNIX libc's don't support stricmp(), but do support the BSD
+# strcasecmp(), so we have to replace every occurance of stricmp() into
+# strcasecmp(). stricmp() seems to be Windows, but maybe also POSIX...
+AM_CPPFLAGS = -Dstricmp=strcasecmp
+
+noinst_HEADERS = adplug.h emuopl.h fmopl.h silentopl.h opl.h diskopl.h \
+a2m.h amd.h bam.h d00.h dfm.h hsc.h hsp.h imf.h ksm.h lds.h mid.h mkj.h \
+mtk.h protrack.h rad.h raw.h s3m.h sa2.h sng.h u6m.h player.h fmc.h mad.h \
+xad.h bmf.h flash.h hyp.h psi.h rat.h hybrid.h rol.h adtrack.h cff.h dtm.h \
+dmo.h fprovide.h database.h players.h xsm.h adlibemu.h kemuopl.h dro.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/Makefile.bt	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,26 @@
+# AdPlug Makefile for Watcom and OpenWatcom
+# Copyright (c) 2001 - 2004 Simon Peter <dn.tlp@gmx.net>
+
+# This flag is set to work around a bug in the Watcom 11.0c compiler in
+# conjunction with the STLport library. Without it, the compiler will crash
+# during compilation of some files and create very fragile code for others.
+CXXFLAGS = -oi+
+
+OUTPUT = adplug.lib
+
+OBJS = debug.obj adplug.obj emuopl.obj fmopl.obj realopl.obj analopl.obj &
+diskopl.obj database.obj player.obj players.obj fprovide.obj protrack.obj &
+a2m.obj hsc.obj imf.obj sng.obj amd.obj d00.obj dfm.obj hsp.obj ksm.obj &
+mid.obj mkj.obj mtk.obj rad.obj raw.obj s3m.obj sa2.obj bam.obj xad.obj &
+mad.obj fmc.obj bmf.obj flash.obj hybrid.obj hyp.obj psi.obj rat.obj lds.obj &
+adtrack.obj cff.obj dtm.obj dmo.obj u6m.obj rol.obj xsm.obj dro.obj
+
+include_INST = protrack.h a2m.h amd.h d00.h dfm.h hsc.h hsp.h imf.h ksm.h &
+mid.h mkj.h mtk.h rad.h raw.h s3m.h sa2.h sng.h bam.h xad.h mad.h fmc.h &
+bmf.h flash.h hybrid.h hyp.h psi.h rat.h adplug.h emuopl.h fmopl.h realopl.h &
+analopl.h diskopl.h player.h opl.h silentopl.h lds.h adtrack.h cff.h dtm.h &
+dmo.h u6m.h rol.h database.h fprovide.h players.h xsm.h dro.h
+
+lib_INST = adplug.lib
+
+includesubdir = adplug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/a2m.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,449 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2002 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * a2m.cpp - A2M Loader by Simon Peter <dn.tlp@gmx.net>
+ *
+ * NOTES:
+ * This loader detects and loads version 1, 4, 5 & 8 files.
+ *
+ * version 1-4 files:
+ * Following commands are ignored:
+ * FF1 - FF9, FAx - FEx
+ *
+ * version 5-8 files:
+ * Instrument panning is ignored. Flags byte is ignored.
+ * Following commands are ignored:
+ * Gxy, Hxy, Kxy - &xy
+ */
+
+#include "a2m.h"
+
+const unsigned int Ca2mLoader::MAXFREQ = 2000,
+Ca2mLoader::MINCOPY = ADPLUG_A2M_MINCOPY,
+Ca2mLoader::MAXCOPY = ADPLUG_A2M_MAXCOPY,
+Ca2mLoader::COPYRANGES = ADPLUG_A2M_COPYRANGES,
+Ca2mLoader::CODESPERRANGE = ADPLUG_A2M_CODESPERRANGE,
+Ca2mLoader::TERMINATE = 256,
+Ca2mLoader::FIRSTCODE = ADPLUG_A2M_FIRSTCODE,
+Ca2mLoader::MAXCHAR = FIRSTCODE + COPYRANGES * CODESPERRANGE - 1,
+Ca2mLoader::SUCCMAX = MAXCHAR + 1,
+Ca2mLoader::TWICEMAX = ADPLUG_A2M_TWICEMAX,
+Ca2mLoader::ROOT = 1, Ca2mLoader::MAXBUF = 42 * 1024,
+Ca2mLoader::MAXDISTANCE = 21389, Ca2mLoader::MAXSIZE = 21389 + MAXCOPY;
+
+const unsigned short Ca2mLoader::bitvalue[14] =
+  {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192};
+
+const signed short Ca2mLoader::copybits[COPYRANGES] =
+  {4, 6, 8, 10, 12, 14};
+
+const signed short Ca2mLoader::copymin[COPYRANGES] =
+  {0, 16, 80, 336, 1360, 5456};
+
+CPlayer *Ca2mLoader::factory(Copl *newopl)
+{
+  return new Ca2mLoader(newopl);
+}
+
+bool Ca2mLoader::load(const std::string &filename, const CFileProvider &fp)
+{
+  binistream *f = fp.open(filename); if(!f) return false;
+  struct {
+    char id[10];
+    unsigned long crc;
+    unsigned char version,numpats;
+  } ch;
+  int i,j,k,t;
+  unsigned int l;
+  unsigned char *org, *orgptr;
+  unsigned long alength;
+  unsigned short len[9], *secdata, *secptr;
+  const unsigned char convfx[16] = {0,1,2,23,24,3,5,4,6,9,17,13,11,19,7,14};
+  const unsigned char convinf1[16] = {0,1,2,6,7,8,9,4,5,3,10,11,12,13,14,15};
+  const unsigned char newconvfx[] = {0,1,2,3,4,5,6,23,24,21,10,11,17,13,7,19,
+				     255,255,22,25,255,15,255,255,255,255,255,
+				     255,255,255,255,255,255,255,255,14,255};
+
+  // read header
+  f->readString(ch.id, 10); ch.crc = f->readInt(4);
+  ch.version = f->readInt(1); ch.numpats = f->readInt(1);
+
+  // file validation section
+  if(strncmp(ch.id,"_A2module_",10) || (ch.version != 1 && ch.version != 5 &&
+					ch.version != 4 && ch.version != 8)) {
+    fp.close(f);
+    return false;
+  }
+
+  // load, depack & convert section
+  nop = ch.numpats; length = 128; restartpos = 0; activechan = 0xffff;
+  if(ch.version == 1 || ch.version == 4) {
+    for(i=0;i<5;i++) len[i] = f->readInt(2);
+    t = 9;
+  } else {
+    for(i=0;i<9;i++) len[i] = f->readInt(2);
+    t = 18;
+  }
+
+  // block 0
+  secdata = new unsigned short [len[0] / 2];
+  if(ch.version == 1 || ch.version == 5) {
+    for(i=0;i<len[0]/2;i++) secdata[i] = f->readInt(2);
+    org = new unsigned char [MAXBUF]; orgptr = org;
+    sixdepak(secdata,org,len[0]);
+  } else {
+    orgptr = (unsigned char *)secdata;
+    for(i=0;i<len[0];i++) orgptr[i] = f->readInt(1);
+  }
+  memcpy(songname,orgptr,43); orgptr += 43;
+  memcpy(author,orgptr,43); orgptr += 43;
+  memcpy(instname,orgptr,250*33); orgptr += 250*33;
+  for(i=0;i<250;i++) {	// instruments
+    inst[i].data[0] = *(orgptr+i*13+10);
+    inst[i].data[1] = *(orgptr+i*13);
+    inst[i].data[2] = *(orgptr+i*13+1);
+    inst[i].data[3] = *(orgptr+i*13+4);
+    inst[i].data[4] = *(orgptr+i*13+5);
+    inst[i].data[5] = *(orgptr+i*13+6);
+    inst[i].data[6] = *(orgptr+i*13+7);
+    inst[i].data[7] = *(orgptr+i*13+8);
+    inst[i].data[8] = *(orgptr+i*13+9);
+    inst[i].data[9] = *(orgptr+i*13+2);
+    inst[i].data[10] = *(orgptr+i*13+3);
+    if(ch.version == 1 || ch.version == 4)
+      inst[i].misc = *(orgptr+i*13+11);
+    else
+      inst[i].misc = 0;
+    inst[i].slide = *(orgptr+i*13+12);
+  }
+
+  orgptr += 250*13;
+  memcpy(order,orgptr,128); orgptr += 128;
+  bpm = *orgptr; orgptr += 1;
+  initspeed = *orgptr;
+  // v5-8 files have an additional flag byte here
+  if(ch.version == 1 || ch.version == 5)
+    delete [] org;
+  delete [] secdata;
+
+  // blocks 1-4 or 1-8
+  alength = len[1];
+  for(i=0;i<(ch.version == 1 || ch.version == 4 ? ch.numpats/16 : ch.numpats/8);i++)
+    alength += len[i+2];
+
+  secdata = new unsigned short [alength / 2];
+  if(ch.version == 1 || ch.version == 5) {
+    for(l=0;l<alength/2;l++) secdata[l] = f->readInt(2);
+    org = new unsigned char [MAXBUF * (ch.numpats / (ch.version == 1 ? 16 : 8) + 1)];
+    orgptr = org; secptr = secdata;
+    orgptr += sixdepak(secptr,orgptr,len[1]); secptr += len[1] / 2;
+    if(ch.version == 1) {
+      if(ch.numpats > 16)
+	orgptr += sixdepak(secptr,orgptr,len[2]); secptr += len[2] / 2;
+      if(ch.numpats > 32)
+	orgptr += sixdepak(secptr,orgptr,len[3]); secptr += len[3] / 2;
+      if(ch.numpats > 48)
+	sixdepak(secptr,orgptr,len[4]);
+    } else {
+      if(ch.numpats > 8)
+	orgptr += sixdepak(secptr,orgptr,len[2]); secptr += len[2] / 2;
+      if(ch.numpats > 16)
+	orgptr += sixdepak(secptr,orgptr,len[3]); secptr += len[3] / 2;
+      if(ch.numpats > 24)
+	orgptr += sixdepak(secptr,orgptr,len[4]); secptr += len[4] / 2;
+      if(ch.numpats > 32)
+	orgptr += sixdepak(secptr,orgptr,len[5]); secptr += len[5] / 2;
+      if(ch.numpats > 40)
+	orgptr += sixdepak(secptr,orgptr,len[6]); secptr += len[6] / 2;
+      if(ch.numpats > 48)
+	orgptr += sixdepak(secptr,orgptr,len[7]); secptr += len[7] / 2;
+      if(ch.numpats > 56)
+	sixdepak(secptr,orgptr,len[8]);
+    }
+    delete [] secdata;
+  } else {
+    org = (unsigned char *)secdata;
+    for(l=0;l<alength;l++) org[l] = f->readInt(1);
+  }
+
+  for(i=0;i<64*9;i++)		// patterns
+    trackord[i/9][i%9] = i+1;
+
+  if(ch.version == 1 || ch.version == 4) {
+    for(i=0;i<ch.numpats;i++)
+      for(j=0;j<64;j++)
+	for(k=0;k<9;k++) {
+	  tracks[i*9+k][j].note = org[i*64*t*4+j*t*4+k*4] == 255 ? 127 : org[i*64*t*4+j*t*4+k*4];
+	  tracks[i*9+k][j].inst = org[i*64*t*4+j*t*4+k*4+1];
+	  tracks[i*9+k][j].command = convfx[org[i*64*t*4+j*t*4+k*4+2]];
+	  tracks[i*9+k][j].param2 = org[i*64*t*4+j*t*4+k*4+3] & 0x0f;
+	  if(tracks[i*9+k][j].command != 14)
+	    tracks[i*9+k][j].param1 = org[i*64*t*4+j*t*4+k*4+3] >> 4;
+	  else {
+	    tracks[i*9+k][j].param1 = convinf1[org[i*64*t*4+j*t*4+k*4+3] >> 4];
+	    if(tracks[i*9+k][j].param1 == 15 && !tracks[i*9+k][j].param2) {	// convert key-off
+	      tracks[i*9+k][j].command = 8;
+	      tracks[i*9+k][j].param1 = 0;
+	      tracks[i*9+k][j].param2 = 0;
+	    }
+	  }
+	  if(tracks[i*9+k][j].command == 14) {
+	    switch(tracks[i*9+k][j].param1) {
+	    case 2: // convert define waveform
+	      tracks[i*9+k][j].command = 25;
+	      tracks[i*9+k][j].param1 = tracks[i*9+k][j].param2;
+	      tracks[i*9+k][j].param2 = 0xf;
+	      break;
+	    case 8: // convert volume slide up
+	      tracks[i*9+k][j].command = 26;
+	      tracks[i*9+k][j].param1 = tracks[i*9+k][j].param2;
+	      tracks[i*9+k][j].param2 = 0;
+	      break;
+	    case 9: // convert volume slide down
+	      tracks[i*9+k][j].command = 26;
+	      tracks[i*9+k][j].param1 = 0;
+	      break;
+	    }
+	  }
+	}
+  } else {
+    for(i=0;i<ch.numpats;i++)
+      for(j=0;j<9;j++)
+	for(k=0;k<64;k++) {
+	  tracks[i*9+j][k].note = org[i*64*t*4+j*64*4+k*4] == 255 ? 127 : org[i*64*t*4+j*64*4+k*4];
+	  tracks[i*9+j][k].inst = org[i*64*t*4+j*64*4+k*4+1];
+	  tracks[i*9+j][k].command = newconvfx[org[i*64*t*4+j*64*4+k*4+2]];
+	  tracks[i*9+j][k].param1 = org[i*64*t*4+j*64*4+k*4+3] >> 4;
+	  tracks[i*9+j][k].param2 = org[i*64*t*4+j*64*4+k*4+3] & 0x0f;
+	}
+  }
+
+  if(ch.version == 1 || ch.version == 5)
+    delete [] org;
+  else
+    delete [] secdata;
+  fp.close(f);
+  rewind(0);
+  return true;
+}
+
+float Ca2mLoader::getrefresh()
+{
+	if(tempo != 18)
+		return (float) (tempo);
+	else
+		return 18.2f;
+}
+
+/*** private methods *************************************/
+
+void Ca2mLoader::inittree()
+{
+	unsigned short i;
+
+	for(i=2;i<=TWICEMAX;i++) {
+		dad[i] = i / 2;
+		freq[i] = 1;
+	}
+
+	for(i=1;i<=MAXCHAR;i++) {
+		leftc[i] = 2 * i;
+		rghtc[i] = 2 * i + 1;
+	}
+}
+
+void Ca2mLoader::updatefreq(unsigned short a,unsigned short b)
+{
+	do {
+		freq[dad[a]] = freq[a] + freq[b];
+		a = dad[a];
+		if(a != ROOT)
+			if(leftc[dad[a]] == a)
+				b = rghtc[dad[a]];
+			else
+				b = leftc[dad[a]];
+	} while(a != ROOT);
+
+	if(freq[ROOT] == MAXFREQ)
+		for(a=1;a<=TWICEMAX;a++)
+			freq[a] >>= 1;
+}
+
+void Ca2mLoader::updatemodel(unsigned short code)
+{
+	unsigned short a=code+SUCCMAX,b,c,code1,code2;
+
+	freq[a]++;
+	if(dad[a] != ROOT) {
+		code1 = dad[a];
+		if(leftc[code1] == a)
+			updatefreq(a,rghtc[code1]);
+		else
+			updatefreq(a,leftc[code1]);
+
+		do {
+			code2 = dad[code1];
+			if(leftc[code2] == code1)
+				b = rghtc[code2];
+			else
+				b = leftc[code2];
+
+			if(freq[a] > freq[b]) {
+				if(leftc[code2] == code1)
+					rghtc[code2] = a;
+				else
+					leftc[code2] = a;
+
+				if(leftc[code1] == a) {
+					leftc[code1] = b;
+					c = rghtc[code1];
+				} else {
+					rghtc[code1] = b;
+					c = leftc[code1];
+				}
+
+				dad[b] = code1;
+				dad[a] = code2;
+				updatefreq(b,c);
+				a = b;
+			}
+
+			a = dad[a];
+			code1 = dad[a];
+		} while(code1 != ROOT);
+	}
+}
+
+unsigned short Ca2mLoader::inputcode(unsigned short bits)
+{
+	unsigned short i,code=0;
+
+	for(i=1;i<=bits;i++) {
+		if(!ibitcount) {
+			if(ibitcount == MAXBUF)
+				ibufcount = 0;
+			ibitbuffer = wdbuf[ibufcount];
+			ibufcount++;
+			ibitcount = 15;
+		} else
+			ibitcount--;
+
+		if(ibitbuffer > 0x7fff)
+			code |= bitvalue[i-1];
+		ibitbuffer <<= 1;
+	}
+
+	return code;
+}
+
+unsigned short Ca2mLoader::uncompress()
+{
+	unsigned short a=1;
+
+	do {
+		if(!ibitcount) {
+			if(ibufcount == MAXBUF)
+				ibufcount = 0;
+			ibitbuffer = wdbuf[ibufcount];
+			ibufcount++;
+			ibitcount = 15;
+		} else
+			ibitcount--;
+
+		if(ibitbuffer > 0x7fff)
+			a = rghtc[a];
+		else
+			a = leftc[a];
+		ibitbuffer <<= 1;
+	} while(a <= MAXCHAR);
+
+	a -= SUCCMAX;
+	updatemodel(a);
+	return a;
+}
+
+void Ca2mLoader::decode()
+{
+	unsigned short i,j,k,t,c,count=0,dist,len,index;
+
+	inittree();
+	c = uncompress();
+
+	while(c != TERMINATE) {
+		if(c < 256) {
+			obuf[obufcount] = (unsigned char)c;
+			obufcount++;
+			if(obufcount == MAXBUF) {
+				output_size = MAXBUF;
+				obufcount = 0;
+			}
+
+			buf[count] = (unsigned char)c;
+			count++;
+			if(count == MAXSIZE)
+				count = 0;
+		} else {
+			t = c - FIRSTCODE;
+			index = t / CODESPERRANGE;
+			len = t + MINCOPY - index * CODESPERRANGE;
+			dist = inputcode(copybits[index]) + len + copymin[index];
+
+			j = count;
+			k = count - dist;
+			if(count < dist)
+				k += MAXSIZE;
+
+			for(i=0;i<=len-1;i++) {
+				obuf[obufcount] = buf[k];
+				obufcount++;
+				if(obufcount == MAXBUF) {
+					output_size = MAXBUF;
+					obufcount = 0;
+				}
+
+				buf[j] = buf[k];
+				j++; k++;
+				if(j == MAXSIZE) j = 0;
+				if(k == MAXSIZE) k = 0;
+			}
+
+			count += len;
+			if(count >= MAXSIZE)
+				count -= MAXSIZE;
+		}
+		c = uncompress();
+	}
+	output_size = obufcount;
+}
+
+unsigned short Ca2mLoader::sixdepak(unsigned short *source, unsigned char *dest,
+				    unsigned short size)
+{
+	if((unsigned int)size + 4096 > MAXBUF)
+		return 0;
+
+	buf = new unsigned char [MAXSIZE];
+	input_size = size;
+	ibitcount = 0; ibitbuffer = 0;
+	obufcount = 0; ibufcount = 0;
+	wdbuf = source; obuf = dest;
+
+	decode();
+	delete [] buf;
+	return output_size;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/a2m.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,80 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2002 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * a2m.h - A2M Loader by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "protrack.h"
+
+class Ca2mLoader: public CmodPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	Ca2mLoader(Copl *newopl)
+		: CmodPlayer(newopl)
+	{ };
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+	float getrefresh();
+
+	std::string gettype()
+	{ return std::string("AdLib Tracker 2"); };
+	std::string gettitle()
+	{ if(*songname) return std::string(songname,1,*songname); else return std::string(); };
+	std::string getauthor()
+	{ if(*author) return std::string(author,1,*author); else return std::string(); };
+	unsigned int getinstruments()
+	{ return 250; };
+	std::string getinstrument(unsigned int n)
+	{ return std::string(instname[n],1,*instname[n]); };
+
+private:
+
+#define ADPLUG_A2M_COPYRANGES		6
+#define ADPLUG_A2M_FIRSTCODE		257
+#define ADPLUG_A2M_MINCOPY			3
+#define ADPLUG_A2M_MAXCOPY			255
+#define ADPLUG_A2M_CODESPERRANGE	(ADPLUG_A2M_MAXCOPY - ADPLUG_A2M_MINCOPY + 1)
+#define ADPLUG_A2M_MAXCHAR			(ADPLUG_A2M_FIRSTCODE + \
+	ADPLUG_A2M_COPYRANGES * ADPLUG_A2M_CODESPERRANGE - 1)
+#define ADPLUG_A2M_TWICEMAX			(2 * ADPLUG_A2M_MAXCHAR + 1)
+
+	static const unsigned int MAXFREQ, MINCOPY, MAXCOPY, COPYRANGES,
+		CODESPERRANGE, TERMINATE, FIRSTCODE, MAXCHAR, SUCCMAX, TWICEMAX, ROOT,
+		MAXBUF, MAXDISTANCE, MAXSIZE;
+
+	static const unsigned short bitvalue[14];
+	static const signed short copybits[ADPLUG_A2M_COPYRANGES],
+		copymin[ADPLUG_A2M_COPYRANGES];
+
+	void inittree();
+	void updatefreq(unsigned short a,unsigned short b);
+	void updatemodel(unsigned short code);
+	unsigned short inputcode(unsigned short bits);
+	unsigned short uncompress();
+	void decode();
+	unsigned short sixdepak(unsigned short *source,unsigned char *dest,unsigned short size);
+
+	char songname[43], author[43], instname[250][33];
+
+	unsigned short ibitcount, ibitbuffer, ibufcount, obufcount, input_size,
+		output_size, leftc[ADPLUG_A2M_MAXCHAR+1], rghtc[ADPLUG_A2M_MAXCHAR+1],
+		dad[ADPLUG_A2M_TWICEMAX+1], freq[ADPLUG_A2M_TWICEMAX+1], *wdbuf;
+	unsigned char *obuf, *buf;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/adlibemu.c	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,600 @@
+/*
+ * ADLIBEMU.C
+ * Copyright (C) 1998-2001 Ken Silverman
+ * Ken Silverman's official web site: "http://www.advsys.net/ken"
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+This file is a digital Adlib emulator for OPL2 and possibly OPL3
+
+Features that could be added in a future version:
+- Amplitude and Frequency Vibrato Bits (not hard, but a big speed hit)
+- Global Keyboard Split Number Bit (need to research this one some more)
+- 2nd Adlib chip for OPL3 (simply need to make my cell array bigger)
+- Advanced connection modes of OPL3 (Just need to add more "docell" cases)
+- L/R Stereo bits of OPL3 (Need adlibgetsample to return stereo)
+
+Features that aren't worth supporting:
+- Anything related to adlib timers&interrupts (Sorry - I always used IRQ0)
+- Composite sine wave mode (CSM) (Supported only on ancient cards)
+
+I'm not sure about a few things in my code:
+- Attack curve.  What function is this anyway?  I chose to use an order-3
+  polynomial to approximate but this doesn't seem right.
+- Attack/Decay/Release constants - my constants may not be exact
+- What should ADJUSTSPEED be?
+- Haven't verified that Global Keyboard Split Number Bit works yet
+- Some of the drums don't always sound right.  It's pretty hard to guess
+  the exact waveform of drums when you look at random data which is
+  slightly randomized due to digital ADC recording.
+- Adlib seems to have a lot more treble than my emulator does.  I'm not
+  sure if this is simply unfixable due to the sound blaster's different
+  filtering on FM and digital playback or if it's a serious bug in my
+  code.
+*/
+
+#include <math.h>
+#include <string.h>
+
+#if !defined(max) && !defined(__cplusplus)
+#define max(a,b)  (((a) > (b)) ? (a) : (b))
+#endif
+#if !defined(min) && !defined(__cplusplus)
+#define min(a,b)  (((a) < (b)) ? (a) : (b))
+#endif
+
+#define PI 3.141592653589793
+#define MAXCELLS 18
+#define WAVPREC 2048
+
+static float AMPSCALE=(8192.0);
+#define FRQSCALE (49716/512.0)
+
+//Constants for Ken's Awe32, on a PII-266 (Ken says: Use these for KSM's!)
+#define MODFACTOR 4.0      //How much of modulator cell goes into carrier
+#define MFBFACTOR 1.0      //How much feedback goes back into modulator
+#define ADJUSTSPEED 0.75   //0<=x<=1  Simulate finite rate of change of state
+
+//Constants for Ken's Awe64G, on a P-133
+//#define MODFACTOR 4.25   //How much of modulator cell goes into carrier
+//#define MFBFACTOR 0.5    //How much feedback goes back into modulator
+//#define ADJUSTSPEED 0.85 //0<=x<=1  Simulate finite rate of change of state
+
+typedef struct
+{
+    float val, t, tinc, vol, sustain, amp, mfb;
+    float a0, a1, a2, a3, decaymul, releasemul;
+    short *waveform;
+    long wavemask;
+    void (*cellfunc)(void *, float);
+    unsigned char flags, dum0, dum1, dum2;
+} celltype;
+
+static long numspeakers, bytespersample;
+static float recipsamp;
+static celltype cell[MAXCELLS];
+static signed short wavtable[WAVPREC*3];
+static float kslmul[4] = {0.0,0.5,0.25,1.0};
+static float frqmul[16] = {.5,1,2,3,4,5,6,7,8,9,10,10,12,12,15,15}, nfrqmul[16];
+static unsigned char adlibreg[256], ksl[8][16];
+static unsigned char modulatorbase[9] = {0,1,2,8,9,10,16,17,18};
+static unsigned char odrumstat = 0;
+static unsigned char base2cell[22] = {0,1,2,0,1,2,0,0,3,4,5,3,4,5,0,0,6,7,8,6,7,8};
+
+float lvol[9] = {1,1,1,1,1,1,1,1,1};  //Volume multiplier on left speaker
+float rvol[9] = {1,1,1,1,1,1,1,1,1};  //Volume multiplier on right speaker
+long lplc[9] = {0,0,0,0,0,0,0,0,0};   //Samples to delay on left speaker
+long rplc[9] = {0,0,0,0,0,0,0,0,0};   //Samples to delay on right speaker
+
+long nlvol[9], nrvol[9];
+long nlplc[9], nrplc[9];
+long rend = 0;
+#define FIFOSIZ 256
+static float *rptr[9], *nrptr[9];
+static float rbuf[9][FIFOSIZ*2];
+static float snd[FIFOSIZ*2];
+
+#ifndef USING_ASM
+#define _inline
+#endif
+
+#ifdef USING_ASM
+static _inline void ftol (float f, long *a)
+{
+    _asm
+	{
+	    mov eax, a
+		fld f
+		fistp dword ptr [eax]
+		}
+}
+#else
+static void ftol(float f, long *a) {
+    *a=f;
+}
+#endif
+
+#define ctc ((celltype *)c)      //A rare attempt to make code easier to read!
+void docell4 (void *c, float modulator) { }
+void docell3 (void *c, float modulator)
+{
+    long i;
+
+    ftol(ctc->t+modulator,&i);
+    ctc->t += ctc->tinc;
+    ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED;
+}
+void docell2 (void *c, float modulator)
+{
+    long i;
+
+    ftol(ctc->t+modulator,&i);
+
+    if (*(long *)&ctc->amp <= 0x37800000)
+    {
+	ctc->amp = 0;
+	ctc->cellfunc = docell4;
+    }
+    ctc->amp *= ctc->releasemul;
+
+    ctc->t += ctc->tinc;
+    ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED;
+}
+void docell1 (void *c, float modulator)
+{
+    long i;
+
+    ftol(ctc->t+modulator,&i);
+
+    if ((*(long *)&ctc->amp) <= (*(long *)&ctc->sustain))
+    {
+	if (ctc->flags&32)
+	{
+	    ctc->amp = ctc->sustain;
+	    ctc->cellfunc = docell3;
+	}
+	else
+	    ctc->cellfunc = docell2;
+    }
+    else
+	ctc->amp *= ctc->decaymul;
+
+    ctc->t += ctc->tinc;
+    ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED;
+}
+void docell0 (void *c, float modulator)
+{
+    long i;
+
+    ftol(ctc->t+modulator,&i);
+
+    ctc->amp = ((ctc->a3*ctc->amp + ctc->a2)*ctc->amp + ctc->a1)*ctc->amp + ctc->a0;
+    if ((*(long *)&ctc->amp) > 0x3f800000)
+    {
+	ctc->amp = 1;
+	ctc->cellfunc = docell1;
+    }
+
+    ctc->t += ctc->tinc;
+    ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED;
+}
+
+
+static long waveform[8] = {WAVPREC,WAVPREC>>1,WAVPREC,(WAVPREC*3)>>2,0,0,(WAVPREC*5)>>2,WAVPREC<<1};
+static long wavemask[8] = {WAVPREC-1,WAVPREC-1,(WAVPREC>>1)-1,(WAVPREC>>1)-1,WAVPREC-1,((WAVPREC*3)>>2)-1,WAVPREC>>1,WAVPREC-1};
+static long wavestart[8] = {0,WAVPREC>>1,0,WAVPREC>>2,0,0,0,WAVPREC>>3};
+static float attackconst[4] = {1/2.82624,1/2.25280,1/1.88416,1/1.59744};
+static float decrelconst[4] = {1/39.28064,1/31.41608,1/26.17344,1/22.44608};
+void cellon (long i, long j, celltype *c, unsigned char iscarrier)
+{
+    long frn, oct, toff;
+    float f;
+
+    frn = ((((long)adlibreg[i+0xb0])&3)<<8) + (long)adlibreg[i+0xa0];
+    oct = ((((long)adlibreg[i+0xb0])>>2)&7);
+    toff = (oct<<1) + ((frn>>9)&((frn>>8)|(((adlibreg[8]>>6)&1)^1)));
+    if (!(adlibreg[j+0x20]&16)) toff >>= 2;
+
+    f = pow(2.0,(adlibreg[j+0x60]>>4)+(toff>>2)-1)*attackconst[toff&3]*recipsamp;
+    c->a0 = .0377*f; c->a1 = 10.73*f+1; c->a2 = -17.57*f; c->a3 = 7.42*f;
+    f = -7.4493*decrelconst[toff&3]*recipsamp;
+    c->decaymul = pow(2.0,f*pow(2.0,(adlibreg[j+0x60]&15)+(toff>>2)));
+    c->releasemul = pow(2.0,f*pow(2.0,(adlibreg[j+0x80]&15)+(toff>>2)));
+    c->wavemask = wavemask[adlibreg[j+0xe0]&7];
+    c->waveform = &wavtable[waveform[adlibreg[j+0xe0]&7]];
+    if (!(adlibreg[1]&0x20)) c->waveform = &wavtable[WAVPREC];
+    c->t = wavestart[adlibreg[j+0xe0]&7];
+    c->flags = adlibreg[j+0x20];
+    c->cellfunc = docell0;
+    c->tinc = (float)(frn<<oct)*nfrqmul[adlibreg[j+0x20]&15];
+    c->vol = pow(2.0,((float)(adlibreg[j+0x40]&63) +
+		      (float)kslmul[adlibreg[j+0x40]>>6]*ksl[oct][frn>>6]) * -.125 - 14);
+    c->sustain = pow(2.0,(float)(adlibreg[j+0x80]>>4) * -.5);
+    if (!iscarrier) c->amp = 0;
+    c->mfb = pow(2.0,((adlibreg[i+0xc0]>>1)&7)+5)*(WAVPREC/2048.0)*MFBFACTOR;
+    if (!(adlibreg[i+0xc0]&14)) c->mfb = 0;
+    c->val = 0;
+}
+
+//This function (and bug fix) written by Chris Moeller
+void cellfreq (signed long i, signed long j, celltype *c)
+{
+    long frn, oct;
+
+    frn = ((((long)adlibreg[i+0xb0])&3)<<8) + (long)adlibreg[i+0xa0];
+    oct = ((((long)adlibreg[i+0xb0])>>2)&7);
+
+    c->tinc = (float)(frn<<oct)*nfrqmul[adlibreg[j+0x20]&15];
+    c->vol = pow(2.0,((float)(adlibreg[j+0x40]&63) +
+		      (float)kslmul[adlibreg[j+0x40]>>6]*ksl[oct][frn>>6]) * -.125 - 14);
+}
+
+static long initfirstime = 0;
+void adlibinit (long dasamplerate, long danumspeakers, long dabytespersample)
+{
+    long i, j, frn, oct;
+
+    memset((void *)adlibreg,0,sizeof(adlibreg));
+    memset((void *)cell,0,sizeof(celltype)*MAXCELLS);
+    memset((void *)rbuf,0,sizeof(rbuf));
+    rend = 0; odrumstat = 0;
+
+    for(i=0;i<MAXCELLS;i++)
+    {
+	cell[i].cellfunc = docell4;
+	cell[i].amp = 0;
+	cell[i].vol = 0;
+	cell[i].t = 0;
+	cell[i].tinc = 0;
+	cell[i].wavemask = 0;
+	cell[i].waveform = &wavtable[WAVPREC];
+    }
+
+    numspeakers = danumspeakers;
+    bytespersample = dabytespersample;
+
+    recipsamp = 1.0 / (float)dasamplerate;
+    for(i=15;i>=0;i--) nfrqmul[i] = frqmul[i]*recipsamp*FRQSCALE*(WAVPREC/2048.0);
+
+    if (!initfirstime)
+    {
+	initfirstime = 1;
+
+	for(i=0;i<(WAVPREC>>1);i++)
+	{
+	    wavtable[i] =
+		wavtable[(i<<1)  +WAVPREC] = (signed short)(16384*sin((float)((i<<1)  )*PI*2/WAVPREC));
+	    wavtable[(i<<1)+1+WAVPREC] = (signed short)(16384*sin((float)((i<<1)+1)*PI*2/WAVPREC));
+	}
+	for(i=0;i<(WAVPREC>>3);i++)
+	{
+	    wavtable[i+(WAVPREC<<1)] = wavtable[i+(WAVPREC>>3)]-16384;
+	    wavtable[i+((WAVPREC*17)>>3)] = wavtable[i+(WAVPREC>>2)]+16384;
+	}
+
+	//[table in book]*8/3
+	ksl[7][0] = 0; ksl[7][1] = 24; ksl[7][2] = 32; ksl[7][3] = 37;
+	ksl[7][4] = 40; ksl[7][5] = 43; ksl[7][6] = 45; ksl[7][7] = 47;
+	ksl[7][8] = 48; for(i=9;i<16;i++) ksl[7][i] = i+41;
+	for(j=6;j>=0;j--)
+	    for(i=0;i<16;i++)
+	    {
+		oct = (long)ksl[j+1][i]-8; if (oct < 0) oct = 0;
+		ksl[j][i] = (unsigned char)oct;
+	    }
+    }
+    else
+    {
+	for(i=0;i<9;i++)
+	{
+	    frn = ((((long)adlibreg[i+0xb0])&3)<<8) + (long)adlibreg[i+0xa0];
+	    oct = ((((long)adlibreg[i+0xb0])>>2)&7);
+	    cell[i].tinc = (float)(frn<<oct)*nfrqmul[adlibreg[modulatorbase[i]+0x20]&15];
+	}
+    }
+}
+
+void adlib0 (long i, long v)
+{
+    unsigned char tmp = adlibreg[i];
+    adlibreg[i] = v;
+
+    if (i == 0xbd)
+    {
+	if ((v&16) > (odrumstat&16)) //BassDrum
+	{
+	    cellon(6,16,&cell[6],0);
+	    cellon(6,19,&cell[15],1);
+	    cell[15].vol *= 2;
+	}
+	if ((v&8) > (odrumstat&8)) //Snare
+	{
+	    cellon(16,20,&cell[16],0);
+	    cell[16].tinc *= 2*(nfrqmul[adlibreg[17+0x20]&15] / nfrqmul[adlibreg[20+0x20]&15]);
+	    if (((adlibreg[20+0xe0]&7) >= 3) && ((adlibreg[20+0xe0]&7) <= 5)) cell[16].vol = 0;
+	    cell[16].vol *= 2;
+	}
+	if ((v&4) > (odrumstat&4)) //TomTom
+	{
+	    cellon(8,18,&cell[8],0);
+	    cell[8].vol *= 2;
+	}
+	if ((v&2) > (odrumstat&2)) //Cymbal
+	{
+	    cellon(17,21,&cell[17],0);
+
+	    cell[17].wavemask = wavemask[5];
+	    cell[17].waveform = &wavtable[waveform[5]];
+	    cell[17].tinc *= 16; cell[17].vol *= 2;
+
+	    //cell[17].waveform = &wavtable[WAVPREC]; cell[17].wavemask = 0;
+	    //if (((adlibreg[21+0xe0]&7) == 0) || ((adlibreg[21+0xe0]&7) == 6))
+	    //   cell[17].waveform = &wavtable[(WAVPREC*7)>>2];
+	    //if (((adlibreg[21+0xe0]&7) == 2) || ((adlibreg[21+0xe0]&7) == 3))
+	    //   cell[17].waveform = &wavtable[(WAVPREC*5)>>2];
+	}
+	if ((v&1) > (odrumstat&1)) //Hihat
+	{
+	    cellon(7,17,&cell[7],0);
+	    if (((adlibreg[17+0xe0]&7) == 1) || ((adlibreg[17+0xe0]&7) == 4) ||
+		((adlibreg[17+0xe0]&7) == 5) || ((adlibreg[17+0xe0]&7) == 7)) cell[7].vol = 0;
+	    if ((adlibreg[17+0xe0]&7) == 6) { cell[7].wavemask = 0; cell[7].waveform = &wavtable[(WAVPREC*7)>>2]; }
+	}
+
+	odrumstat = v;
+    }
+    else if (((unsigned)(i-0x40) < (unsigned)22) && ((i&7) < 6))
+    {
+	if ((i&7) < 3) // Modulator
+	    cellfreq(base2cell[i-0x40],i-0x40,&cell[base2cell[i-0x40]]);
+	else          // Carrier
+	    cellfreq(base2cell[i-0x40],i-0x40,&cell[base2cell[i-0x40]+9]);
+    }
+    else if ((unsigned)(i-0xa0) < (unsigned)9)
+    {
+	cellfreq(i-0xa0,modulatorbase[i-0xa0],&cell[i-0xa0]);
+	cellfreq(i-0xa0,modulatorbase[i-0xa0]+3,&cell[i-0xa0+9]);
+    }
+    else if ((unsigned)(i-0xb0) < (unsigned)9)
+    {
+	if ((v&32) > (tmp&32))
+	{
+	    cellon(i-0xb0,modulatorbase[i-0xb0],&cell[i-0xb0],0);
+	    cellon(i-0xb0,modulatorbase[i-0xb0]+3,&cell[i-0xb0+9],1);
+	}
+	else if ((v&32) < (tmp&32))
+	    cell[i-0xb0].cellfunc = cell[i-0xb0+9].cellfunc = docell2;
+	cellfreq(i-0xb0,modulatorbase[i-0xb0],&cell[i-0xb0]);
+	cellfreq(i-0xb0,modulatorbase[i-0xb0]+3,&cell[i-0xb0+9]);
+    }
+
+    //outdata(i,v);
+}
+
+#ifdef USING_ASM
+static long fpuasm;
+static float fakeadd = 8388608.0+128.0;
+static _inline void clipit8 (float f, long a)
+{
+    _asm
+	{
+	    mov edi, a
+		fld dword ptr f
+		fadd dword ptr fakeadd
+		fstp dword ptr fpuasm
+		mov eax, fpuasm
+		test eax, 0x007fff00
+		jz short skipit
+		shr eax, 16
+		xor eax, -1
+		skipit: mov byte ptr [edi], al
+		}
+}
+
+static _inline void clipit16 (float f, long a)
+{
+    _asm
+	{
+	    mov eax, a
+		fld dword ptr f
+		fist word ptr [eax]
+		cmp word ptr [eax], 0x8000
+		jne short skipit2
+		fst dword ptr [fpuasm]
+		cmp fpuasm, 0x80000000
+		sbb word ptr [eax], 0
+		skipit2: fstp st
+		}
+}
+#else
+static void clipit8(float f,unsigned char *a) {
+    f/=256.0;
+    f+=128.0;
+    if (f>254.5) *a=255;
+    else if (f<0.5) *a=0;
+    else *a=f;
+}
+
+static void clipit16(float f,short *a) {
+    if (f>32766.5) *a=32767;
+    else if (f<-32767.5) *a=-32768;
+    else *a=f;
+}
+#endif
+
+void adlibsetvolume(int i) {
+    AMPSCALE=i;
+}
+
+void adlibgetsample (unsigned char *sndptr, long numbytes)
+{
+    long i, j, k=0, ns, endsamples, rptrs, numsamples;
+    celltype *cptr;
+    float f;
+    short *sndptr2=(short *)sndptr;
+
+    numsamples = (numbytes>>(numspeakers+bytespersample-2));
+
+    if (bytespersample == 1) f = AMPSCALE/256.0; else f = AMPSCALE;
+    if (numspeakers == 1)
+    {
+	nlvol[0] = lvol[0]*f;
+	for(i=0;i<9;i++) rptr[i] = &rbuf[0][0];
+	rptrs = 1;
+    }
+    else
+    {
+	rptrs = 0;
+	for(i=0;i<9;i++)
+	{
+	    if ((!i) || (lvol[i] != lvol[i-1]) || (rvol[i] != rvol[i-1]) ||
+		(lplc[i] != lplc[i-1]) || (rplc[i] != rplc[i-1]))
+	    {
+		nlvol[rptrs] = lvol[i]*f;
+		nrvol[rptrs] = rvol[i]*f;
+		nlplc[rptrs] = rend-min(max(lplc[i],0),FIFOSIZ);
+		nrplc[rptrs] = rend-min(max(rplc[i],0),FIFOSIZ);
+		rptrs++;
+	    }
+	    rptr[i] = &rbuf[rptrs-1][0];
+	}
+    }
+
+
+    //CPU time used to be somewhat less when emulator was only mono!
+    //   Because of no delay fifos!
+
+    for(ns=0;ns<numsamples;ns+=endsamples)
+    {
+	endsamples = min(FIFOSIZ*2-rend,FIFOSIZ);
+	endsamples = min(endsamples,numsamples-ns);
+
+	for(i=0;i<9;i++)
+	    nrptr[i] = &rptr[i][rend];
+	for(i=0;i<rptrs;i++)
+	    memset((void *)&rbuf[i][rend],0,endsamples*sizeof(float));
+
+	if (adlibreg[0xbd]&0x20)
+	{
+				//BassDrum (j=6)
+	    if (cell[15].cellfunc != docell4)
+	    {
+		if (adlibreg[0xc6]&1)
+		{
+		    for(i=0;i<endsamples;i++)
+		    {
+			(cell[15].cellfunc)((void *)&cell[15],0.0);
+			nrptr[6][i] += cell[15].val;
+		    }
+		}
+		else
+		{
+		    for(i=0;i<endsamples;i++)
+		    {
+			(cell[6].cellfunc)((void *)&cell[6],cell[6].val*cell[6].mfb);
+			(cell[15].cellfunc)((void *)&cell[15],cell[6].val*WAVPREC*MODFACTOR);
+			nrptr[6][i] += cell[15].val;
+		    }
+		}
+	    }
+
+				//Snare/Hihat (j=7), Cymbal/TomTom (j=8)
+	    if ((cell[7].cellfunc != docell4) || (cell[8].cellfunc != docell4) || (cell[16].cellfunc != docell4) || (cell[17].cellfunc != docell4))
+	    {
+		for(i=0;i<endsamples;i++)
+		{
+		    k = k*1664525+1013904223;
+		    (cell[16].cellfunc)((void *)&cell[16],k&((WAVPREC>>1)-1)); //Snare
+		    (cell[7].cellfunc)((void *)&cell[7],k&(WAVPREC-1));       //Hihat
+		    (cell[17].cellfunc)((void *)&cell[17],k&((WAVPREC>>3)-1)); //Cymbal
+		    (cell[8].cellfunc)((void *)&cell[8],0.0);                 //TomTom
+		    nrptr[7][i] += cell[7].val + cell[16].val;
+		    nrptr[8][i] += cell[8].val + cell[17].val;
+		}
+	    }
+	}
+	for(j=9-1;j>=0;j--)
+	{
+	    if ((adlibreg[0xbd]&0x20) && (j >= 6) && (j < 9)) continue;
+
+	    cptr = &cell[j]; k = j;
+	    if (adlibreg[0xc0+k]&1)
+	    {
+		if ((cptr[9].cellfunc == docell4) && (cptr->cellfunc == docell4)) continue;
+		for(i=0;i<endsamples;i++)
+		{
+		    (cptr->cellfunc)((void *)cptr,cptr->val*cptr->mfb);
+		    (cptr->cellfunc)((void *)&cptr[9],0);
+		    nrptr[j][i] += cptr[9].val + cptr->val;
+		}
+	    }
+	    else
+	    {
+		if (cptr[9].cellfunc == docell4) continue;
+		for(i=0;i<endsamples;i++)
+		{
+		    (cptr->cellfunc)((void *)cptr,cptr->val*cptr->mfb);
+		    (cptr[9].cellfunc)((void *)&cptr[9],cptr->val*WAVPREC*MODFACTOR);
+		    nrptr[j][i] += cptr[9].val;
+		}
+	    }
+	}
+
+	if (numspeakers == 1)
+	{
+	    if (bytespersample == 1)
+	    {
+		for(i=endsamples-1;i>=0;i--)
+		    clipit8(nrptr[0][i]*nlvol[0],sndptr+1);
+	    }
+	    else
+	    {
+		for(i=endsamples-1;i>=0;i--)
+		    clipit16(nrptr[0][i]*nlvol[0],sndptr2+i);
+	    }
+	}
+	else
+	{
+	    memset((void *)snd,0,endsamples*sizeof(float)*2);
+	    for(j=0;j<rptrs;j++)
+	    {
+		for(i=0;i<endsamples;i++)
+		{
+		    snd[(i<<1)  ] += rbuf[j][(nlplc[j]+i)&(FIFOSIZ*2-1)]*nlvol[j];
+		    snd[(i<<1)+1] += rbuf[j][(nrplc[j]+i)&(FIFOSIZ*2-1)]*nrvol[j];
+		}
+		nlplc[j] += endsamples;
+		nrplc[j] += endsamples;
+	    }
+
+	    if (bytespersample == 1)
+	    {
+		for(i=(endsamples<<1)-1;i>=0;i--)
+		    clipit8(snd[i],sndptr+i);
+	    }
+	    else
+	    {
+		for(i=(endsamples<<1)-1;i>=0;i--)
+		    clipit16(snd[i],sndptr2+i);
+	    }
+	}
+
+	sndptr = sndptr+(numspeakers*endsamples);
+	sndptr2 = sndptr2+(numspeakers*endsamples);
+	rend = ((rend+endsamples)&(FIFOSIZ*2-1));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/adlibemu.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,26 @@
+/*
+ * ADLIBEMU.H
+ * Copyright (C) 1998-2001 Ken Silverman
+ * Ken Silverman's official web site: "http://www.advsys.net/ken"
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+void adlibinit(long dasamplerate,long danumspeakers,long dabytespersample);
+void adlib0(long i,long v);
+void adlibgetsample(void *sndptr,long numbytes);
+void adlibsetvolume(int i);
+void randoinsts();
+extern float lvol[9],rvol[9],lplc[9],rplc[9];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/adplug.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,179 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2005 Simon Peter <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * adplug.cpp - CAdPlug utility class, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include <string>
+#include <binfile.h>
+
+#include "adplug.h"
+#include "debug.h"
+
+/***** Replayer includes *****/
+
+#include "hsc.h"
+#include "amd.h"
+#include "a2m.h"
+#include "imf.h"
+#include "sng.h"
+#include "adtrack.h"
+#include "bam.h"
+#include "d00.h"
+#include "dfm.h"
+#include "hsp.h"
+#include "ksm.h"
+#include "mad.h"
+#include "mid.h"
+#include "mkj.h"
+#include "cff.h"
+#include "dmo.h"
+#include "s3m.h"
+#include "dtm.h"
+#include "fmc.h"
+#include "mtk.h"
+#include "rad.h"
+#include "raw.h"
+#include "sa2.h"
+#include "bmf.h"
+#include "flash.h"
+#include "hybrid.h"
+#include "hyp.h"
+#include "psi.h"
+#include "rat.h"
+#include "lds.h"
+#include "u6m.h"
+#include "rol.h"
+#include "xsm.h"
+#include "dro.h"
+
+/***** Defines *****/
+
+#define VERSION		"1.5.1"		// AdPlug library version string
+
+/***** CAdPlug *****/
+
+// List of all players that come with the standard AdPlug distribution
+const CPlayerDesc CAdPlug::allplayers[] = {
+  CPlayerDesc(ChscPlayer::factory, "HSC-Tracker", ".hsc\0"),
+  CPlayerDesc(CsngPlayer::factory, "SNGPlay", ".sng\0"),
+  CPlayerDesc(CimfPlayer::factory, "Apogee IMF", ".imf\0.wlf\0.adlib\0"),
+  CPlayerDesc(Ca2mLoader::factory, "Adlib Tracker 2", ".a2m\0"),
+  CPlayerDesc(CadtrackLoader::factory, "Adlib Tracker", ".sng\0"),
+  CPlayerDesc(CamdLoader::factory, "AMUSIC", ".amd\0"),
+  CPlayerDesc(CbamPlayer::factory, "Bob's Adlib Music", ".bam\0"),
+  CPlayerDesc(Cd00Player::factory, "Packed EdLib", ".d00\0"),
+  CPlayerDesc(CdfmLoader::factory, "Digital-FM", ".dfm\0"),
+  CPlayerDesc(ChspLoader::factory, "HSC Packed", ".hsp\0"),
+  CPlayerDesc(CksmPlayer::factory, "Ken Silverman Music", ".ksm\0"),
+  CPlayerDesc(CmadLoader::factory, "Mlat Adlib Tracker", ".mad\0"),
+  CPlayerDesc(CmidPlayer::factory, "MIDI", ".mid\0.cmf\0.sci\0.laa\0"),
+  CPlayerDesc(CmkjPlayer::factory, "MKJamz", ".mkj\0"),
+  CPlayerDesc(CcffLoader::factory, "Boomtracker", ".cff\0"),
+  CPlayerDesc(CdmoLoader::factory, "TwinTeam", ".dmo\0"),
+  CPlayerDesc(Cs3mPlayer::factory, "Scream Tracker 3", ".s3m\0"),
+  CPlayerDesc(CdtmLoader::factory, "DeFy Adlib Tracker", ".dtm\0"),
+  CPlayerDesc(CfmcLoader::factory, "Faust Music Creator", ".sng\0"),
+  CPlayerDesc(CmtkLoader::factory, "MPU-401 Trakker", ".mtk\0"),
+  CPlayerDesc(CradLoader::factory, "Reality Adlib Tracker", ".rad\0"),
+  CPlayerDesc(CrawPlayer::factory, "RdosPlay RAW", ".raw\0"),
+  CPlayerDesc(Csa2Loader::factory, "Surprise! Adlib Tracker", ".sat\0.sa2\0"),
+  CPlayerDesc(CxadbmfPlayer::factory, "BMF Adlib Tracker", ".xad\0"),
+  CPlayerDesc(CxadflashPlayer::factory, "Flash", ".xad\0"),
+  CPlayerDesc(CxadhybridPlayer::factory, "Hybrid", ".xad\0"),
+  CPlayerDesc(CxadhypPlayer::factory, "Hypnosis", ".xad\0"),
+  CPlayerDesc(CxadpsiPlayer::factory, "PSI", ".xad\0"),
+  CPlayerDesc(CxadratPlayer::factory, "rat", ".xad\0"),
+  CPlayerDesc(CldsPlayer::factory, "LOUDNESS Sound System", ".lds\0"),
+  CPlayerDesc(Cu6mPlayer::factory, "Ultima 6 Music", ".m\0"),
+  CPlayerDesc(CrolPlayer::factory, "Adlib Visual Composer", ".rol\0"),
+  CPlayerDesc(CxsmPlayer::factory, "eXtra Simple Music", ".xsm\0"),
+  CPlayerDesc(CdroPlayer::factory, "DOSBox Raw OPL", ".dro\0"),
+  CPlayerDesc()
+};
+
+const CPlayers &CAdPlug::init_players(const CPlayerDesc pd[])
+{
+  static CPlayers	initplayers;
+  unsigned int		i;
+
+  for(i = 0; pd[i].factory; i++)
+    initplayers.push_back(&pd[i]);
+
+  return initplayers;
+}
+
+const CPlayers CAdPlug::players = CAdPlug::init_players(CAdPlug::allplayers);
+CAdPlugDatabase *CAdPlug::database = 0;
+
+CPlayer *CAdPlug::factory(const std::string &fn, Copl *opl, const CPlayers &pl,
+			  const CFileProvider &fp)
+{
+  CPlayer			*p;
+  CPlayers::const_iterator	i;
+  unsigned int			j;
+
+  AdPlug_LogWrite("*** CAdPlug::factory(\"%s\",opl,fp) ***\n", fn.c_str());
+
+  // Try a direct hit by file extension
+  for(i = pl.begin(); i != pl.end(); i++)
+    for(j = 0; (*i)->get_extension(j); j++)
+      if(fp.extension(fn, (*i)->get_extension(j))) {
+	AdPlug_LogWrite("Trying direct hit: %s\n", (*i)->filetype.c_str());
+	if((p = (*i)->factory(opl)))
+	  if(p->load(fn, fp)) {
+	    AdPlug_LogWrite("got it!\n");
+	    AdPlug_LogWrite("--- CAdPlug::factory ---\n");
+	    return p;
+	  } else
+	    delete p;
+      }
+
+  // Try all players, one by one
+  for(i = pl.begin(); i != pl.end(); i++) {
+    AdPlug_LogWrite("Trying: %s\n", (*i)->filetype.c_str());
+    if((p = (*i)->factory(opl)))
+      if(p->load(fn, fp)) {
+        AdPlug_LogWrite("got it!\n");
+        AdPlug_LogWrite("--- CAdPlug::factory ---\n");
+	return p;
+      } else
+	delete p;
+  }
+
+  // Unknown file
+  AdPlug_LogWrite("End of list!\n");
+  AdPlug_LogWrite("--- CAdPlug::factory ---\n");
+  return 0;
+}
+
+void CAdPlug::set_database(CAdPlugDatabase *db)
+{
+  database = db;
+}
+
+std::string CAdPlug::get_version()
+{
+  return std::string(VERSION);
+}
+
+void CAdPlug::debug_output(const std::string &filename)
+{
+  AdPlug_LogFile(filename.c_str());
+  AdPlug_LogWrite("CAdPlug::debug_output(\"%s\"): Redirected.\n",filename.c_str());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/adplug.dsp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,509 @@
+# Microsoft Developer Studio Project File - Name="adplug" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** NICHT BEARBEITEN **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=adplug - Win32 Debug
+!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE
+!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl
+!MESSAGE 
+!MESSAGE NMAKE /f "adplug.mak".
+!MESSAGE 
+!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben
+!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:
+!MESSAGE 
+!MESSAGE NMAKE /f "adplug.mak" CFG="adplug - Win32 Debug"
+!MESSAGE 
+!MESSAGE Für die Konfiguration stehen zur Auswahl:
+!MESSAGE 
+!MESSAGE "adplug - Win32 Release" (basierend auf  "Win32 (x86) Static Library")
+!MESSAGE "adplug - Win32 Debug" (basierend auf  "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "adplug - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Installing library and headers...
+PostBuild_Cmds=call vc6inst l "Release\adplug.lib"	call vc6inst i *.h adplug
+# End Special Build Tool
+
+!ELSEIF  "$(CFG)" == "adplug - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x407 /d "_DEBUG"
+# ADD RSC /l 0x407 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"Debug\adplugd.lib"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Installing library and headers...
+PostBuild_Cmds=call vc6inst l "Debug\adplugd.lib"	call vc6inst i *.h adplug
+# End Special Build Tool
+
+!ENDIF 
+
+# Begin Target
+
+# Name "adplug - Win32 Release"
+# Name "adplug - Win32 Debug"
+# Begin Group "Quellcodedateien"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\a2m.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\adlibemu.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\adplug.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\adtrack.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\amd.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\analopl.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\bam.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\bmf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\cff.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\d00.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\database.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\debug.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dfm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\diskopl.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\dmo.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\dro.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\dtm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\emuopl.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\flash.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\fmc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\fmopl.c
+# ADD CPP /W1
+# End Source File
+# Begin Source File
+
+SOURCE=.\fprovide.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\hsc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\hsp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\hybrid.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\hyp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\imf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ksm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\lds.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\mad.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\mid.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\mkj.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\mtk.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\player.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\players.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\protrack.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\psi.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\rad.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\rat.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\raw.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\realopl.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\rol.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\s3m.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sa2.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sng.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\u6m.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\xad.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\xsm.cpp
+# End Source File
+# End Group
+# Begin Group "Header-Dateien"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\a2m.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\adlibemu.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\adplug.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\adtrack.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\amd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\analopl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\bam.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\bmf.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\cff.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\d00.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\database.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\debug.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\dfm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\diskopl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\dmo.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\dro.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\dtm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\emuopl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\flash.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\fmc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\fmopl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\fprovide.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\hsc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\hsp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\hybrid.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\hyp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\imf.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\imfcrc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\kemuopl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ksm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\lds.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\mad.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\mid.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\mididata.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\mkj.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\mtk.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\opl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\player.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\players.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\protrack.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\psi.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\rad.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\rat.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\raw.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\realopl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\rol.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\s3m.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sa2.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\silentopl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sng.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\u6m.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xad.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xsm.h
+# End Source File
+# End Group
+# End Target
+# End Project
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/adplug.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,55 @@
+/*
+ * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * adplug.h - AdPlug main header file, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#ifndef H_ADPLUG_ADPLUG
+#define H_ADPLUG_ADPLUG
+
+#include <string>
+
+#include "player.h"
+#include "opl.h"
+#include "fprovide.h"
+#include "players.h"
+#include "database.h"
+
+class CAdPlug
+{
+  friend CPlayer::CPlayer(Copl *newopl);
+
+public:
+  static const CPlayers players;
+
+  static CPlayer *factory(const std::string &fn, Copl *opl,
+			  const CPlayers &pl = players,
+			  const CFileProvider &fp = CProvider_Filesystem());
+
+  static void set_database(CAdPlugDatabase *db);
+  static std::string get_version();
+  static void debug_output(const std::string &filename);
+
+private:
+  static CAdPlugDatabase *database;
+  static const CPlayerDesc allplayers[];
+
+  static const CPlayers &init_players(const CPlayerDesc pd[]);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/adtrack.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,176 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * adtrack.cpp - Adlib Tracker 1.0 Loader by Simon Peter <dn.tlp@gmx.net>
+ *
+ * NOTES:
+ * The original Adlib Tracker 1.0 is behaving a little different from the
+ * official spec: The 'octave' integer from the instrument file is stored
+ * "minus 1" from the actual value, underflowing from 0 to 0xffff.
+ *
+ * I also noticed that my player is playing everything transposed a few tones
+ * higher than the original tracker. As far as i can see, my player perfectly
+ * follows the official spec, so it "must" be the tracker that does something
+ * wrong here...
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "adtrack.h"
+#include "debug.h"
+
+/*** Public methods ***/
+
+CPlayer *CadtrackLoader::factory(Copl *newopl)
+{
+  return new CadtrackLoader(newopl);
+}
+
+bool CadtrackLoader::load(const std::string &filename, const CFileProvider &fp)
+{
+  binistream *f = fp.open(filename); if(!f) return false;
+  binistream *instf;
+  char note[2];
+  unsigned short rwp;
+  unsigned char chp, octave, pnote = 0;
+  int i,j;
+  AdTrackInst myinst;
+
+  // file validation
+  if(!fp.extension(filename, ".sng") || fp.filesize(f) != 36000)
+    { fp.close(f); return false; }
+
+  // check for instruments file
+  std::string instfilename(filename, 0, filename.find_last_of('.'));
+  instfilename += ".ins";
+  AdPlug_LogWrite("CadtrackLoader::load(,\"%s\"): Checking for \"%s\"...\n",
+		  filename.c_str(), instfilename.c_str());
+  instf = fp.open(instfilename);
+  if(!instf || fp.filesize(instf) != 468) { fp.close(f); return false; }
+
+  // give CmodPlayer a hint on what we're up to
+  realloc_patterns(1,1000,9); realloc_instruments(9); realloc_order(1);
+  init_trackord(); flags = NoKeyOn;
+  (*order) = 0; length = 1; restartpos = 0; bpm = 120; initspeed = 3;
+
+  // load instruments from instruments file
+  for(i=0;i<9;i++) {
+    for(j=0;j<2;j++) {
+      myinst.op[j].appampmod = instf->readInt(2);
+      myinst.op[j].appvib = instf->readInt(2);
+      myinst.op[j].maintsuslvl = instf->readInt(2);
+      myinst.op[j].keybscale = instf->readInt(2);
+      myinst.op[j].octave = instf->readInt(2);
+      myinst.op[j].freqrisevollvldn = instf->readInt(2);
+      myinst.op[j].softness = instf->readInt(2);
+      myinst.op[j].attack = instf->readInt(2);
+      myinst.op[j].decay = instf->readInt(2);
+      myinst.op[j].release = instf->readInt(2);
+      myinst.op[j].sustain = instf->readInt(2);
+      myinst.op[j].feedback = instf->readInt(2);
+      myinst.op[j].waveform = instf->readInt(2);
+    }
+    convert_instrument(i, &myinst);
+  }
+  fp.close(instf);
+
+  // load file
+  for(rwp=0;rwp<1000;rwp++)
+    for(chp=0;chp<9;chp++) {
+      // read next record
+      f->readString(note, 2); octave = f->readInt(1); f->ignore();
+      switch(*note) {
+      case 'C': if(note[1] == '#') pnote = 2; else pnote = 1; break;
+      case 'D': if(note[1] == '#') pnote = 4; else pnote = 3; break;
+      case 'E': pnote = 5; break;
+      case 'F': if(note[1] == '#') pnote = 7; else pnote = 6; break;
+      case 'G': if(note[1] == '#') pnote = 9; else pnote = 8; break;
+      case 'A': if(note[1] == '#') pnote = 11; else pnote = 10; break;
+      case 'B': pnote = 12; break;
+      case '\0':
+	if(note[1] == '\0')
+	  tracks[chp][rwp].note = 127;
+	else {
+	  fp.close(f);
+	  return false;
+	}
+	break;
+      default: fp.close(f); return false;
+      }
+      if((*note) != '\0') {
+	tracks[chp][rwp].note = pnote + (octave * 12);
+	tracks[chp][rwp].inst = chp + 1;
+      }
+    }
+
+  fp.close(f);
+  rewind(0);
+  return true;
+}
+
+float CadtrackLoader::getrefresh()
+{
+  return 18.2f;
+}
+
+/*** Private methods ***/
+
+void CadtrackLoader::convert_instrument(unsigned int n, AdTrackInst *i)
+{
+  // Carrier "Amp Mod / Vib / Env Type / KSR / Multiple" register
+  inst[n].data[2] = i->op[Carrier].appampmod ? 1 << 7 : 0;
+  inst[n].data[2] += i->op[Carrier].appvib ? 1 << 6 : 0;
+  inst[n].data[2] += i->op[Carrier].maintsuslvl ? 1 << 5 : 0;
+  inst[n].data[2] += i->op[Carrier].keybscale ? 1 << 4 : 0;
+  inst[n].data[2] += (i->op[Carrier].octave + 1) & 0xffff; // Bug in original tracker
+  // Modulator...
+  inst[n].data[1] = i->op[Modulator].appampmod ? 1 << 7 : 0;
+  inst[n].data[1] += i->op[Modulator].appvib ? 1 << 6 : 0;
+  inst[n].data[1] += i->op[Modulator].maintsuslvl ? 1 << 5 : 0;
+  inst[n].data[1] += i->op[Modulator].keybscale ? 1 << 4 : 0;
+  inst[n].data[1] += (i->op[Modulator].octave + 1) & 0xffff; // Bug in original tracker
+
+  // Carrier "Key Scaling / Level" register
+  inst[n].data[10] = (i->op[Carrier].freqrisevollvldn & 3) << 6;
+  inst[n].data[10] += i->op[Carrier].softness & 63;
+  // Modulator...
+  inst[n].data[9] = (i->op[Modulator].freqrisevollvldn & 3) << 6;
+  inst[n].data[9] += i->op[Modulator].softness & 63;
+
+  // Carrier "Attack / Decay" register
+  inst[n].data[4] = (i->op[Carrier].attack & 0x0f) << 4;
+  inst[n].data[4] += i->op[Carrier].decay & 0x0f;
+  // Modulator...
+  inst[n].data[3] = (i->op[Modulator].attack & 0x0f) << 4;
+  inst[n].data[3] += i->op[Modulator].decay & 0x0f;
+
+  // Carrier "Release / Sustain" register
+  inst[n].data[6] = (i->op[Carrier].release & 0x0f) << 4;
+  inst[n].data[6] += i->op[Carrier].sustain & 0x0f;
+  // Modulator...
+  inst[n].data[5] = (i->op[Modulator].release & 0x0f) << 4;
+  inst[n].data[5] += i->op[Modulator].sustain & 0x0f;
+
+  // Channel "Feedback / Connection" register
+  inst[n].data[0] = (i->op[Carrier].feedback & 7) << 1;
+
+  // Carrier/Modulator "Wave Select" registers
+  inst[n].data[8] = i->op[Carrier].waveform & 3;
+  inst[n].data[7] = i->op[Modulator].waveform & 3;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/adtrack.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,53 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * adtrack.h - Adlib Tracker 1.0 Loader by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "protrack.h"
+
+class CadtrackLoader: public CmodPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	CadtrackLoader(Copl *newopl)
+		: CmodPlayer(newopl)
+	{ };
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+	float getrefresh();
+
+	std::string gettype()
+	{ return std::string("Adlib Tracker 1.0"); };
+	unsigned int getinstruments()
+	{ return 9; };
+
+private:
+        enum Operators {Carrier = 1, Modulator = 0};
+
+	typedef struct {
+	  struct {
+	    unsigned short appampmod, appvib, maintsuslvl, keybscale, octave,
+	      freqrisevollvldn, softness, attack, decay, release, sustain,
+	      feedback, waveform;
+	  } op[2];
+	} AdTrackInst;
+
+	void convert_instrument(unsigned int n, AdTrackInst *i);
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/amd.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,173 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * amd.cpp - AMD Loader by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include <string.h>
+
+#include "amd.h"
+#include "debug.h"
+
+CPlayer *CamdLoader::factory(Copl *newopl)
+{
+  return new CamdLoader(newopl);
+}
+
+bool CamdLoader::load(const std::string &filename, const CFileProvider &fp)
+{
+        binistream *f = fp.open(filename); if(!f) return false;
+	struct {
+		char id[9];
+		unsigned char version;
+	} header;
+	int i, j, k, t, numtrax;
+	unsigned char buf, buf2, buf3;
+	const unsigned char convfx[10] = {0,1,2,9,17,11,13,18,3,14};
+
+	// file validation section
+	if(fp.filesize(f) < 1072) { fp.close(f); return false; }
+	f->seek(1062); f->readString(header.id, 9);
+	header.version = f->readInt(1);
+	if(strncmp(header.id, "<o\xefQU\xeeRoR", 9) &&
+	   strncmp(header.id, "MaDoKaN96", 9)) { fp.close(f); return false; }
+
+	// load section
+	memset(inst, 0, sizeof(inst));
+	f->seek(0);
+	f->readString(songname, sizeof(songname));
+	f->readString(author, sizeof(author));
+	for(i = 0; i < 26; i++) {
+		f->readString(instname[i], 23);
+		for(j = 0; j < 11; j++) inst[i].data[j] = f->readInt(1);
+	}
+	length = f->readInt(1); nop = f->readInt(1) + 1;
+	for(i=0;i<128;i++) order[i] = f->readInt(1);
+	f->seek(10, binio::Add);
+	if(header.version == 0x10) {	// unpacked module
+		for(i=0;i<64*9;i++)
+			trackord[i/9][i%9] = i+1;
+		t = 0;
+		while(!f->ateof()) {
+			for(j=0;j<64;j++)
+				for(i=t;i<t+9;i++) {
+					buf = f->readInt(1);
+					tracks[i][j].param2 = (buf&127) % 10;
+					tracks[i][j].param1 = (buf&127) / 10;
+					buf = f->readInt(1);
+					tracks[i][j].inst = buf >> 4;
+					tracks[i][j].command = buf & 0x0f;
+					buf = f->readInt(1);
+					if(buf >> 4)	// fix bug in AMD save routine
+						tracks[i][j].note = ((buf & 14) >> 1) * 12 + (buf >> 4);
+					else
+						tracks[i][j].note = 0;
+					tracks[i][j].inst += (buf & 1) << 4;
+				}
+			t += 9;
+		}
+	} else {						// packed module
+		for(i=0;i<nop;i++)
+		  for(j=0;j<9;j++)
+		    trackord[i][j] = f->readInt(2) + 1;
+		numtrax = f->readInt(2);
+		for(k=0;k<numtrax;k++) {
+			i = f->readInt(2);
+			if(i > 575) i = 575;	// fix corrupted modules
+			j = 0;
+			do {
+				buf = f->readInt(1);
+				if(buf & 128) {
+					for(t = j; t < j + (buf & 127) && t < 64; t++) {
+						tracks[i][t].command = 0;
+						tracks[i][t].inst = 0;
+						tracks[i][t].note = 0;
+						tracks[i][t].param1 = 0;
+						tracks[i][t].param2 = 0;
+					}
+					j += buf & 127;
+					continue;
+				}
+				tracks[i][j].param2 = buf % 10;
+				tracks[i][j].param1 = buf / 10;
+				buf = f->readInt(1);
+				tracks[i][j].inst = buf >> 4;
+				tracks[i][j].command = buf & 0x0f;
+				buf = f->readInt(1);
+				if(buf >> 4)	// fix bug in AMD save routine
+					tracks[i][j].note = ((buf & 14) >> 1) * 12 + (buf >> 4);
+				else
+					tracks[i][j].note = 0;
+				tracks[i][j].inst += (buf & 1) << 4;
+				j++;
+			} while(j<64);
+		}
+	}
+	fp.close(f);
+
+	// convert to protracker replay data
+	bpm = 50; restartpos = 0; activechan = 0xffff; flags = Decimal;
+	for(i=0;i<26;i++) {	// convert instruments
+		buf = inst[i].data[0];
+		buf2 = inst[i].data[1];
+		inst[i].data[0] = inst[i].data[10];
+		inst[i].data[1] = buf;
+		buf = inst[i].data[2];
+		inst[i].data[2] = inst[i].data[5];
+		buf3 = inst[i].data[3];
+		inst[i].data[3] = buf;
+		buf = inst[i].data[4];
+		inst[i].data[4] = inst[i].data[7];
+		inst[i].data[5] = buf3;
+		buf3 = inst[i].data[6];
+		inst[i].data[6] = inst[i].data[8];
+		inst[i].data[7] = buf;
+		inst[i].data[8] = inst[i].data[9];
+		inst[i].data[9] = buf2;
+		inst[i].data[10] = buf3;
+		for(j=0;j<23;j++)	// convert names
+			if(instname[i][j] == '\xff')
+				instname[i][j] = '\x20';
+	}
+	for(i=0;i<nop*9;i++)	// convert patterns
+		for(j=0;j<64;j++) {
+			tracks[i][j].command = convfx[tracks[i][j].command];
+			if(tracks[i][j].command == 14) {
+				if(tracks[i][j].param1 == 2) {
+					tracks[i][j].command = 10;
+					tracks[i][j].param1 = tracks[i][j].param2;
+					tracks[i][j].param2 = 0;
+				}
+				if(tracks[i][j].param1 == 3) {
+					tracks[i][j].command = 10;
+					tracks[i][j].param1 = 0;
+				}
+			}
+		}
+
+	rewind(0);
+	return true;
+}
+
+float CamdLoader::getrefresh()
+{
+	if(tempo)
+		return (float) (tempo);
+	else
+		return 18.2f;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/amd.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,49 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * amd.h - AMD Loader by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "protrack.h"
+
+class CamdLoader: public CmodPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	CamdLoader(Copl *newopl)
+		: CmodPlayer(newopl)
+	{ };
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+	float getrefresh();
+
+	std::string gettype()
+	{ return std::string("AMUSIC Adlib Tracker"); };
+	std::string gettitle()
+	{ return std::string(songname,0,24); };
+	std::string getauthor()
+	{ return std::string(author,0,24); };
+	unsigned int getinstruments()
+	{ return 26; };
+	std::string getinstrument(unsigned int n)
+	{ return std::string(instname[n],0,23); };
+
+private:
+	char songname[24],author[24],instname[26][23];
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/analopl.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,167 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999, 2000, 2001 Simon Peter, <dn.tlp@gmx.net>, et al.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * analopl.cpp - Spectrum analyzing hardware OPL, by Simon Peter (dn.tlp@gmx.net)
+ */
+
+#include <conio.h>
+#include "analopl.h"
+
+#ifdef _MSC_VER
+	#define INP		_inp
+	#define OUTP	_outp
+#elif defined(__WATCOMC__)
+	#define INP		inp
+	#define OUTP	outp
+#endif
+
+#define SHORTDELAY		6					// short delay in I/O port-reads after OPL hardware output
+#define LONGDELAY		35					// long delay in I/O port-reads after OPL hardware output
+
+// the 9 operators as expected by the OPL2
+static const unsigned char op_table[9] = {0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12};
+
+CAnalopl::CAnalopl(unsigned short initport): adlport(initport), hardvol(0), bequiet(false), nowrite(false)
+{
+	int i;
+
+	for(i=0;i<22;i++) {
+		hardvols[i][0] = 0;
+		hardvols[i][1] = 0;
+	}
+	for(i=0;i<9;i++) {
+		keyregs[i][0] = 0;
+		keyregs[i][1] = 0;
+	}
+}
+
+bool CAnalopl::detect()
+{
+	unsigned char stat1,stat2,i;
+
+	hardwrite(4,0x60); hardwrite(4,0x80);
+	stat1 = INP(adlport);
+	hardwrite(2,0xff); hardwrite(4,0x21);
+	for(i=0;i<80;i++)			// wait for adlib
+		INP(adlport);
+	stat2 = INP(adlport);
+	hardwrite(4,0x60); hardwrite(4,0x80);
+
+	if(((stat1 & 0xe0) == 0) && ((stat2 & 0xe0) == 0xc0))
+		return true;
+	else
+		return false;
+}
+
+void CAnalopl::setvolume(int volume)
+{
+	int i;
+
+	hardvol = volume;
+	for(i=0;i<9;i++) {
+		hardwrite(0x43+op_table[i],((hardvols[op_table[i]+3][0] & 63) + volume) > 63 ? 63 : hardvols[op_table[i]+3][0] + volume);
+		if(hardvols[i][1] & 1)	// modulator too?
+			hardwrite(0x40+op_table[i],((hardvols[op_table[i]][0] & 63) + volume) > 63 ? 63 : hardvols[op_table[i]][0] + volume);
+	}
+}
+
+void CAnalopl::setquiet(bool quiet)
+{
+	bequiet = quiet;
+
+	if(quiet) {
+		oldvol = hardvol;
+		setvolume(63);
+	} else
+		setvolume(oldvol);
+}
+
+void CAnalopl::hardwrite(int reg, int val)
+{
+	int i;
+
+	OUTP(adlport,reg);							// set register
+	for(i=0;i<SHORTDELAY;i++)					// wait for adlib
+		INP(adlport);
+	OUTP(adlport+1,val);						// set value
+	for(i=0;i<LONGDELAY;i++)					// wait for adlib
+		INP(adlport);
+}
+
+void CAnalopl::write(int reg, int val)
+{
+	int i;
+
+	if(nowrite)
+		return;
+
+	if(reg >= 0xb0 && reg <= 0xb8) {
+		if(!keyregs[reg - 0xb0][0] && (val & 32))
+			keyregs[reg - 0xb0][1] = 1;
+		else
+			keyregs[reg - 0xb0][1] = 0;
+		keyregs[reg - 0xb0][0] = val & 32;
+		if(bequiet)	// filter all key-on commands
+			val &= ~32;
+	}
+	if(reg >= 0x40 && reg <= 0x55)				// cache volumes
+		hardvols[reg-0x40][0] = val;
+	if(reg >= 0xc0 && reg <= 0xc8)
+		hardvols[reg-0xc0][1] = val;
+	if(hardvol)									// reduce volume
+		for(i=0;i<9;i++) {
+			if(reg == 0x43 + op_table[i])
+				val = ((val & 63) + hardvol) > 63 ? 63 : val + hardvol;
+			else
+				if((reg == 0x40 + op_table[i]) && (hardvols[i][1] & 1))
+					val = ((val & 63) + hardvol) > 63 ? 63 : val + hardvol;
+		}
+
+	hardwrite(reg,val);
+}
+
+void CAnalopl::init()
+{
+	int i;
+
+	for (i=0;i<9;i++) {				// stop instruments
+		hardwrite(0xb0 + i,0);				// key off
+		hardwrite(0x80 + op_table[i],0xff);	// fastest release
+	}
+	hardwrite(0xbd,0);	// clear misc. register
+}
+
+int CAnalopl::getcarriervol(unsigned int v)
+{
+	return (hardvols[op_table[v]+3][0] & 63);
+}
+
+int CAnalopl::getmodulatorvol(unsigned int v)
+{
+	return (hardvols[op_table[v]][0] & 63);
+}
+
+bool CAnalopl::getkeyon(unsigned int v)
+{
+	if(keyregs[v][1]) {
+		keyregs[v][1] = 0;
+		return true;
+	} else
+		return false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/analopl.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,64 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999, 2000, 2001 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * analopl.h - Spectrum analyzing hardware OPL, by Simon Peter (dn.tlp@gmx.net)
+ */
+
+#ifndef H_ANALOPL_DEFINED
+#define H_ANALOPL_DEFINED
+
+#include "opl.h"
+
+#define DFL_ADLIBPORT	0x388		// default adlib baseport
+
+class CAnalopl: public Copl
+{
+public:
+	CAnalopl(unsigned short initport = DFL_ADLIBPORT);	// initport = OPL2 hardware baseport
+
+	bool detect();						// returns true if adlib compatible board is found, else false
+	void setvolume(int volume);			// set adlib master volume (0 - 63) 0 = loudest, 63 = softest
+	void setquiet(bool quiet = true);	// sets the OPL2 quiet, while still writing to the registers
+	void setport(unsigned short port)	// set new OPL2 hardware baseport
+	{ adlport = port; };
+	void setnowrite(bool nw = true)		// set hardware write status
+	{ nowrite = nw; };
+
+	int getvolume()						// get adlib master volume
+	{ return hardvol; };
+	int getcarriervol(unsigned int v);			// get carrier volume of adlib voice v
+	int getmodulatorvol(unsigned int v);		// get modulator volume of adlib voice v
+	bool getkeyon(unsigned int v);
+
+	// template methods
+	void write(int reg, int val);
+	void init();
+
+private:
+	void hardwrite(int reg, int val);	// write to OPL2 hardware registers
+
+	unsigned short	adlport;			// adlib hardware baseport
+	int				hardvol,oldvol;		// hardware master volume
+	bool			bequiet;			// quiet status cache
+	char			hardvols[22][2];	// volume cache
+	unsigned char	keyregs[9][2];			// shadow key register
+	bool			nowrite;			// don't write to hardware, if true
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/bam.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,203 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * bam.cpp - Bob's Adlib Music Player, by Simon Peter <dn.tlp@gmx.net>
+ *
+ * NOTES:
+ * In my player, the loop counter is stored with the label. This can be
+ * dangerous for some situations (see below), but there shouldn't be any BAM
+ * files triggering this situation.
+ *
+ * From SourceForge Bug #476088:
+ * -----------------------------
+ * Using just one loop counter for each label, my player can't
+ * handle files that loop twice to the same label (if that's at
+ * all possible with BAM). Imagine the following situation:
+ * 
+ * ... [*] ---- [<- *] ---- [<- *] ...
+ *  ^   ^    ^     ^     ^     ^    ^
+ *  |   |    |     |     |     |    |
+ *  +---|----+-----|-----+-----|----+--- normal song data
+ *      +----------|-----------|-------- label 1
+ *                 +-----------+-------- loop points to label 1
+ * 
+ * both loop points loop to the same label. Storing the loop 
+ * count with the label would cause chaos with the counter, 
+ * when the player executes the inner jump.
+ * ------------------
+ * Not to worry. my reference implementation of BAM does not
+ * support the multiple loop situation you describe, and
+ * neither do any BAM-creation programs. Then both loops point
+ * to the same label, the inner loop's counter is just allowed
+ * to clobber the outer loop's counter. No stack is neccisary.
+ */
+
+#include <string.h>
+#include "bam.h"
+
+const unsigned short CbamPlayer::freq[] = {172,182,193,205,217,230,243,258,274,
+290,307,326,345,365,387,410,435,460,489,517,547,580,614,651,1369,1389,1411,
+1434,1459,1484,1513,1541,1571,1604,1638,1675,2393,2413,2435,2458,2483,2508,
+2537,2565,2595,2628,2662,2699,3417,3437,3459,3482,3507,3532,3561,3589,3619,
+3652,3686,3723,4441,4461,4483,4506,4531,4556,4585,4613,4643,4676,4710,4747,
+5465,5485,5507,5530,5555,5580,5609,5637,5667,5700,5734,5771,6489,6509,6531,
+6554,6579,6604,6633,6661,6691,6724,6758,6795,7513,7533,7555,7578,7603,7628,
+7657,7685,7715,7748,7782,7819,7858,7898,7942,7988,8037,8089,8143,8191,8191,
+8191,8191,8191,8191,8191,8191,8191,8191,8191,8191};
+
+CPlayer *CbamPlayer::factory(Copl *newopl)
+{
+  return new CbamPlayer(newopl);
+}
+
+bool CbamPlayer::load(const std::string &filename, const CFileProvider &fp)
+{
+        binistream *f = fp.open(filename); if(!f) return false;
+	char id[4];
+	unsigned int i;
+
+	size = fp.filesize(f) - 4;	// filesize minus header
+	f->readString(id, 4);
+	if(strncmp(id,"CBMF",4)) { fp.close(f); return false; }
+
+	song = new unsigned char [size];
+	for(i = 0; i < size; i++) song[i] = f->readInt(1);
+
+	fp.close(f);
+	rewind(0);
+	return true;
+}
+
+bool CbamPlayer::update()
+{
+	unsigned char	cmd,c;
+
+	if(del) {
+		del--;
+		return !songend;
+	}
+
+	if(pos >= size) {	// EOF detection
+		pos = 0;
+		songend = true;
+	}
+
+	while(song[pos] < 128) {
+		cmd = song[pos] & 240;
+		c = song[pos] & 15;
+		switch(cmd) {
+		case 0:		// stop song
+			pos = 0;
+			songend = true;
+			break;
+		case 16:	// start note
+			if(c < 9) {
+				opl->write(0xa0 + c, freq[song[++pos]] & 255);
+				opl->write(0xb0 + c, (freq[song[pos]] >> 8) + 32);
+			} else
+				pos++;
+			pos++;
+			break;
+		case 32:	// stop note
+			if(c < 9)
+				opl->write(0xb0 + c, 0);
+			pos++;
+			break;
+		case 48:	// define instrument
+			if(c < 9) {
+				opl->write(0x20 + op_table[c],song[pos+1]);
+				opl->write(0x23 + op_table[c],song[pos+2]);
+				opl->write(0x40 + op_table[c],song[pos+3]);
+				opl->write(0x43 + op_table[c],song[pos+4]);
+				opl->write(0x60 + op_table[c],song[pos+5]);
+				opl->write(0x63 + op_table[c],song[pos+6]);
+				opl->write(0x80 + op_table[c],song[pos+7]);
+				opl->write(0x83 + op_table[c],song[pos+8]);
+				opl->write(0xe0 + op_table[c],song[pos+9]);
+				opl->write(0xe3 + op_table[c],song[pos+10]);
+				opl->write(0xc0 + c,song[pos+11]);
+			}
+			pos += 12;
+			break;
+		case 80:	// set label
+			label[c].target = ++pos;
+			label[c].defined = true;
+			break;
+		case 96:	// jump
+			if(label[c].defined)
+				switch(song[pos+1]) {
+				case 254:	// infinite loop
+					if(label[c].defined) {
+						pos = label[c].target;
+						songend = true;
+						break;
+					}
+					// fall through...
+				case 255:	// chorus
+					if(!chorus && label[c].defined) {
+						chorus = true;
+						gosub = pos + 2;
+						pos = label[c].target;
+						break;
+					}
+					// fall through...
+				case 0:		// end of loop
+					pos += 2;
+					break;
+				default:	// finite loop
+					if(!label[c].count) {	// loop elapsed
+						label[c].count = 255;
+						pos += 2;
+						break;
+					}
+					if(label[c].count < 255)	// loop defined
+						label[c].count--;
+					else						// loop undefined
+						label[c].count = song[pos+1] - 1;
+					pos = label[c].target;
+					break;
+				}
+			break;
+		case 112:	// end of chorus
+			if(chorus) {
+				pos = gosub;
+				chorus = false;
+			} else
+				pos++;
+			break;
+		default:	// reserved command (skip)
+			pos++;
+			break;
+		}
+	}
+	if(song[pos] >= 128) {		// wait
+		del = song[pos] - 127;
+		pos++;
+	}
+	return !songend;
+}
+
+void CbamPlayer::rewind(int subsong)
+{
+        int i;
+
+	pos = 0; songend = false; del = 0; gosub = 0; chorus = false;
+	memset(label, 0, sizeof(label)); label[0].defined = true;
+	for(i = 0; i < 16; i++) label[i].count = 255;	// 255 = undefined
+	opl->init(); opl->write(1,32);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/bam.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,56 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * bam.h - Bob's Adlib Music Player, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "player.h"
+
+class CbamPlayer: public CPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	CbamPlayer(Copl *newopl)
+		: CPlayer(newopl), song(0)
+	{ };
+	~CbamPlayer()
+	{ if(song) delete [] song; };
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+	bool update();
+	void rewind(int subsong);
+	float getrefresh()
+	{ return 25.0f; };
+
+	std::string gettype()
+	{ return std::string("Bob's Adlib Music"); };
+
+private:
+	static const unsigned short freq[];
+
+	unsigned char	*song, del;
+	unsigned long	pos, size, gosub;
+	bool		songend, chorus;
+
+	struct {
+		unsigned long	target;
+		bool		defined;
+		unsigned char	count;
+	} label[16];
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/bmf.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,594 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * [xad] BMF player, by Riven the Mage <riven@ok.ru>
+ */
+
+/*
+    - discovery -
+
+  file(s) : GAMESNET.COM
+     type : GamesNet advertising intro
+     tune : by (?)The Brain [Razor 1911]
+   player : ver.0.9b by Hammer
+
+  file(s) : 2FAST4U.COM
+     type : Ford Knox BBStro
+     tune : by The Brain [Razor 1911]
+   player : ver.1.1 by ?
+  comment : in original player at 9th channel the feedback adlib register is not C8 but C6.
+
+  file(s) : DATURA.COM
+     type : Datura BBStro
+     tune : by The Brain [Razor 1911]
+   player : ver.1.2 by ?
+  comment : inaccurate replaying, because constant outport; in original player it can be 380 or 382.
+*/
+
+#include "bmf.h"
+#include "debug.h"
+
+const unsigned char CxadbmfPlayer::bmf_adlib_registers[117] =
+{
+  0x20, 0x23, 0x40, 0x43, 0x60, 0x63, 0x80, 0x83, 0xA0, 0xB0, 0xC0, 0xE0, 0xE3,
+  0x21, 0x24, 0x41, 0x44, 0x61, 0x64, 0x81, 0x84, 0xA1, 0xB1, 0xC1, 0xE1, 0xE4,
+  0x22, 0x25, 0x42, 0x45, 0x62, 0x65, 0x82, 0x85, 0xA2, 0xB2, 0xC2, 0xE2, 0xE5,
+  0x28, 0x2B, 0x48, 0x4B, 0x68, 0x6B, 0x88, 0x8B, 0xA3, 0xB3, 0xC3, 0xE8, 0xEB,
+  0x29, 0x2C, 0x49, 0x4C, 0x69, 0x6C, 0x89, 0x8C, 0xA4, 0xB4, 0xC4, 0xE9, 0xEC,
+  0x2A, 0x2D, 0x4A, 0x4D, 0x6A, 0x6D, 0x8A, 0x8D, 0xA5, 0xB5, 0xC5, 0xEA, 0xED,
+  0x30, 0x33, 0x50, 0x53, 0x70, 0x73, 0x90, 0x93, 0xA6, 0xB6, 0xC6, 0xF0, 0xF3,
+  0x31, 0x34, 0x51, 0x54, 0x71, 0x74, 0x91, 0x94, 0xA7, 0xB7, 0xC7, 0xF1, 0xF4,
+  0x32, 0x35, 0x52, 0x55, 0x72, 0x75, 0x92, 0x95, 0xA8, 0xB8, 0xC8, 0xF2, 0xF5
+};
+
+const unsigned short CxadbmfPlayer::bmf_notes[12] =
+{
+  0x157, 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287
+};
+
+/* for 1.1 */
+const unsigned short CxadbmfPlayer::bmf_notes_2[12] =
+{
+  0x159, 0x16D, 0x183, 0x19A, 0x1B2, 0x1CC, 0x1E8, 0x205, 0x223, 0x244, 0x267, 0x28B
+};
+
+const unsigned char CxadbmfPlayer::bmf_default_instrument[13] =
+{
+  0x01, 0x01, 0x3F, 0x3F, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+CPlayer *CxadbmfPlayer::factory(Copl *newopl)
+{
+  return new CxadbmfPlayer(newopl);
+}
+
+bool CxadbmfPlayer::xadplayer_load()
+{
+  unsigned short ptr = 0;
+  int i;
+
+  if(xad.fmt != BMF)
+    return false;
+
+#ifdef DEBUG
+  AdPlug_LogWrite("\nbmf_load():\n\n");
+#endif
+  if (!strncmp((char *)&tune[0],"BMF1.2",6))
+  {
+    bmf.version = BMF1_2;
+    bmf.timer = 70.0f;
+  }
+  else if (!strncmp((char *)&tune[0],"BMF1.1",6))
+  {
+    bmf.version = BMF1_1;
+    bmf.timer = 60.0f;
+  }
+  else
+  {
+    bmf.version = BMF0_9B;
+    bmf.timer = 18.2f;
+  }
+
+  // copy title & author
+  if (bmf.version > BMF0_9B)
+  {
+    ptr = 6;
+
+    strncpy(bmf.title,(char *)&tune[ptr],36);
+
+    while (tune[ptr]) { ptr++; }
+	ptr++;
+
+    strncpy(bmf.author,(char *)&tune[ptr],36);
+
+    while (tune[ptr]) { ptr++; }
+	ptr++;
+  }
+  else
+  {
+    strncpy(bmf.title,xad.title,36);
+    strncpy(bmf.author,xad.author,36);
+  }
+
+  // speed
+  if (bmf.version > BMF0_9B)
+    bmf.speed = tune[ptr++];
+  else
+    bmf.speed = ((tune[ptr++] << 8) / 3) >> 8; // strange, yeh ?
+
+  // load instruments
+  if (bmf.version > BMF0_9B)
+  {
+    unsigned long iflags = (tune[ptr] << 24) | (tune[ptr+1] << 16) | (tune[ptr+2] << 8) | tune[ptr+3];
+    ptr+=4;
+
+    for(i=0;i<32;i++)
+      if (iflags & (1 << (31-i)))
+	  {
+        strcpy(bmf.instruments[i].name, (char *)&tune[ptr]);
+        memcpy(bmf.instruments[i].data, &tune[ptr+11], 13);
+        ptr += 24;
+	  }
+      else
+	  {
+        bmf.instruments[i].name[0] = 0;
+		
+        if (bmf.version == BMF1_1)
+		  for(int j=0;j<13;j++)
+			bmf.instruments[i].data[j] = bmf_default_instrument[j];
+        else
+		  for(int j=0;j<13;j++)
+			bmf.instruments[i].data[j] = 0;
+	  }
+  }
+  else
+  {
+    ptr = 6;
+
+    for(i=0;i<32;i++)
+    {
+      bmf.instruments[i].name[0] = 0;
+      memcpy(bmf.instruments[tune[ptr]].data, &tune[ptr+2],13); // bug no.1 (no instrument-table-end detection)
+      ptr+=15;
+    }
+  }
+  
+  // load streams
+  if (bmf.version > BMF0_9B)
+  {
+    unsigned long sflags = (tune[ptr] << 24) | (tune[ptr+1] << 16) | (tune[ptr+2] << 8) | tune[ptr+3];
+    ptr+=4;
+
+    for(i=0;i<9;i++)
+      if (sflags & (1 << (31-i)))
+        ptr+=__bmf_convert_stream(&tune[ptr],i);
+      else
+        bmf.streams[i][0].cmd = 0xFF;
+  }
+  else
+  {
+    for(i=0;i<tune[5];i++)
+      ptr+=__bmf_convert_stream(&tune[ptr],i);
+
+	for(i=tune[5];i<9;i++)
+      bmf.streams[i][0].cmd = 0xFF;
+  }
+
+  return true;
+}
+
+void CxadbmfPlayer::xadplayer_rewind(int subsong)
+{
+  int i,j;
+
+  for(i=0; i<9; i++)
+  {
+    bmf.channel[i].stream_position = 0;
+    bmf.channel[i].delay = 0;
+    bmf.channel[i].loop_position = 0;
+    bmf.channel[i].loop_counter = 0;
+  }
+
+  plr.speed = bmf.speed;
+#ifdef DEBUG
+  AdPlug_LogWrite("speed: %x\n",plr.speed);
+#endif
+
+  bmf.active_streams = 9;
+
+  // OPL initialization
+  if (bmf.version > BMF0_9B)
+  {
+    opl_write(0x01, 0x20);
+    
+    /* 1.1 */
+    if (bmf.version == BMF1_1)
+      for(i=0;i<9;i++)
+        for(j=0;j<13;j++)
+          opl_write(bmf_adlib_registers[13*i+j], bmf_default_instrument[j]);
+    /* 1.2 */
+    else if (bmf.version == BMF1_2)
+      for(i=0x20; i<0x100; i++)
+        opl_write(i,0xFF); // very interesting, really!
+  }
+
+  /* ALL */
+
+  opl_write(0x08, 0x00);
+  opl_write(0xBD, 0xC0);
+}
+
+void CxadbmfPlayer::xadplayer_update()
+{
+  for(int i=0;i<9;i++)
+    if (bmf.channel[i].stream_position != 0xFFFF)
+    if (bmf.channel[i].delay)
+      bmf.channel[i].delay--;
+	else
+	{
+#ifdef DEBUG
+   AdPlug_LogWrite("channel %02X:\n", i);
+#endif
+      bmf_event event;
+
+      // process so-called cross-events
+  	  while (true)
+	  {
+        memcpy(&event, &bmf.streams[i][bmf.channel[i].stream_position], sizeof(bmf_event));
+#ifdef DEBUG
+   AdPlug_LogWrite("%02X %02X %02X %02X %02X %02X\n",event.note,event.delay,event.volume,event.instrument,event.cmd,event.cmd_data );
+#endif
+
+        if (event.cmd == 0xFF)
+		{
+          bmf.channel[i].stream_position = 0xFFFF;
+          bmf.active_streams--;
+          break;
+		}
+        else if (event.cmd == 0xFE)
+		{
+          bmf.channel[i].loop_position = bmf.channel[i].stream_position+1;
+          bmf.channel[i].loop_counter = event.cmd_data;
+		}
+        else if (event.cmd == 0xFD)
+		{
+          if (bmf.channel[i].loop_counter)
+          {
+            bmf.channel[i].stream_position = bmf.channel[i].loop_position-1;
+            bmf.channel[i].loop_counter--;
+          }
+		}
+        else
+          break;
+
+        bmf.channel[i].stream_position++;
+	  } // while (true)
+
+      // process normal event
+      unsigned short pos = bmf.channel[i].stream_position;
+
+      if (pos != 0xFFFF)
+      {
+        bmf.channel[i].delay = bmf.streams[i][pos].delay;
+
+        // command ?
+        if (bmf.streams[i][pos].cmd)
+		{
+          unsigned char cmd = bmf.streams[i][pos].cmd;
+
+          // 0x01: Set Modulator Volume
+          if (cmd == 0x01)
+		  {
+            unsigned char reg = bmf_adlib_registers[13*i+2];
+
+            opl_write(reg, (adlib[reg] | 0x3F) - bmf.streams[i][pos].cmd_data);
+		  }
+          // 0x10: Set Speed
+		  else if (cmd == 0x10)
+		  {
+            plr.speed = bmf.streams[i][pos].cmd_data;
+		    plr.speed_counter = plr.speed;
+		  }
+		} // if (bmf.streams[i][pos].cmd)
+
+        // instrument ?
+        if (bmf.streams[i][pos].instrument)
+		{
+          unsigned char ins = bmf.streams[i][pos].instrument-1;
+
+          if (bmf.version != BMF1_1)
+            opl_write(0xB0+i, adlib[0xB0+i] & 0xDF);
+
+          for(int j=0;j<13;j++)
+            opl_write(bmf_adlib_registers[i*13+j], bmf.instruments[ins].data[j]);
+		} // if (bmf.streams[i][pos].instrument)
+
+        // volume ?
+        if (bmf.streams[i][pos].volume)
+		{
+          unsigned char vol = bmf.streams[i][pos].volume-1;
+          unsigned char reg = bmf_adlib_registers[13*i+3];
+
+          opl_write(reg, (adlib[reg] | 0x3F) - vol);
+		} // if (bmf.streams[i][pos].volume)
+
+	    // note ?
+        if (bmf.streams[i][pos].note)
+		{
+          unsigned short note = bmf.streams[i][pos].note;
+          unsigned short freq = 0;
+
+          // mute channel
+          opl_write(0xB0+i, adlib[0xB0+i] & 0xDF);
+
+          // get frequency
+          if (bmf.version == BMF1_1)
+          {
+            if (note <= 0x60)
+              freq = bmf_notes_2[--note % 12];
+          }
+          else
+		  {
+            if (note != 0x7F)
+              freq = bmf_notes[--note % 12];
+		  }
+
+          // play note
+		  if (freq)
+          {
+            opl_write(0xB0+i, (freq >> 8) | ((note / 12) << 2) | 0x20);
+            opl_write(0xA0+i, freq & 0xFF);
+          }
+		} // if (bmf.streams[i][pos].note)
+
+        bmf.channel[i].stream_position++;
+      } // if (pos != 0xFFFF)
+
+	} // if (!bmf.channel[i].delay)
+
+  // is module loop ?
+  if (!bmf.active_streams)
+  {
+    for(int j=0;j<9;j++)
+      bmf.channel[j].stream_position = 0;
+
+	bmf.active_streams = 9;
+
+    plr.looping = 1;
+  }
+}
+
+float CxadbmfPlayer::xadplayer_getrefresh()
+{
+  return bmf.timer;
+}
+
+std::string CxadbmfPlayer::xadplayer_gettype()
+{
+  return std::string("xad: BMF Adlib Tracker");
+}
+
+std::string CxadbmfPlayer::xadplayer_gettitle()
+{
+  return std::string(bmf.title);
+}
+
+std::string CxadbmfPlayer::xadplayer_getauthor()
+{
+  return std::string(bmf.author);
+}
+
+unsigned int CxadbmfPlayer::xadplayer_getinstruments()
+{
+  return 32;
+}
+
+std::string CxadbmfPlayer::xadplayer_getinstrument(unsigned int i)
+{
+  return std::string(bmf.instruments[i].name);
+}
+
+/* -------- Internal Functions ---------------------------- */
+
+int CxadbmfPlayer::__bmf_convert_stream(unsigned char *stream, int channel)
+{
+#ifdef DEBUG
+  AdPlug_LogWrite("channel %02X (note,delay,volume,instrument,command,command_data):\n",channel);
+  unsigned char *last = stream;
+#endif
+  unsigned char *stream_start = stream;
+
+  int pos = 0;
+
+  while (true)
+  {
+    memset(&bmf.streams[channel][pos], 0, sizeof(bmf_event));
+
+    bool is_cmd = false;
+
+    if (*stream == 0xFE)
+	{
+      // 0xFE -> 0xFF: End of Stream
+      bmf.streams[channel][pos].cmd = 0xFF;
+
+	  stream++;
+
+      break;
+	}
+    else if (*stream == 0xFC)
+	{
+      // 0xFC -> 0xFE xx: Save Loop Position
+      bmf.streams[channel][pos].cmd = 0xFE;
+      bmf.streams[channel][pos].cmd_data = (*(stream+1) & ((bmf.version == BMF0_9B) ? 0x7F : 0x3F)) - 1;
+
+	  stream+=2;
+    }
+    else if (*stream == 0x7D)
+	{
+      // 0x7D -> 0xFD: Loop Saved Position
+      bmf.streams[channel][pos].cmd = 0xFD;
+
+	  stream++;
+	}
+	else
+    {
+      if (*stream & 0x80)                           
+      {
+		if (*(stream+1) & 0x80)
+        {
+		  if (*(stream+1) & 0x40)
+          {
+            // byte0: 1aaaaaaa = NOTE
+            bmf.streams[channel][pos].note = *stream & 0x7F;
+            // byte1: 11bbbbbb = DELAY
+            bmf.streams[channel][pos].delay = *(stream+1) & 0x3F;
+            // byte2: cccccccc = COMMAND
+
+            stream+=2;
+
+            is_cmd = true;
+          }
+		  else
+          {
+            // byte0: 1aaaaaaa = NOTE
+            bmf.streams[channel][pos].note = *stream & 0x7F;
+            // byte1: 11bbbbbb = DELAY
+            bmf.streams[channel][pos].delay = *(stream+1) & 0x3F;
+
+			stream+=2;
+          } // if (*(stream+1) & 0x40)
+		}
+        else
+        {
+          // byte0: 1aaaaaaa = NOTE
+          bmf.streams[channel][pos].note = *stream & 0x7F;
+          // byte1: 0bbbbbbb = COMMAND
+
+          stream++;
+
+          is_cmd = true;
+        } // if (*(stream+1) & 0x80)
+	  }
+	  else
+      {
+        // byte0: 0aaaaaaa = NOTE
+        bmf.streams[channel][pos].note = *stream & 0x7F;
+
+		stream++;
+      } // if (*stream & 0x80)
+    } // if (*stream == 0xFE)
+
+	// is command ?
+    if (is_cmd)
+    {
+
+      /* ALL */
+
+      if ((0x20 <= *stream) && (*stream <= 0x3F))
+      {
+        // 0x20 or higher; 0x3F or lower: Set Instrument 
+        bmf.streams[channel][pos].instrument = *stream - 0x20 + 1;
+
+		stream++;
+      }
+      else if (0x40 <= *stream)
+      {
+        // 0x40 or higher: Set Volume
+        bmf.streams[channel][pos].volume = *stream - 0x40 + 1;
+
+		stream++;
+      }
+      else
+      {
+
+        /* 0.9b */
+
+        if (bmf.version == BMF0_9B)
+        if (*stream < 0x20)
+		{
+          // 0x1F or lower: ?
+		  stream++;
+		}
+
+        /* 1.2 */
+
+        if (bmf.version == BMF1_2)
+        if (*stream == 0x01)
+		{
+          // 0x01: Set Modulator Volume -> 0x01
+          bmf.streams[channel][pos].cmd = 0x01;
+          bmf.streams[channel][pos].cmd_data = *(stream+1);
+
+		  stream+=2;
+		}
+        else if (*stream == 0x02)
+		{
+          // 0x02: ?
+		  stream+=2;
+		}
+        else if (*stream == 0x03)
+		{
+          // 0x03: ?
+		  stream+=2;
+		}
+        else if (*stream == 0x04)
+		{
+          // 0x04: Set Speed -> 0x10
+          bmf.streams[channel][pos].cmd = 0x10;
+          bmf.streams[channel][pos].cmd_data = *(stream+1);
+
+          stream+=2;
+		}
+        else if (*stream == 0x05)
+		{
+          // 0x05: Set Carrier Volume (port 380)
+          bmf.streams[channel][pos].volume = *(stream+1) + 1;
+
+		  stream+=2;
+		}
+        else if (*stream == 0x06)
+		{
+          // 0x06: Set Carrier Volume (port 382)
+          bmf.streams[channel][pos].volume = *(stream+1) + 1;
+
+		  stream+=2;
+		} // if (bmf.version == BMF1_2)
+
+      } // if ((0x20 <= *stream) && (*stream <= 0x3F))
+
+    } // if (is_cmd)
+
+#ifdef DEBUG
+   AdPlug_LogWrite("%02X %02X %02X %02X %02X %02X  <----  ", 
+			bmf.streams[channel][pos].note,	
+			bmf.streams[channel][pos].delay,
+			bmf.streams[channel][pos].volume, 
+			bmf.streams[channel][pos].instrument,
+			bmf.streams[channel][pos].cmd, 
+			bmf.streams[channel][pos].cmd_data
+		   );
+   for(int zz=0;zz<(stream-last);zz++)
+     AdPlug_LogWrite("%02X ",last[zz]);
+   AdPlug_LogWrite("\n");
+   last=stream;
+#endif
+    pos++;
+  } // while (true)
+
+  return (stream - stream_start);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/bmf.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,91 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * [xad] BMF player, by Riven the Mage <riven@ok.ru>
+ */
+
+#include "xad.h"
+
+class CxadbmfPlayer: public CxadPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+  CxadbmfPlayer(Copl *newopl): CxadPlayer(newopl)
+    { };
+  ~CxadbmfPlayer()
+    { };
+
+protected:
+  enum { BMF0_9B, BMF1_1, BMF1_2 };
+  //
+  struct bmf_event
+  {
+    unsigned char   note;
+    unsigned char   delay;
+    unsigned char   volume;
+    unsigned char   instrument;
+    unsigned char   cmd;
+    unsigned char   cmd_data;
+  };
+
+  struct
+  {
+    unsigned char   version;
+    char            title[36];
+    char            author[36];
+    float           timer;
+    unsigned char   speed;
+  
+    struct
+    {
+      char            name[11];
+      unsigned char   data[13];
+    } instruments[32];
+
+    bmf_event       streams[9][1024];
+
+    int             active_streams;
+
+    struct
+    {
+      unsigned short  stream_position;
+      unsigned char   delay;
+      unsigned short  loop_position;
+      unsigned char   loop_counter;
+    } channel[9];
+  } bmf;
+  //
+  bool            xadplayer_load();
+  void            xadplayer_rewind(int subsong);
+  void            xadplayer_update();
+  float           xadplayer_getrefresh();
+  std::string     xadplayer_gettype();
+  std::string     xadplayer_gettitle();
+  std::string     xadplayer_getauthor();
+  std::string     xadplayer_getinstrument(unsigned int i);
+  unsigned int    xadplayer_getinstruments();
+  //
+private:
+  static const unsigned char bmf_adlib_registers[117];
+  static const unsigned short bmf_notes[12];
+  static const unsigned short bmf_notes_2[12];
+  static const unsigned char bmf_default_instrument[13];
+
+  int             __bmf_convert_stream(unsigned char *stream, int channel);
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/cff.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,487 @@
+/*
+  AdPlug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2002 Simon Peter <dn.tlp@gmx.net>, et al.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  cff.cpp - BoomTracker loader by Riven the Mage <riven@ok.ru>
+*/
+/*
+  NOTE: Conversion of slides is not 100% accurate. Original volume slides
+  have effect on carrier volume only. Also, original arpeggio, frequency & volume
+  slides use previous effect data instead of current.
+*/
+
+#include <stdlib.h>
+
+#include "cff.h"
+
+/* -------- Public Methods -------------------------------- */
+
+CPlayer *CcffLoader::factory(Copl *newopl)
+{
+  return new CcffLoader(newopl);
+}
+
+bool CcffLoader::load(const std::string &filename, const CFileProvider &fp)
+{
+        binistream *f = fp.open(filename); if(!f) return false;
+	const unsigned char conv_inst[11] = { 2,1,10,9,4,3,6,5,0,8,7 };
+	const unsigned short conv_note[12] = { 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287, 0x2AE };
+
+	int i,j,k,t=0;
+
+	// '<CUD-FM-File>' - signed ?
+	f->readString(header.id, 16);
+	header.version = f->readInt(1); header.size = f->readInt(2);
+	header.packed = f->readInt(1); f->readString((char *)header.reserved, 12);
+	if (memcmp(header.id,"<CUD-FM-File>""\x1A\xDE\xE0",16))
+	  { fp.close(f); return false; }
+
+	unsigned char *module = new unsigned char [0x10000];
+
+	// packed ?
+	if (header.packed)
+	{
+		cff_unpacker *unpacker = new cff_unpacker;
+
+		unsigned char *packed_module = new unsigned char [header.size + 4];
+
+		memset(packed_module,0,header.size + 4);
+
+		f->readString((char *)packed_module, header.size);
+		fp.close(f);
+
+		if (!unpacker->unpack(packed_module,module))
+		{
+			delete unpacker;
+			delete packed_module;
+			delete module;
+			return false;
+		}
+
+		delete unpacker;
+		delete packed_module;
+
+		if (memcmp(&module[0x5E1],"CUD-FM-File - SEND A POSTCARD -",31))
+		{
+			delete module;
+			return false;
+		}
+	}
+	else
+	{
+		f->readString((char *)module, header.size);
+		fp.close(f);
+	}
+
+	// init CmodPlayer
+	realloc_instruments(47);
+	realloc_order(64);
+	realloc_patterns(36,64,9);
+	init_notetable(conv_note);
+	init_trackord();
+
+	// load instruments
+	for (i=0;i<47;i++)
+	{
+		memcpy(&instruments[i],&module[i*32],sizeof(cff_instrument));
+
+		for (j=0;j<11;j++)
+			inst[i].data[conv_inst[j]] = instruments[i].data[j];
+
+		instruments[i].name[20] = 0;
+	}
+
+	// number of patterns
+	nop = module[0x5E0];
+
+	// load title & author
+	memcpy(song_title,&module[0x614],20);
+	memcpy(song_author,&module[0x600],20);
+
+	// load order
+	memcpy(order,&module[0x628],64);
+
+	// load tracks
+	for (i=0;i<nop;i++)
+	{
+		unsigned char old_event_byte2[9];
+
+		memset(old_event_byte2,0,9);
+
+		for (j=0;j<9;j++)
+		{
+			for (k=0;k<64;k++)
+			{
+				cff_event *event = (cff_event *)&module[0x669 + ((i*64+k)*9+j)*3];
+
+				// convert note
+				if (event->byte0 == 0x6D)
+					tracks[t][k].note = 127;
+				else
+					if (event->byte0)
+						tracks[t][k].note = event->byte0;
+
+				if (event->byte2)
+					old_event_byte2[j] = event->byte2;
+
+				// convert effect
+				switch (event->byte1)
+				{
+					case 'I': // set instrument
+						tracks[t][k].inst = event->byte2 + 1;
+						tracks[t][k].param1 = tracks[t][k].param2 = 0;
+						break;
+
+					case 'H': // set tempo
+						tracks[t][k].command = 7;
+						if (event->byte2 < 16)
+						{
+							tracks[t][k].param1 = 0x07;
+	  						tracks[t][k].param2 = 0x0D;
+						}
+						break;
+
+					case 'A': // set speed
+						tracks[t][k].command = 19;
+						tracks[t][k].param1  = event->byte2 >> 4;
+						tracks[t][k].param2  = event->byte2 & 15;
+						break;
+
+					case 'L': // pattern break
+						tracks[t][k].command = 13;
+						tracks[t][k].param1  = event->byte2 >> 4;
+						tracks[t][k].param2  = event->byte2 & 15;
+						break;
+
+					case 'K': // order jump
+						tracks[t][k].command = 11;
+						tracks[t][k].param1  = event->byte2 >> 4;
+						tracks[t][k].param2  = event->byte2 & 15;
+						break;
+
+					case 'M': // set vibrato/tremolo
+						tracks[t][k].command = 27;
+						tracks[t][k].param1  = event->byte2 >> 4;
+						tracks[t][k].param2  = event->byte2 & 15;
+						break;
+
+					case 'C': // set modulator volume
+						tracks[t][k].command = 21;
+						tracks[t][k].param1 = (0x3F - event->byte2) >> 4;
+						tracks[t][k].param2 = (0x3F - event->byte2) & 15;
+						break;
+
+					case 'G': // set carrier volume
+						tracks[t][k].command = 22;
+						tracks[t][k].param1 = (0x3F - event->byte2) >> 4;
+						tracks[t][k].param2 = (0x3F - event->byte2) & 15;
+						break;
+
+					case 'B': // set carrier waveform
+						tracks[t][k].command = 25;
+						tracks[t][k].param1  = event->byte2;
+						tracks[t][k].param2  = 0x0F;
+						break;
+
+					case 'E': // fine frequency slide down
+						tracks[t][k].command = 24;
+						tracks[t][k].param1  = old_event_byte2[j] >> 4;
+						tracks[t][k].param2  = old_event_byte2[j] & 15;
+						break;
+
+					case 'F': // fine frequency slide up
+						tracks[t][k].command = 23;
+						tracks[t][k].param1  = old_event_byte2[j] >> 4;
+						tracks[t][k].param2  = old_event_byte2[j] & 15;
+						break;
+
+					case 'D': // fine volume slide
+						tracks[t][k].command = 14;
+						if (old_event_byte2[j] & 15)
+						{
+							// slide down
+							tracks[t][k].param1 = 5;
+							tracks[t][k].param2 = old_event_byte2[j] & 15;
+						}
+						else
+						{
+							// slide up
+							tracks[t][k].param1 = 4;
+							tracks[t][k].param2 = old_event_byte2[j] >> 4;
+						}
+						break;
+
+					case 'J': // arpeggio
+						tracks[t][k].param1  = old_event_byte2[j] >> 4;
+						tracks[t][k].param2  = old_event_byte2[j] & 15;
+						break;
+				}
+			}
+
+			t++;
+		}
+	}
+
+	delete [] module;
+
+	// order loop
+	restartpos = 0;
+
+	// order length
+	for (i=0;i<64;i++)
+	{
+		if (order[i] >= 0x80)
+		{
+			length = i;
+			break;
+		}
+	}
+
+	// default tempo
+	bpm = 0x7D;
+
+	rewind(0);
+
+	return true;	
+}
+
+void CcffLoader::rewind(int subsong)
+{
+	CmodPlayer::rewind(subsong);
+
+	// default instruments
+	for (int i=0;i<9;i++)
+	{
+		channel[i].inst = i;
+
+		channel[i].vol1 = 63 - (inst[i].data[10] & 63);
+		channel[i].vol2 = 63 - (inst[i].data[9] & 63);
+	}
+}
+
+std::string CcffLoader::gettype()
+{
+	if (header.packed)
+		return std::string("BoomTracker 4, packed");
+	else
+		return std::string("BoomTracker 4");
+}
+
+std::string CcffLoader::gettitle()
+{
+	return std::string(song_title,20);
+}
+
+std::string CcffLoader::getauthor()
+{
+	return std::string(song_author,20);
+}
+
+std::string CcffLoader::getinstrument(unsigned int n)
+{
+	return std::string(instruments[n].name);
+}
+
+unsigned int CcffLoader::getinstruments()
+{
+	return 47;
+}
+
+/* -------- Private Methods ------------------------------- */
+
+#ifdef _WIN32
+#pragma warning(disable:4244)
+#pragma warning(disable:4018)
+#endif
+
+/*
+  Lempel-Ziv-Tyr ;-)
+*/
+long CcffLoader::cff_unpacker::unpack(unsigned char *ibuf, unsigned char *obuf)
+{
+	if (memcmp(ibuf,"YsComp""\x07""CUD1997""\x1A\x04",16))
+		return 0;
+
+	input = ibuf + 16;
+	output = obuf;
+
+	output_length = 0;
+
+	heap = (unsigned char *)malloc(0x10000);
+	dictionary = (unsigned char **)malloc(sizeof(unsigned char *)*0x8000);
+
+	memset(heap,0,0x10000);
+	memset(dictionary,0,0x8000);
+
+	cleanup();
+	startup();
+
+	// LZW
+	while (1)
+	{
+		new_code = get_code();
+
+		// 0x00: end of data
+		if (new_code == 0)
+			break;
+
+		// 0x01: end of block
+		if (new_code == 1)
+		{
+			cleanup();
+			startup();
+
+			continue;
+		}
+
+		// 0x02: expand code length
+		if (new_code == 2)
+		{
+			code_length++;
+
+			continue;
+		}
+
+		// 0x03: RLE
+		if (new_code == 3)
+		{
+			unsigned char old_code_length = code_length;
+
+			code_length = 2;
+
+			unsigned char repeat_length = get_code() + 1;
+
+			code_length = 4 << get_code();
+
+			unsigned long repeat_counter = get_code();
+
+			for (unsigned int i=0;i<repeat_counter*repeat_length;i++)
+				output[output_length++] = output[output_length - repeat_length];
+
+			code_length = old_code_length;
+
+			startup();
+
+			continue;
+		}
+
+		if (new_code >= (0x104 + dictionary_length))
+		{
+			// dictionary <- old.code.string + old.code.char
+			the_string[++the_string[0]] = the_string[1];
+		}
+		else
+		{
+			// dictionary <- old.code.string + new.code.char
+			unsigned char temp_string[256];
+
+			translate_code(new_code,temp_string);
+
+			the_string[++the_string[0]] = temp_string[1];
+		}
+
+		expand_dictionary(the_string);
+
+		// output <- new.code.string
+		translate_code(new_code,the_string);
+
+		for (int i=0;i<the_string[0];i++)
+			output[output_length++] = the_string[i+1];
+
+		old_code = new_code;
+	}
+
+	free(heap);
+	free(dictionary);
+
+	return output_length;
+}
+
+unsigned long CcffLoader::cff_unpacker::get_code()
+{
+	unsigned long code;
+
+	while (bits_left < code_length)
+	{
+		bits_buffer |= ((*input++) << bits_left);
+		bits_left += 8;
+	}
+
+	code = bits_buffer & ((1 << code_length) - 1);
+
+	bits_buffer >>= code_length;
+	bits_left -= code_length;
+
+	return code;
+}
+
+void CcffLoader::cff_unpacker::translate_code(unsigned long code, unsigned char *string)
+{
+	unsigned char translated_string[256];
+
+	if (code >= 0x104)
+	{
+		memcpy(translated_string,dictionary[code - 0x104],(*(dictionary[code - 0x104])) + 1);
+	}
+	else
+	{
+		translated_string[0] = 1;
+		translated_string[1] = (code - 4) & 0xFF;
+	}
+
+	memcpy(string,translated_string,256);
+}
+
+void CcffLoader::cff_unpacker::cleanup()
+{
+	code_length = 9;
+
+	bits_buffer = 0;
+	bits_left = 0;
+
+	heap_length = 0;
+	dictionary_length = 0;
+}
+
+void CcffLoader::cff_unpacker::startup()
+{
+	old_code = get_code();
+
+	translate_code(old_code,the_string);
+
+	for (int i=0;i<the_string[0];i++)
+		output[output_length++] = the_string[i+1];
+}
+
+void CcffLoader::cff_unpacker::expand_dictionary(unsigned char *string)
+{
+	if (string[0] >= 0xF0)
+		return;
+
+	memcpy(&heap[heap_length],string,string[0] + 1);
+
+	dictionary[dictionary_length] = &heap[heap_length];
+
+	dictionary_length++;
+
+	heap_length += (string[0] + 1);
+}
+
+#ifdef _WIN32
+#pragma warning(default:4244)
+#pragma warning(default:4018)
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/cff.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,103 @@
+/*
+  AdPlug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2003 Simon Peter <dn.tlp@gmx.net>, et al.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  cff.h - BoomTracker loader by Riven the Mage <riven@ok.ru>
+*/
+
+#include "protrack.h"
+
+class CcffLoader: public CmodPlayer
+{
+	public:
+		static CPlayer *factory(Copl *newopl);
+
+		CcffLoader(Copl *newopl) : CmodPlayer(newopl) { };
+
+		bool	load(const std::string &filename, const CFileProvider &fp);
+		void	rewind(int subsong);
+
+		std::string		gettype();
+		std::string		gettitle();
+		std::string		getauthor();
+		std::string		getinstrument(unsigned int n);
+		unsigned int	getinstruments();
+
+	private:
+
+		class cff_unpacker
+		{
+			public:
+
+				long unpack(unsigned char *ibuf, unsigned char *obuf);
+
+			private:
+
+				unsigned long get_code();
+				void translate_code(unsigned long code, unsigned char *string);
+
+				void cleanup();
+				void startup();
+
+				void expand_dictionary(unsigned char *string);
+
+				unsigned char *input;
+				unsigned char *output;
+
+				long output_length;
+
+				unsigned char code_length;
+
+				unsigned long bits_buffer;
+				unsigned int bits_left;
+
+				unsigned char *heap;
+				unsigned char **dictionary;
+
+				unsigned int heap_length;
+				unsigned int dictionary_length;
+
+				unsigned long old_code,new_code;
+
+				unsigned char the_string[256];
+		};
+
+		struct cff_header
+		{
+			char	id[16];
+			unsigned char	version;
+			unsigned short	size;
+			unsigned char	packed;
+			unsigned char	reserved[12];
+		} header;
+
+		struct cff_instrument
+		{
+			unsigned char	data[12];
+			char            name[21];
+		} instruments[47];
+
+		char    song_title[20];
+		char	song_author[20];
+
+		struct cff_event
+		{
+			unsigned char	byte0;
+			unsigned char	byte1;
+			unsigned char	byte2;
+		};
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/d00.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,527 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * d00.c - D00 Player by Simon Peter <dn.tlp@gmx.net>
+ *
+ * NOTES:
+ * Sorry for the goto's, but the code looks so much nicer now.
+ * I tried it with while loops but it was just a mess. If you
+ * can come up with a nicer solution, just tell me.
+ *
+ * BUGS:
+ * Hard restart SR is sometimes wrong
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "debug.h"
+#include "d00.h"
+
+#define HIBYTE(val)	(val >> 8)
+#define LOBYTE(val)	(val & 0xff)
+
+static const unsigned short notetable[12] =	// D00 note table
+			{340,363,385,408,432,458,485,514,544,577,611,647};
+
+/*** public methods *************************************/
+
+CPlayer *Cd00Player::factory(Copl *newopl)
+{
+  return new Cd00Player(newopl);
+}
+
+bool Cd00Player::load(const std::string &filename, const CFileProvider &fp)
+{
+        binistream	*f = fp.open(filename); if(!f) return false;
+	d00header	*checkhead;
+	d00header1	*ch;
+	unsigned long	filesize;
+	int		i,ver1=0;
+	char		*str;
+
+	// file validation section
+	checkhead = new d00header;
+	f->readString((char *)checkhead, sizeof(d00header));
+
+	// Check for version 2-4 header
+	if(strncmp(checkhead->id,"JCH\x26\x02\x66",6) || checkhead->type ||
+	   !checkhead->subsongs || checkhead->soundcard) {
+	  // Check for version 0 or 1 header (and .d00 file extension)
+		delete checkhead;
+		if(!fp.extension(filename, ".d00")) { fp.close(f); return false; }
+		ch = new d00header1;
+		f->seek(0); f->readString((char *)ch, sizeof(d00header1));
+		if(ch->version > 1 || !ch->subsongs)
+		  { delete ch; fp.close(f); return false; }
+		delete ch;
+		ver1 = 1;
+	} else
+		delete checkhead;
+
+	AdPlug_LogWrite("Cd00Player::load(f,\"%s\"): %s format D00 file detected!\n",
+			filename.c_str(), ver1 ? "Old" : "New");
+
+	// load section
+	filesize = fp.filesize(f); f->seek(0);
+	filedata = new char [filesize + 1];			// 1 byte is needed for old-style DataInfo block
+	f->readString((char *)filedata, filesize);
+	fp.close(f);
+	if(!ver1) {	// version 2 and above
+		header = (struct d00header *)filedata;
+		version = header->version;
+		datainfo = (char *)filedata + header->infoptr;
+		inst = (struct Sinsts *)((char *)filedata + header->instptr);
+		seqptr = (unsigned short *)((char *)filedata + header->seqptr);
+		for(i=31;i>=0;i--)	// erase whitespace
+			if(header->songname[i] == ' ')
+				header->songname[i] = '\0';
+			else
+				break;
+		for(i=31;i>=0;i--)
+			if(header->author[i] == ' ')
+				header->author[i] = '\0';
+			else
+				break;
+	} else {	// version 1
+		header1 = (struct d00header1 *)filedata;
+		version = header1->version;
+		datainfo = (char *)filedata + header1->infoptr;
+		inst = (struct Sinsts *)((char *)filedata + header1->instptr);
+		seqptr = (unsigned short *)((char *)filedata + header1->seqptr);
+	}
+	switch(version) {
+	case 0:
+		levpuls = 0;
+		spfx = 0;
+		header1->speed = 70;		// v0 files default to 70Hz
+		break;
+	case 1:
+		levpuls = (struct Slevpuls *)((char *)filedata + header1->lpulptr);
+		spfx = 0;
+		break;
+	case 2:
+		levpuls = (struct Slevpuls *)((char *)filedata + header->spfxptr);
+		spfx = 0;
+		break;
+	case 3:
+		spfx = 0;
+		levpuls = 0;
+		break;
+	case 4:
+		spfx = (struct Sspfx *)((char *)filedata + header->spfxptr);
+		levpuls = 0;
+		break;
+	}
+	if((str = strstr(datainfo,"\xff\xff")))
+		while((*str == '\xff' || *str == ' ') && str >= datainfo) {
+			*str = '\0'; str--;
+		}
+	else	// old-style block
+		memset((char *)filedata+filesize,0,1);
+
+	rewind(0);
+	return true;
+}
+
+bool Cd00Player::update()
+{
+	unsigned char	c,cnt,trackend=0,fx,note;
+	unsigned short	ord,*patt,buf,fxop;
+
+	// effect handling (timer dependant)
+	for(c=0;c<9;c++) {
+		channel[c].slideval += channel[c].slide; setfreq(c);	// sliding
+		vibrato(c);	// vibrato
+
+		if(channel[c].spfx != 0xffff) {	// SpFX
+			if(channel[c].fxdel)
+				channel[c].fxdel--;
+			else {
+				channel[c].spfx = spfx[channel[c].spfx].ptr;
+				channel[c].fxdel = spfx[channel[c].spfx].duration;
+				channel[c].inst = spfx[channel[c].spfx].instnr & 0xfff;
+				if(spfx[channel[c].spfx].modlev != 0xff)
+					channel[c].modvol = spfx[channel[c].spfx].modlev;
+				setinst(c);
+				if(spfx[channel[c].spfx].instnr & 0x8000)	// locked frequency
+					note = spfx[channel[c].spfx].halfnote;
+				else												// unlocked frequency
+					note = spfx[channel[c].spfx].halfnote + channel[c].note;
+				channel[c].freq = notetable[note%12] + ((note/12) << 10);
+				setfreq(c);
+			}
+			channel[c].modvol += spfx[channel[c].spfx].modlevadd; channel[c].modvol &= 63;
+			setvolume(c);
+		}
+
+		if(channel[c].levpuls != 0xff)	// Levelpuls
+			if(channel[c].frameskip)
+				channel[c].frameskip--;
+			else {
+				channel[c].frameskip = inst[channel[c].inst].timer;
+				if(channel[c].fxdel)
+					channel[c].fxdel--;
+				else {
+					channel[c].levpuls = levpuls[channel[c].levpuls].ptr - 1;
+					channel[c].fxdel = levpuls[channel[c].levpuls].duration;
+					if(levpuls[channel[c].levpuls].level != 0xff)
+						channel[c].modvol = levpuls[channel[c].levpuls].level;
+				}
+				channel[c].modvol += levpuls[channel[c].levpuls].voladd; channel[c].modvol &= 63;
+				setvolume(c);
+			}
+	}
+
+	// song handling
+	for(c=0;c<9;c++)
+		if(version < 3 ? channel[c].del : channel[c].del <= 0x7f) {
+			if(version == 4)	// v4: hard restart SR
+				if(channel[c].del == inst[channel[c].inst].timer)
+					if(channel[c].nextnote)
+						opl->write(0x83 + op_table[c], inst[channel[c].inst].sr);
+			if(version < 3)
+				channel[c].del--;
+			else
+				if(channel[c].speed)
+					channel[c].del += channel[c].speed;
+				else {
+					channel[c].seqend = 1;
+					continue;
+				}
+		} else {
+			if(channel[c].speed) {
+				if(version < 3)
+					channel[c].del = channel[c].speed;
+				else {
+					channel[c].del &= 0x7f;
+					channel[c].del += channel[c].speed;
+				}
+			} else {
+				channel[c].seqend = 1;
+				continue;
+			}
+			if(channel[c].rhcnt) {	// process pending REST/HOLD events
+				channel[c].rhcnt--;
+				continue;
+			}
+readorder:	// process arrangement (orderlist)
+			ord = channel[c].order[channel[c].ordpos];
+			switch(ord) {
+			case 0xfffe: channel[c].seqend = 1; continue;	// end of arrangement stream
+			case 0xffff:										// jump to order
+				channel[c].ordpos = channel[c].order[channel[c].ordpos+1];
+				channel[c].seqend = 1;
+				goto readorder;
+			default:
+				if(ord >= 0x9000) {		// set speed
+					channel[c].speed = ord & 0xff;
+					ord = channel[c].order[channel[c].ordpos - 1];
+					channel[c].ordpos++;
+				} else
+					if(ord >= 0x8000) {	// transpose track
+						channel[c].transpose = ord & 0xff;
+						if(ord & 0x100)
+							channel[c].transpose = -channel[c].transpose;
+						ord = channel[c].order[++channel[c].ordpos];
+					}
+				patt = (unsigned short *)((char *)filedata + seqptr[ord]);
+				break;
+			}
+readseq:	// process sequence (pattern)
+			if(!version)	// v0: always initialize rhcnt
+				channel[c].rhcnt = channel[c].irhcnt;
+			if(patt[channel[c].pattpos] == 0xffff) {	// pattern ended?
+				channel[c].pattpos = 0;
+				channel[c].ordpos++;
+				goto readorder;
+			}
+			cnt = HIBYTE(patt[channel[c].pattpos]);
+			note = LOBYTE(patt[channel[c].pattpos]);
+			fx = patt[channel[c].pattpos] >> 12;
+			fxop = patt[channel[c].pattpos] & 0x0fff;
+			channel[c].pattpos++;
+			channel[c].nextnote = LOBYTE(patt[channel[c].pattpos]) & 0x7f;
+			if(version ? cnt < 0x40 : !fx) {	// note event
+				switch(note) {
+				case 0:						// REST event
+				case 0x80:
+					if(!note || version) {
+						channel[c].key = 0;
+						setfreq(c);
+					}
+					// fall through...
+				case 0x7e:					// HOLD event
+					if(version)
+						channel[c].rhcnt = cnt;
+					channel[c].nextnote = 0;
+					break;
+				default:					// play note
+					channel[c].slideval = 0; channel[c].slide = 0; channel[c].vibdepth = 0;	// restart fx
+
+					if(version) {	// note handling for v1 and above
+						if(note > 0x80)	// locked note (no channel transpose)
+							note -= 0x80;
+						else			// unlocked note
+							note += channel[c].transpose;
+						channel[c].note = note;	// remember note for SpFX
+
+						if(channel[c].ispfx != 0xffff && cnt < 0x20) {	// reset SpFX
+							channel[c].spfx = channel[c].ispfx;
+							if(spfx[channel[c].spfx].instnr & 0x8000)	// locked frequency
+								note = spfx[channel[c].spfx].halfnote;
+							else												// unlocked frequency
+								note += spfx[channel[c].spfx].halfnote;
+							channel[c].inst = spfx[channel[c].spfx].instnr & 0xfff;
+							channel[c].fxdel = spfx[channel[c].spfx].duration;
+							if(spfx[channel[c].spfx].modlev != 0xff)
+								channel[c].modvol = spfx[channel[c].spfx].modlev;
+							else
+								channel[c].modvol = inst[channel[c].inst].data[7] & 63;
+						}
+
+						if(channel[c].ilevpuls != 0xff && cnt < 0x20) {	// reset LevelPuls
+							channel[c].levpuls = channel[c].ilevpuls;
+							channel[c].fxdel = levpuls[channel[c].levpuls].duration;
+							channel[c].frameskip = inst[channel[c].inst].timer;
+							if(levpuls[channel[c].levpuls].level != 0xff)
+								channel[c].modvol = levpuls[channel[c].levpuls].level;
+							else
+								channel[c].modvol = inst[channel[c].inst].data[7] & 63;
+						}
+
+						channel[c].freq = notetable[note%12] + ((note/12) << 10);
+						if(cnt < 0x20)	// normal note
+							playnote(c);
+						else {			// tienote
+							setfreq(c);
+							cnt -= 0x20;	// make count proper
+						}
+						channel[c].rhcnt = cnt;
+					} else {	// note handling for v0
+						if(cnt < 2)	// unlocked note
+							note += channel[c].transpose;
+						channel[c].note = note;
+
+						channel[c].freq = notetable[note%12] + ((note/12) << 10);
+						if(cnt == 1)	// tienote
+							setfreq(c);
+						else			// normal note
+							playnote(c);
+					}
+					break;
+				}
+				continue;	// event is complete
+			} else {		// effect event
+				switch(fx) {
+				case 6:		// Cut/Stop Voice
+					buf = channel[c].inst;
+					channel[c].inst = 0;
+					playnote(c);
+					channel[c].inst = buf;
+					channel[c].rhcnt = fxop;
+					continue;	// no note follows this event
+				case 7:		// Vibrato
+					channel[c].vibspeed = fxop & 0xff;
+					channel[c].vibdepth = fxop >> 8;
+					channel[c].trigger = fxop >> 9;
+					break;
+				case 8:		// v0: Duration
+					if(!version)
+						channel[c].irhcnt = fxop;
+					break;
+				case 9:		// New Level
+					channel[c].vol = fxop & 63;
+					if(channel[c].vol + channel[c].cvol < 63)	// apply channel volume
+						channel[c].vol += channel[c].cvol;
+					else
+						channel[c].vol = 63;
+					setvolume(c);
+					break;
+				case 0xb:	// v4: Set SpFX
+					if(version == 4)
+						channel[c].ispfx = fxop;
+					break;
+				case 0xc:	// Set Instrument
+					channel[c].ispfx = 0xffff;
+					channel[c].spfx = 0xffff;
+					channel[c].inst = fxop;
+					channel[c].modvol = inst[fxop].data[7] & 63;
+					if(version < 3 && version && inst[fxop].tunelev)	// Set LevelPuls
+						channel[c].ilevpuls = inst[fxop].tunelev - 1;
+					else {
+						channel[c].ilevpuls = 0xff;
+						channel[c].levpuls = 0xff;
+					}
+					break;
+				case 0xd:	// Slide up
+					channel[c].slide = fxop;
+					break;
+				case 0xe:	// Slide down
+					channel[c].slide = -fxop;
+					break;
+				}
+				goto readseq;	// event is incomplete, note follows
+			}
+		}
+
+	for(c=0;c<9;c++)
+		if(channel[c].seqend)
+			trackend++;
+	if(trackend == 9)
+		songend = 1;
+
+	return !songend;
+}
+
+void Cd00Player::rewind(int subsong)
+{
+	struct Stpoin {
+		unsigned short ptr[9];
+		unsigned char volume[9],dummy[5];
+	} *tpoin;
+	int i;
+
+	if(version > 1) {	// do nothing if subsong > number of subsongs
+		if(subsong >= header->subsongs)
+			return;
+	} else
+		if(subsong >= header1->subsongs)
+			return;
+
+	memset(channel,0,sizeof(channel));
+	if(version > 1)
+		tpoin = (struct Stpoin *)((char *)filedata + header->tpoin);
+	else
+		tpoin = (struct Stpoin *)((char *)filedata + header1->tpoin);
+	for(i=0;i<9;i++) {
+		if(tpoin[subsong].ptr[i]) {	// track enabled
+			channel[i].speed = *((unsigned short *)((char *)filedata + tpoin[subsong].ptr[i]));
+			channel[i].order = (unsigned short *)((char *)filedata + tpoin[subsong].ptr[i] + 2);
+		} else {					// track disabled
+			channel[i].speed = 0;
+			channel[i].order = 0;
+		}
+		channel[i].ispfx = 0xffff; channel[i].spfx = 0xffff;	// no SpFX
+		channel[i].ilevpuls = 0xff; channel[i].levpuls = 0xff;	// no LevelPuls
+		channel[i].cvol = tpoin[subsong].volume[i] & 0x7f;			// our player may savely ignore bit 7
+		channel[i].vol = channel[i].cvol;						// initialize volume
+	}
+	songend = 0;
+	opl->init(); opl->write(1,32);	// reset OPL chip
+}
+
+std::string Cd00Player::gettype()
+{
+	char	tmpstr[40];
+
+	sprintf(tmpstr,"EdLib packed (version %d)",version > 1 ? header->version : header1->version);
+	return std::string(tmpstr);
+}
+
+float Cd00Player::getrefresh()
+{
+	if(version > 1)
+		return header->speed;
+	else
+		return header1->speed;
+}
+
+unsigned int Cd00Player::getsubsongs()
+{
+	if(version <= 1)	// return number of subsongs
+		return header1->subsongs;
+	else
+		return header->subsongs;
+}
+
+/*** private methods *************************************/
+
+void Cd00Player::setvolume(unsigned char chan)
+{
+	unsigned char	op = op_table[chan];
+	unsigned short	insnr = channel[chan].inst;
+
+	opl->write(0x43 + op,(int)(63-((63-(inst[insnr].data[2] & 63))/63.0)*(63-channel[chan].vol)) +
+		(inst[insnr].data[2] & 192));
+	if(inst[insnr].data[10] & 1)
+		opl->write(0x40 + op,(int)(63-((63-channel[chan].modvol)/63.0)*(63-channel[chan].vol)) +
+			(inst[insnr].data[7] & 192));
+	else
+		opl->write(0x40 + op,channel[chan].modvol + (inst[insnr].data[7] & 192));
+}
+
+void Cd00Player::setfreq(unsigned char chan)
+{
+	unsigned short freq = channel[chan].freq;
+
+	if(version == 4)	// v4: apply instrument finetune
+		freq += inst[channel[chan].inst].tunelev;
+
+	freq += channel[chan].slideval;
+	opl->write(0xa0 + chan, freq & 255);
+	if(channel[chan].key)
+		opl->write(0xb0 + chan, ((freq >> 8) & 31) | 32);
+	else
+		opl->write(0xb0 + chan, (freq >> 8) & 31);
+}
+
+void Cd00Player::setinst(unsigned char chan)
+{
+	unsigned char	op = op_table[chan];
+	unsigned short	insnr = channel[chan].inst;
+
+	// set instrument data
+	opl->write(0x63 + op, inst[insnr].data[0]);
+	opl->write(0x83 + op, inst[insnr].data[1]);
+	opl->write(0x23 + op, inst[insnr].data[3]);
+	opl->write(0xe3 + op, inst[insnr].data[4]);
+	opl->write(0x60 + op, inst[insnr].data[5]);
+	opl->write(0x80 + op, inst[insnr].data[6]);
+	opl->write(0x20 + op, inst[insnr].data[8]);
+	opl->write(0xe0 + op, inst[insnr].data[9]);
+	if(version)
+		opl->write(0xc0 + chan, inst[insnr].data[10]);
+	else
+		opl->write(0xc0 + chan, (inst[insnr].data[10] << 1) + (inst[insnr].tunelev & 1));
+}
+
+void Cd00Player::playnote(unsigned char chan)
+{
+	// set misc vars & play
+	opl->write(0xb0 + chan, 0);	// stop old note
+	setinst(chan);
+	channel[chan].key = 1;
+	setfreq(chan);
+	setvolume(chan);
+}
+
+void Cd00Player::vibrato(unsigned char chan)
+{
+	if(!channel[chan].vibdepth)
+		return;
+
+	if(channel[chan].trigger)
+		channel[chan].trigger--;
+	else {
+		channel[chan].trigger = channel[chan].vibdepth;
+		channel[chan].vibspeed = -channel[chan].vibspeed;
+	}
+	channel[chan].freq += channel[chan].vibspeed;
+	setfreq(chan);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/d00.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,107 @@
+/*
+ * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * d00.h - D00 Player by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#ifndef H_D00
+#define H_D00
+
+#include "player.h"
+
+class Cd00Player: public CPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	Cd00Player(Copl *newopl)
+		: CPlayer(newopl), filedata(0)
+	{ };
+	~Cd00Player()
+	{ if(filedata) delete [] filedata; };
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+	bool update();
+	void rewind(int subsong);
+	float getrefresh();
+
+	std::string gettype();
+	std::string gettitle()
+	{ if(version > 1) return std::string(header->songname); else return std::string(); };
+	std::string getauthor()
+	{ if(version > 1) return std::string(header->author); else return std::string(); };
+	std::string getdesc()
+	{ if(*datainfo) return std::string(datainfo); else return std::string(); };
+	unsigned int getsubsongs();
+
+protected:
+#pragma pack(1)
+	struct d00header {
+		char id[6];
+		unsigned char type,version,speed,subsongs,soundcard;
+		char songname[32],author[32],dummy[32];
+		unsigned short tpoin,seqptr,instptr,infoptr,spfxptr,endmark;
+	};
+
+	struct d00header1 {
+		unsigned char version,speed,subsongs;
+		unsigned short tpoin,seqptr,instptr,infoptr,lpulptr,endmark;
+	};
+#pragma pack()
+
+	struct {
+		unsigned short	*order,ordpos,pattpos,del,speed,rhcnt,key,freq,inst,spfx,ispfx,irhcnt;
+		signed short	transpose,slide,slideval,vibspeed;
+		unsigned char	seqend,vol,vibdepth,fxdel,modvol,cvol,levpuls,frameskip,nextnote,note,ilevpuls,trigger;
+	} channel[9];
+
+	struct Sinsts {
+		unsigned char data[11],tunelev,timer,sr,dummy[2];
+	} *inst;
+
+	struct Sspfx {
+		unsigned short instnr;
+		signed char halfnote;
+		unsigned char modlev;
+		signed char modlevadd;
+		unsigned char duration;
+		unsigned short ptr;
+	} *spfx;
+
+	struct Slevpuls {
+		unsigned char level;
+		signed char voladd;
+		unsigned char duration,ptr;
+	} *levpuls;
+
+	unsigned char songend,version;
+	char *datainfo;
+	unsigned short *seqptr;
+	d00header *header;
+	d00header1 *header1;
+	char *filedata;
+
+private:
+	void setvolume(unsigned char chan);
+	void setfreq(unsigned char chan);
+	void setinst(unsigned char chan);
+	void playnote(unsigned char chan);
+	void vibrato(unsigned char chan);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/database.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,423 @@
+/*
+ * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (c) 1999 - 2003 Simon Peter <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * database.cpp - AdPlug database class
+ * Copyright (c) 2002 Riven the Mage <riven@ok.ru>
+ * Copyright (c) 2002, 2003 Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include <binio.h>
+#include <binfile.h>
+#include <string.h>
+
+#include "database.h"
+
+#define DB_FILEID_V10	"AdPlug Module Information Database 1.0\x10"
+
+/***** CAdPlugDatabase *****/
+
+const unsigned short CAdPlugDatabase::hash_radix = 0xfff1;	// should be prime
+
+CAdPlugDatabase::CAdPlugDatabase()
+  : linear_index(0), linear_logic_length(0), linear_length(0)
+{
+  db_linear = new DB_Bucket * [hash_radix];
+  db_hashed = new DB_Bucket * [hash_radix];
+  memset(db_linear, 0, sizeof(DB_Bucket *) * hash_radix);
+  memset(db_hashed, 0, sizeof(DB_Bucket *) * hash_radix);
+}
+
+CAdPlugDatabase::~CAdPlugDatabase()
+{
+  unsigned long i;
+
+  for(i = 0; i < linear_length; i++)
+    delete db_linear[i];
+
+  delete [] db_linear;
+  delete [] db_hashed;
+}
+
+bool CAdPlugDatabase::load(std::string db_name)
+{
+  binifstream f(db_name);
+  if(f.error()) return false;
+  return load(f);
+}
+
+bool CAdPlugDatabase::load(binistream &f)
+{
+  unsigned int idlen = strlen(DB_FILEID_V10);
+  char *id = new char [idlen];
+  unsigned long length;
+
+  // Open database as little endian with IEEE floats
+  f.setFlag(binio::BigEndian, false); f.setFlag(binio::FloatIEEE);
+
+  f.readString(id,idlen);
+  if(memcmp(id,DB_FILEID_V10,idlen)) {
+    delete [] id;
+    return false;
+  }
+  delete [] id;
+  length = f.readInt(4);
+
+  // read records
+  for(unsigned long i = 0; i < length; i++)
+    insert(CRecord::factory(f));
+
+  return true;
+}
+
+bool CAdPlugDatabase::save(std::string db_name)
+{
+  binofstream f(db_name);
+  if(f.error()) return false;
+  return save(f);
+}
+
+bool CAdPlugDatabase::save(binostream &f)
+{
+  unsigned long i;
+
+  f.writeString(DB_FILEID_V10);
+  f.writeInt(linear_logic_length, 4);
+
+  // write records
+  for(i = 0; i < linear_length; i++)
+    if(!db_linear[i]->deleted)
+      db_linear[i]->record->write(f);
+
+  return true;
+}
+
+CAdPlugDatabase::CRecord *CAdPlugDatabase::search(CKey const &key)
+{
+  if(lookup(key)) return get_record(); else return 0;
+}
+
+bool CAdPlugDatabase::lookup(CKey const &key)
+{
+  unsigned long index = make_hash(key);
+  if(!db_hashed[index]) return false;
+
+  // immediate hit ?
+  DB_Bucket *bucket = db_hashed[index];
+
+  if(!bucket->deleted && bucket->record->key == key) {
+    linear_index = bucket->index;
+    return true;
+  }
+
+  // in-chain hit ?
+  bucket = db_hashed[index]->chain;
+
+  while(bucket) {
+    if(!bucket->deleted && bucket->record->key == key) {
+      linear_index = bucket->index;
+      return true;
+    }
+
+    bucket = bucket->chain;
+  }
+
+  return false;
+}
+
+bool CAdPlugDatabase::insert(CRecord *record)
+{
+  long index;
+
+  // sanity checks
+  if(!record) return false;			// null-pointer given
+  if(linear_length == hash_radix) return false;	// max. db size exceeded
+  if(lookup(record->key)) return false;		// record already in db
+
+  // make bucket
+  DB_Bucket *bucket = new DB_Bucket(linear_length, record);
+  if(!bucket) return false;
+
+  // add to linear list
+  db_linear[linear_length] = bucket;
+  linear_logic_length++; linear_length++;
+
+  // add to hashed list
+  index = make_hash(record->key);
+
+  if(!db_hashed[index])	// First entry in hashtable
+    db_hashed[index] = bucket;
+  else {		// Add entry in chained list
+    DB_Bucket *chain = db_hashed[index];
+
+    while(chain->chain) chain = chain->chain;
+    chain->chain = bucket;
+  }
+
+  return true;
+}
+
+void CAdPlugDatabase::wipe(CRecord *record)
+{
+  if(!lookup(record->key)) return;
+  wipe();
+}
+
+void CAdPlugDatabase::wipe()
+{
+  if(!linear_length) return;
+
+  DB_Bucket *bucket = db_linear[linear_index];
+
+  if(!bucket->deleted) {
+    delete bucket->record;
+    linear_logic_length--;
+    bucket->deleted = true;
+  }
+}
+
+CAdPlugDatabase::CRecord *CAdPlugDatabase::get_record()
+{
+  if(!linear_length) return 0;
+  return db_linear[linear_index]->record;
+}
+
+bool CAdPlugDatabase::go_forward()
+{
+  if(linear_index + 1 < linear_length) {
+    linear_index++;
+    return true;
+  } else
+    return false;
+}
+
+bool CAdPlugDatabase::go_backward()
+{
+  if(!linear_index) return false;
+  linear_index--;
+  return true;
+}
+
+void CAdPlugDatabase::goto_begin()
+{	
+  if(linear_length) linear_index = 0;
+}
+
+void CAdPlugDatabase::goto_end()
+{
+  if(linear_length) linear_index = linear_length - 1;
+}
+
+inline unsigned long CAdPlugDatabase::make_hash(CKey const &key)
+{
+  return (key.crc32 + key.crc16) % hash_radix;
+}
+
+/***** CAdPlugDatabase::DB_Bucket *****/
+
+CAdPlugDatabase::DB_Bucket::DB_Bucket(unsigned long nindex, CRecord *newrecord, DB_Bucket *newchain)
+  : index(nindex), deleted(false), chain(newchain), record(newrecord)
+{
+}
+
+CAdPlugDatabase::DB_Bucket::~DB_Bucket()
+{
+  if(!deleted) delete record;
+}
+
+/***** CAdPlugDatabase::CRecord *****/
+
+CAdPlugDatabase::CRecord *CAdPlugDatabase::CRecord::factory(RecordType type)
+{
+  switch(type) {
+  case Plain: return new CPlainRecord;
+  case SongInfo: return new CInfoRecord;
+  case ClockSpeed: return new CClockRecord;
+  default: return 0;
+  }
+}
+
+CAdPlugDatabase::CRecord *CAdPlugDatabase::CRecord::factory(binistream &in)
+{
+  RecordType	type;
+  unsigned long	size;
+  CRecord	*rec;
+
+  type = (RecordType)in.readInt(1); size = in.readInt(4);
+  rec = factory(type);
+
+  if(rec) {
+    rec->key.crc16 = in.readInt(2); rec->key.crc32 = in.readInt(4);
+    rec->filetype = in.readString('\0'); rec->comment = in.readString('\0');
+    rec->read_own(in);
+    return rec;
+  } else {
+    // skip this record, cause we don't know about it
+    in.seek(size, binio::Add);
+    return 0;
+  }
+}
+
+void CAdPlugDatabase::CRecord::write(binostream &out)
+{
+  out.writeInt(type, 1);
+  out.writeInt(get_size() + filetype.length() + comment.length() + 8, 4);
+  out.writeInt(key.crc16, 2); out.writeInt(key.crc32, 4);
+  out.writeString(filetype); out.writeInt('\0', 1);
+  out.writeString(comment); out.writeInt('\0', 1);
+
+  write_own(out);
+}
+
+bool CAdPlugDatabase::CRecord::user_read(std::istream &in, std::ostream &out)
+{
+  return user_read_own(in, out);
+}
+
+bool CAdPlugDatabase::CRecord::user_write(std::ostream &out)
+{
+  out << "Record type: ";
+  switch(type) {
+  case Plain: out << "Plain"; break;
+  case SongInfo: out << "SongInfo"; break;
+  case ClockSpeed: out << "ClockSpeed"; break;
+  default: out << "*** Unknown ***"; break;
+  }
+  out << std::endl;
+  out << "Key: " << std::hex << key.crc16 << ":" << key.crc32 << std::dec << std::endl;
+  out << "File type: " << filetype << std::endl;
+  out << "Comment: " << comment << std::endl;
+
+  return user_write_own(out);
+}
+
+/***** CAdPlugDatabase::CRecord::CKey *****/
+
+CAdPlugDatabase::CKey::CKey(binistream &buf)
+{
+  make(buf);
+}
+
+bool CAdPlugDatabase::CKey::operator==(const CKey &key)
+{
+  return ((crc16 == key.crc16) && (crc32 == key.crc32));
+}
+
+void CAdPlugDatabase::CKey::make(binistream &buf)
+// Key is CRC16:CRC32 pair. CRC16 and CRC32 calculation routines (c) Zhengxi
+{
+  static const unsigned short magic16 = 0xa001;
+  static const unsigned long  magic32 = 0xedb88320;
+
+  crc16 = 0; crc32 = ~0;
+
+  while(!buf.eof())
+    {
+      unsigned char byte = buf.readInt(1);
+
+      for (int j=0;j<8;j++)
+	{
+	  if ((crc16 ^ byte) & 1)
+	    crc16 = (crc16 >> 1) ^ magic16;
+	  else
+	    crc16 >>= 1;
+
+	  if ((crc32 ^ byte) & 1)
+	    crc32 = (crc32 >> 1) ^ magic32;
+	  else
+	    crc32 >>= 1;
+
+	  byte >>= 1;
+	}
+    }
+
+  crc16 &= 0xffff;
+  crc32  = ~crc32;
+}
+
+/***** CInfoRecord *****/
+
+CInfoRecord::CInfoRecord()
+{
+  type = SongInfo;
+}
+
+void CInfoRecord::read_own(binistream &in)
+{
+  title = in.readString('\0');
+  author = in.readString('\0');
+}
+
+void CInfoRecord::write_own(binostream &out)
+{
+  out.writeString(title); out.writeInt('\0', 1);
+  out.writeString(author); out.writeInt('\0', 1);
+}
+
+unsigned long CInfoRecord::get_size()
+{
+  return title.length() + author.length() + 2;
+}
+
+bool CInfoRecord::user_read_own(std::istream &in, std::ostream &out)
+{
+  out << "Title: "; in >> title;
+  out << "Author: "; in >> author;
+  return true;
+}
+
+bool CInfoRecord::user_write_own(std::ostream &out)
+{
+  out << "Title: " << title << std::endl;
+  out << "Author: " << author << std::endl;
+  return true;
+}
+
+/***** CClockRecord *****/
+
+CClockRecord::CClockRecord()
+  : clock(0.0f)
+{
+  type = ClockSpeed;
+}
+
+void CClockRecord::read_own(binistream &in)
+{
+  clock = in.readFloat(binio::Single);
+}
+
+void CClockRecord::write_own(binostream &out)
+{
+  out.writeFloat(clock, binio::Single);
+}
+
+unsigned long CClockRecord::get_size()
+{
+  return 4;
+}
+
+bool CClockRecord::user_read_own(std::istream &in, std::ostream &out)
+{
+  out << "Clockspeed: "; in >> clock;
+  return true;
+}
+
+bool CClockRecord::user_write_own(std::ostream &out)
+{
+  out << "Clock speed: " << clock << " Hz" << std::endl;
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/database.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,169 @@
+/*
+ * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (c) 1999 - 2003 Simon Peter <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * database.h - AdPlug database class
+ * Copyright (c) 2002 Riven the Mage <riven@ok.ru>
+ * Copyright (c) 2002, 2003 Simon Peter <dn.tlp@gmx.net>
+ */
+
+#ifndef H_ADPLUG_DATABASE
+#define H_ADPLUG_DATABASE
+
+#include <iostream>
+#include <string>
+#include <binio.h>
+
+class CAdPlugDatabase
+{
+public:
+  class CKey
+  {
+  public:
+    unsigned short	crc16;
+    unsigned long	crc32;
+
+    CKey() {};
+    CKey(binistream &in);
+
+    bool operator==(const CKey &key);
+
+  private:
+    void make(binistream &in);
+  };
+
+  class CRecord
+  {
+  public:
+    typedef enum { Plain, SongInfo, ClockSpeed } RecordType;
+
+    RecordType	type;
+    CKey	key;
+    std::string	filetype, comment;
+
+    static CRecord *factory(RecordType type);
+    static CRecord *factory(binistream &in);
+
+    CRecord() {}
+    virtual ~CRecord() {}
+
+    void write(binostream &out);
+
+    bool user_read(std::istream &in, std::ostream &out);
+    bool user_write(std::ostream &out);
+
+  protected:
+    virtual void read_own(binistream &in) = 0;
+    virtual void write_own(binostream &out) = 0;
+    virtual unsigned long get_size() = 0;
+    virtual bool user_read_own(std::istream &in, std::ostream &out) = 0;
+    virtual bool user_write_own(std::ostream &out) = 0;
+  };
+
+  CAdPlugDatabase();
+  ~CAdPlugDatabase();
+
+  bool	load(std::string db_name);
+  bool	load(binistream &f);
+  bool	save(std::string db_name);
+  bool	save(binostream &f);
+
+  bool	insert(CRecord *record);
+
+  void	wipe(CRecord *record);
+  void	wipe();
+
+  CRecord *search(CKey const &key);
+  bool lookup(CKey const &key);
+
+  CRecord *get_record();
+
+  bool	go_forward();
+  bool	go_backward();
+
+  void	goto_begin();
+  void	goto_end();
+
+private:
+  static const unsigned short hash_radix;
+
+  class DB_Bucket
+  {
+  public:
+    unsigned long	index;
+    bool		deleted;
+    DB_Bucket		*chain;
+
+    CRecord		*record;
+
+    DB_Bucket(unsigned long nindex, CRecord *newrecord, DB_Bucket *newchain = 0);
+    ~DB_Bucket();
+  };
+
+  DB_Bucket	**db_linear;
+  DB_Bucket	**db_hashed;
+
+  unsigned long	linear_index, linear_logic_length, linear_length;
+
+  unsigned long make_hash(CKey const &key);
+};
+
+class CPlainRecord: public CAdPlugDatabase::CRecord
+{
+public:
+  CPlainRecord() { type = Plain; }
+
+protected:
+  virtual void read_own(binistream &in) {}
+  virtual void write_own(binostream &out) {}
+  virtual unsigned long get_size() { return 0; }
+  virtual bool user_read_own(std::istream &in, std::ostream &out) { return true; }
+  virtual bool user_write_own(std::ostream &out) { return true; }
+};
+
+class CInfoRecord: public CAdPlugDatabase::CRecord
+{
+public:
+  std::string	title;
+  std::string	author;
+
+  CInfoRecord();
+
+protected:
+  virtual void read_own(binistream &in);
+  virtual void write_own(binostream &out);
+  virtual unsigned long get_size();
+  virtual bool user_read_own(std::istream &in, std::ostream &out);
+  virtual bool user_write_own(std::ostream &out);
+};
+
+class CClockRecord: public CAdPlugDatabase::CRecord
+{
+public:
+  float	clock;
+
+  CClockRecord();
+
+protected:
+  virtual void read_own(binistream &in);
+  virtual void write_own(binostream &out);
+  virtual unsigned long get_size();
+  virtual bool user_read_own(std::istream &in, std::ostream &out);
+  virtual bool user_write_own(std::ostream &out);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/debug.c	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,57 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2002 Simon Peter <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * debug.h - AdPlug Debug Logger
+ * Copyright (c) 2002 Riven the Mage <riven@ok.ru>
+ * Copyright (c) 2002 Simon Peter <dn.tlp@gmx.net>
+ */
+
+#ifdef DEBUG
+
+#include <stdio.h>
+#include <stdarg.h>
+
+static FILE *log = NULL;
+
+void AdPlug_LogFile(const char *filename)
+{
+  if(log) fclose(log);
+  log = fopen(filename,"wt");
+}
+
+void AdPlug_LogWrite(const char *fmt, ...)
+{
+  va_list argptr;
+
+  va_start(argptr, fmt);
+
+  if(log) {
+    vfprintf(log, fmt, argptr);
+    fflush(log);
+  } else
+    vfprintf(stderr, fmt, argptr);
+
+  va_end(argptr);
+}
+
+#else
+
+void AdPlug_LogFile(char *filename) { }
+void AdPlug_LogWrite(char *fmt, ...) { }
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/debug.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,41 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2002 Simon Peter <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * debug.h - AdPlug Debug Logger
+ * Copyright (c) 2002 Riven the Mage <riven@ok.ru>
+ * Copyright (c) 2002 Simon Peter <dn.tlp@gmx.net>
+ *
+ * NOTES:
+ * This debug logger is used throughout AdPlug to log debug output to stderr
+ * (the default) or to a user-specified logfile.
+ *
+ * To use it, AdPlug has to be compiled with debug logging support enabled.
+ * This is done by defining the DEBUG macro with every source-file. The
+ * LogFile() function can be used to specify a logfile to write to.
+ */
+
+#ifndef H_DEBUG
+#define H_DEBUG
+
+extern "C"
+{
+        void AdPlug_LogFile(const char *filename);
+        void AdPlug_LogWrite(const char *fmt, ...);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/dfm.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,115 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * dfm.cpp - Digital-FM Loader by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "dfm.h"
+#include "debug.h"
+
+CPlayer *CdfmLoader::factory(Copl *newopl)
+{
+  return new CdfmLoader(newopl);
+}
+
+bool CdfmLoader::load(const std::string &filename, const CFileProvider &fp)
+{
+  binistream *f = fp.open(filename); if(!f) return false;
+  unsigned char		npats,n,note,fx,c,r,param;
+  unsigned int		i;
+  const unsigned char	convfx[8] = {255,255,17,19,23,24,255,13};
+
+  // file validation
+  f->readString(header.id, 4);
+  header.hiver = f->readInt(1); header.lover = f->readInt(1);
+  if(strncmp(header.id,"DFM\x1a",4) || header.hiver > 1)
+    { fp.close(f); return false; }
+
+  // load
+  restartpos = 0; flags = Standard; bpm = 0;
+  init_trackord();
+  f->readString(songinfo, 33);
+  initspeed = f->readInt(1);
+  for(i = 0; i < 32; i++)
+    f->readString(instname[i], 12);
+  for(i = 0; i < 32; i++) {
+    inst[i].data[1] = f->readInt(1);
+    inst[i].data[2] = f->readInt(1);
+    inst[i].data[9] = f->readInt(1);
+    inst[i].data[10] = f->readInt(1);
+    inst[i].data[3] = f->readInt(1);
+    inst[i].data[4] = f->readInt(1);
+    inst[i].data[5] = f->readInt(1);
+    inst[i].data[6] = f->readInt(1);
+    inst[i].data[7] = f->readInt(1);
+    inst[i].data[8] = f->readInt(1);
+    inst[i].data[0] = f->readInt(1);
+  }
+  for(i = 0; i < 128; i++) order[i] = f->readInt(1);
+  for(i = 0; i < 128 && order[i] != 128; i++) ; length = i;
+  npats = f->readInt(1);
+  for(i = 0; i < npats; i++) {
+    n = f->readInt(1);
+    for(r = 0; r < 64; r++)
+      for(c = 0; c < 9; c++) {
+	note = f->readInt(1);
+	if((note & 15) == 15)
+	  tracks[n*9+c][r].note = 127;	// key off
+	else
+	  tracks[n*9+c][r].note = ((note & 127) >> 4) * 12 + (note & 15);
+	if(note & 128) {	// additional effect byte
+	  fx = f->readInt(1);
+	  if(fx >> 5 == 1)
+	    tracks[n*9+c][r].inst = (fx & 31) + 1;
+	  else {
+	    tracks[n*9+c][r].command = convfx[fx >> 5];
+	    if(tracks[n*9+c][r].command == 17) {	// set volume
+	      param = fx & 31;
+	      param = 63 - param * 2;
+	      tracks[n*9+c][r].param1 = param >> 4;
+	      tracks[n*9+c][r].param2 = param & 15;
+	    } else {
+	      tracks[n*9+c][r].param1 = (fx & 31) >> 4;
+	      tracks[n*9+c][r].param2 = fx & 15;
+	    }
+	  }
+	}
+
+      }
+  }
+
+  fp.close(f);
+  rewind(0);
+  return true;
+}
+
+std::string CdfmLoader::gettype()
+{
+	char tmpstr[20];
+
+	sprintf(tmpstr,"Digital-FM %d.%d",header.hiver,header.lover);
+	return std::string(tmpstr);
+}
+
+float CdfmLoader::getrefresh()
+{
+	return 125.0f;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/dfm.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,52 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * dfm.h - Digital-FM Loader by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "protrack.h"
+
+class CdfmLoader: public CmodPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	CdfmLoader(Copl *newopl)
+		: CmodPlayer(newopl)
+	{ };
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+	float getrefresh();
+
+	std::string gettype();
+	unsigned int getinstruments()
+	{ return 32; };
+	std::string getinstrument(unsigned int n)
+	{ if(*instname[n]) return std::string(instname[n],1,*instname[n]); else return std::string(); };
+	std::string getdesc()
+	{ return std::string(songinfo,1,*songinfo); };
+
+private:
+	struct {
+		char id[4];
+		unsigned char hiver,lover;
+	} header;
+
+	char songinfo[33];
+	char instname[32][12];
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/diskopl.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,78 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999, 2000, 2001 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * diskopl.cpp - Disk Writer OPL, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "diskopl.h"
+
+static const unsigned short note_table[12] = {363,385,408,432,458,485,514,544,577,611,647,686};
+static const unsigned char op_table[9] = {0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12};
+
+CDiskopl::CDiskopl(std::string filename): old_freq(0.0f), del(1), nowrite(false)
+{
+	unsigned short clock = 0xffff;
+	f = fopen(filename.c_str(),"wb");
+	fwrite("RAWADATA",8,1,f);
+	fwrite(&clock,sizeof(clock),1,f);
+}
+
+CDiskopl::~CDiskopl()
+{
+	fclose(f);
+}
+
+void CDiskopl::update(CPlayer *p)
+{
+	unsigned short	clock;
+	unsigned int	wait;
+
+	if(p->getrefresh() != old_freq) {
+		old_freq = p->getrefresh();
+		del = wait = (unsigned int)(18.2f / old_freq);
+		clock = (unsigned short)(1192737/(old_freq*(wait+1)));
+		fputc(0,f); fputc(2,f);
+		fwrite(&clock,2,1,f);
+	}
+	if(!nowrite) {
+		fputc(del+1,f);
+		fputc(0,f);
+	}
+}
+
+void CDiskopl::write(int reg, int val)
+{
+	if(!nowrite)
+		diskwrite(reg,val);
+}
+
+void CDiskopl::init()
+{
+	for (int i=0;i<9;i++) {				// stop instruments
+		diskwrite(0xb0 + i,0);				// key off
+		diskwrite(0x80 + op_table[i],0xff);	// fastest release
+	}
+	diskwrite(0xbd,0);	// clear misc. register
+}
+
+void CDiskopl::diskwrite(int reg, int val)
+{
+	fputc(val,f);
+	fputc(reg,f);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/diskopl.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,49 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999, 2000, 2001 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * diskopl.h - Disk Writer OPL, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include <string>
+#include <stdio.h>
+#include "opl.h"
+#include "player.h"
+
+class CDiskopl: public Copl
+{
+public:
+	CDiskopl(std::string filename);
+	virtual ~CDiskopl();
+
+	void update(CPlayer *p);			// write to file
+	void setnowrite(bool nw = true)		// set file write status
+	{ nowrite = nw; };
+
+	// template methods
+	void write(int reg, int val);
+	void init();
+
+private:
+	void diskwrite(int reg, int val);
+
+	FILE			*f;
+	float			old_freq;
+	unsigned char	del;
+	bool			nowrite;			// don't write to file, if true
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/dmo.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,391 @@
+/*
+  Adplug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  dmo.cpp - TwinTeam loader by Riven the Mage <riven@ok.ru>
+*/
+/*
+  NOTES:
+  Panning is ignored.
+
+  A WORD ist 16 bits, a DWORD is 32 bits and a BYTE is 8 bits in this context.
+*/
+
+#include <string.h>
+#include <binstr.h>
+
+#include "dmo.h"
+#include "debug.h"
+
+#define LOWORD(l) ((l) & 0xffff)
+#define HIWORD(l) ((l) >> 16)
+#define LOBYTE(w) ((w) & 0xff)
+#define HIBYTE(w) ((w) >> 8)
+
+#define ARRAY_AS_DWORD(a, i) \
+((a[i + 3] << 24) + (a[i + 2] << 16) + (a[i + 1] << 8) + a[i])
+#define ARRAY_AS_WORD(a, i)	((a[i + 1] << 8) + a[i])
+
+#define CHARP_AS_WORD(p)	(((*(p + 1)) << 8) + (*p))
+
+/* -------- Public Methods -------------------------------- */
+
+CPlayer *CdmoLoader::factory(Copl *newopl)
+{
+  return new CdmoLoader(newopl);
+}
+
+bool CdmoLoader::load(const std::string &filename, const CFileProvider &fp)
+{
+  int i,j;
+  binistream *f;
+
+  // check header
+  dmo_unpacker *unpacker = new dmo_unpacker;
+  unsigned char chkhdr[16];
+
+  if(!fp.extension(filename, ".dmo")) return false;
+  f = fp.open(filename); if(!f) return false;
+
+  f->readString((char *)chkhdr, 16);
+
+  if (!unpacker->decrypt(chkhdr, 16))
+    {
+      delete unpacker;
+      fp.close(f);
+      return false;
+    }
+
+  // get file size
+  long packed_length = fp.filesize(f);
+  f->seek(0);
+
+  unsigned char *packed_module = new unsigned char [packed_length];
+
+  // load file
+  f->readString((char *)packed_module, packed_length);
+  fp.close(f);
+
+  // decrypt
+  unpacker->decrypt(packed_module,packed_length);
+
+  long unpacked_length = 0x2000 * ARRAY_AS_WORD(packed_module, 12);
+  unsigned char *module = new unsigned char [unpacked_length];
+
+  // unpack
+  if (!unpacker->unpack(packed_module+12,module))
+    {
+      delete unpacker;
+      delete [] packed_module;
+      delete [] module;
+      return false;
+    }
+
+  delete unpacker;
+  delete [] packed_module;
+
+  // "TwinTeam" - signed ?
+  if (memcmp(module,"TwinTeam Module File""\x0D\x0A",22))
+    {
+      delete module;
+      return false;
+    }
+
+  // load header
+  binisstream	uf(module, unpacked_length);
+  uf.setFlag(binio::BigEndian, false); uf.setFlag(binio::FloatIEEE);
+
+  memset(&header,0,sizeof(s3mheader));
+
+  uf.ignore(22);				// ignore DMO header ID string
+  uf.readString(header.name, 28);
+
+  uf.ignore(2);				// _unk_1
+  header.ordnum  = uf.readInt(2);
+  header.insnum  = uf.readInt(2);
+  header.patnum  = uf.readInt(2);
+  uf.ignore(2);				// _unk_2
+  header.is      = uf.readInt(2);
+  header.it      = uf.readInt(2);
+
+  memset(header.chanset,0xFF,32);
+
+  for (i=0;i<9;i++)
+    header.chanset[i] = 0x10 + i;
+
+  uf.ignore(32);				// ignore panning settings for all 32 channels
+
+  // load orders
+  for(i = 0; i < 256; i++) orders[i] = uf.readInt(1);
+
+  orders[header.ordnum] = 0xFF;
+
+  // load pattern lengths
+  unsigned short my_patlen[100];
+  for(i = 0; i < 100; i++) my_patlen[i] = uf.readInt(2);
+
+  // load instruments
+  for (i = 0; i < header.insnum; i++)
+    {
+      memset(&inst[i],0,sizeof(s3minst));
+
+      uf.readString(inst[i].name, 28);
+
+      inst[i].volume = uf.readInt(1);
+      inst[i].dsk    = uf.readInt(1);
+      inst[i].c2spd  = uf.readInt(4);
+      inst[i].type   = uf.readInt(1);
+      inst[i].d00    = uf.readInt(1);
+      inst[i].d01    = uf.readInt(1);
+      inst[i].d02    = uf.readInt(1);
+      inst[i].d03    = uf.readInt(1);
+      inst[i].d04    = uf.readInt(1);
+      inst[i].d05    = uf.readInt(1);
+      inst[i].d06    = uf.readInt(1);
+      inst[i].d07    = uf.readInt(1);
+      inst[i].d08    = uf.readInt(1);
+      inst[i].d09    = uf.readInt(1);
+      inst[i].d0a    = uf.readInt(1);
+      /*
+       * Originally, riven sets d0b = d0a and ignores 1 byte in the
+       * stream, but i guess this was a typo, so i read it here.
+       */
+      inst[i].d0b    = uf.readInt(1);
+    }
+
+  // load patterns
+  for (i = 0; i < header.patnum; i++) {
+    long cur_pos = uf.pos();
+
+    for (j = 0; j < 64; j++) {
+      while (1) {
+	unsigned char token = uf.readInt(1);
+
+	if (!token)
+	  break;
+
+	unsigned char chan = token & 31;
+
+	// note + instrument ?
+	if (token & 32) {
+	  unsigned char bufbyte = uf.readInt(1);
+
+	  pattern[i][j][chan].note = bufbyte & 15;
+	  pattern[i][j][chan].oct = bufbyte >> 4;
+	  pattern[i][j][chan].instrument = uf.readInt(1);
+	}
+
+	// volume ?
+	if (token & 64)
+	  pattern[i][j][chan].volume = uf.readInt(1);
+
+	// command ?
+	if (token & 128) {
+	  pattern[i][j][chan].command = uf.readInt(1);
+	  pattern[i][j][chan].info = uf.readInt(1);
+	}
+      }
+    }
+
+    uf.seek(cur_pos + my_patlen[i]);
+  }
+
+  delete [] module;
+  rewind(0);
+  return true;
+}
+
+std::string CdmoLoader::gettype()
+{
+  return std::string("TwinTeam (packed S3M)");
+}
+
+std::string CdmoLoader::getauthor()
+{
+  /*
+    All available .DMO modules written by one composer. And because all .DMO
+    stuff was lost due to hd crash (TwinTeam guys said this), there are
+    never(?) be another.
+  */
+  return std::string("Benjamin GERARDIN");
+}
+
+/* -------- Private Methods ------------------------------- */
+
+unsigned short CdmoLoader::dmo_unpacker::brand(unsigned short range)
+{
+  unsigned short ax,bx,cx,dx;
+
+  ax = LOWORD(bseed);
+  bx = HIWORD(bseed);
+  cx = ax;
+  ax = LOWORD(cx * 0x8405);
+  dx = HIWORD(cx * 0x8405);
+  cx <<= 3;
+  cx = (((HIBYTE(cx) + LOBYTE(cx)) & 0xFF) << 8) + LOBYTE(cx);
+  dx += cx;
+  dx += bx;
+  bx <<= 2;
+  dx += bx;
+  dx = (((HIBYTE(dx) + LOBYTE(bx)) & 0xFF) << 8) + LOBYTE(dx);
+  bx <<= 5;
+  dx = (((HIBYTE(dx) + LOBYTE(bx)) & 0xFF) << 8) + LOBYTE(dx);
+  ax += 1;
+  if (!ax) dx += 1;
+
+  // leave it that way or amd64 might get it wrong
+  bseed = dx;
+  bseed <<= 16;
+  bseed += ax;
+
+  return HIWORD(HIWORD(LOWORD(bseed) * range) + HIWORD(bseed) * range);
+}
+
+bool CdmoLoader::dmo_unpacker::decrypt(unsigned char *buf, long len)
+{
+  unsigned long seed = 0;
+  int i;
+
+  bseed = ARRAY_AS_DWORD(buf, 0);
+
+  for (i=0; i < ARRAY_AS_WORD(buf, 4) + 1; i++)
+    seed += brand(0xffff);
+
+  bseed = seed ^ ARRAY_AS_DWORD(buf, 6);
+
+  if (ARRAY_AS_WORD(buf, 10) != brand(0xffff))
+    return false;
+
+  for (i=0;i<(len-12);i++)
+    buf[12+i] ^= brand(0x100);
+
+  buf[len - 2] = buf[len - 1] = 0;
+
+  return true;
+}
+
+short CdmoLoader::dmo_unpacker::unpack_block(unsigned char *ibuf, long ilen, unsigned char *obuf)
+{
+  unsigned char code,par1,par2;
+  unsigned short ax,bx,cx;
+
+  unsigned char *ipos = ibuf;
+  unsigned char *opos = obuf;
+
+  // LZ77 child
+  while (ipos - ibuf < ilen)
+    {
+      code = *ipos++;
+
+      // 00xxxxxx: copy (xxxxxx + 1) bytes
+      if ((code >> 6) == 0)
+	{
+	  cx = (code & 0x3F) + 1;
+
+	  for (int i=0;i<cx;i++)
+	    *opos++ = *ipos++;
+
+	  continue;
+	}
+
+      // 01xxxxxx xxxyyyyy: copy (Y + 3) bytes from (X + 1)
+      if ((code >> 6) == 1)
+	{
+	  par1 = *ipos++;
+
+	  ax = ((code & 0x3F) << 3) + ((par1 & 0xE0) >> 5) + 1;
+	  cx = (par1 & 0x1F) + 3;
+
+	  for(int i=0;i<cx;i++)
+	    *opos++ = *(opos - ax);
+
+	  continue;
+	}
+
+      // 10xxxxxx xyyyzzzz: copy (Y + 3) bytes from (X + 1); copy Z bytes
+      if ((code >> 6) == 2)
+	{
+	  int i;
+
+	  par1 = *ipos++;
+
+	  ax = ((code & 0x3F) << 1) + (par1 >> 7) + 1;
+	  cx = ((par1 & 0x70) >> 4) + 3;
+	  bx = par1 & 0x0F;
+
+	  for(i=0;i<cx;i++)
+	    *opos++ = *(opos - ax);
+
+	  for (i=0;i<bx;i++)
+	    *opos++ = *ipos++;
+
+	  continue;
+	}
+
+      // 11xxxxxx xxxxxxxy yyyyzzzz: copy (Y + 4) from X; copy Z bytes
+      if ((code >> 6) == 3)
+	{
+	  int i;
+
+	  par1 = *ipos++;
+	  par2 = *ipos++;
+
+	  bx = ((code & 0x3F) << 7) + (par1 >> 1);
+	  cx = ((par1 & 0x01) << 4) + (par2 >> 4) + 4;
+	  ax = par2 & 0x0F;
+
+	  for(i=0;i<cx;i++)
+	    *opos++ = *(opos - bx);
+
+	  for (i=0;i<ax;i++)
+	    *opos++ = *ipos++;
+
+	  continue;
+	}
+    }
+
+  return opos - obuf;
+}
+
+long CdmoLoader::dmo_unpacker::unpack(unsigned char *ibuf, unsigned char *obuf)
+{
+  long olen = 0;
+
+  unsigned short block_count = CHARP_AS_WORD(ibuf);
+
+  ibuf += 2;
+
+  unsigned char *block_length = ibuf;
+
+  ibuf += 2 * block_count;
+
+  for (int i=0;i<block_count;i++)
+    {
+      unsigned short bul = CHARP_AS_WORD(ibuf);
+
+      if (unpack_block(ibuf + 2,CHARP_AS_WORD(block_length) - 2,obuf) != bul)
+	return 0;
+
+      obuf += bul;
+      olen += bul;
+
+      ibuf += CHARP_AS_WORD(block_length);
+      block_length += 2;
+    }
+
+  return olen;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/dmo.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,48 @@
+/*
+  Adplug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  dmo.cpp - TwinTeam loader by Riven the Mage <riven@ok.ru>
+*/
+
+#include "s3m.h"
+
+class CdmoLoader: public Cs3mPlayer
+{
+ public:
+  static CPlayer *factory(Copl *newopl);
+
+  CdmoLoader(Copl *newopl) : Cs3mPlayer(newopl) { };
+
+  bool	load(const std::string &filename, const CFileProvider &fp);
+
+  std::string	gettype();
+  std::string	getauthor();
+
+ private:
+
+  class dmo_unpacker {
+  public:
+    bool decrypt(unsigned char *buf, long len);
+    long unpack(unsigned char *ibuf, unsigned char *obuf);
+
+  private:
+    unsigned short brand(unsigned short range);
+    short unpack_block(unsigned char *ibuf, long ilen, unsigned char *obuf);
+    unsigned long bseed;
+  };
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/dro.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,99 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * dro.c - DOSBox Raw OPL Player by Sjoerd van der Berg <harekiet@zophar.net>
+ *
+ * NOTES:
+ * OPL3 and second opl2 writes are ignored
+  */
+
+#include "dro.h"
+
+/*** public methods *************************************/
+
+CPlayer *CdroPlayer::factory(Copl *newopl)
+{
+  return new CdroPlayer(newopl);
+}
+
+bool CdroPlayer::load(const std::string &filename, const CFileProvider &fp)
+{
+	binistream *f = fp.open(filename); if(!f) return false;
+	char id[8];unsigned long i;
+
+	// file validation section
+	f->readString(id, 8);
+	if(strncmp(id,"DBRAWOPL",8)) { fp.close (f); return false; }
+
+	// load section
+	mstotal = f->readInt(4);	// Total milliseconds in file
+	length = f->readInt(4);		// Total data bytes in file
+	mode = (OplMode)f->readInt(1);		// Type of opl data this can contain
+	data = new unsigned char [length];
+	for (i=0;i<length;i++) 
+		data[i]=f->readInt(1);
+	fp.close(f);
+	rewind(0);
+	return true;
+}
+
+bool CdroPlayer::update()
+{
+	if (delay>500) {
+		delay-=500;
+		return true;
+	} else delay=0;
+	while (pos < length) 
+	{	
+		unsigned char cmd = data[pos++];
+		switch(cmd) {
+		case 0: 
+			delay = 1 + data[pos++];
+			return true;
+		case 1: 
+			delay = 1 + data[pos] + (data[pos+1]<<8);
+			pos+=2;
+			return true;
+		case 2:
+			index = 0;
+			break;
+		case 3:
+			index = 0;
+			break;
+		default:
+		  if(!index)
+		    opl->write(cmd,data[pos++]);
+		  break;
+		}
+	}
+	return pos<length;
+}
+
+void CdroPlayer::rewind(int subsong)
+{
+	delay=1;
+	pos = index = 0; 
+	opl->init(); 
+	opl->write(1,32);	// go to OPL2 mode
+}
+
+float CdroPlayer::getrefresh()
+{
+	if (delay > 500) return 1000 / 500;
+	else return 1000 / (double)delay;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/dro.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,52 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * dro.h - DOSBox Raw OPL Player by Sjoerd van der Berg <harekiet@zophar.net>
+ */
+
+#include "player.h"
+
+class CdroPlayer: public CPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	CdroPlayer(Copl *newopl)
+		: CPlayer(newopl), data(0)
+	{ };
+	~CdroPlayer()
+	{ if(data) delete [] data; };
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+	bool update();
+	void rewind(int subsong);
+	float getrefresh();
+
+	std::string gettype()
+	{ return std::string("DOSBox Raw OPL"); };
+
+protected:
+	unsigned char *data;
+	unsigned long pos,length;
+	unsigned long msdone,mstotal;
+	unsigned short delay;
+	unsigned char index;
+	enum OplMode {
+		ModeOPL2,ModeOPL3,ModeDUALOPL2
+	} mode;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/dtm.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,312 @@
+/*
+  Adplug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  dtm.cpp - DTM loader by Riven the Mage <riven@ok.ru>
+*/
+/*
+  NOTE: Panning (Ex) effect is ignored.
+*/
+
+#include "dtm.h"
+
+/* -------- Public Methods -------------------------------- */
+
+CPlayer *CdtmLoader::factory(Copl *newopl)
+{
+  return new CdtmLoader(newopl);
+}
+
+bool CdtmLoader::load(const std::string &filename, const CFileProvider &fp)
+{
+        binistream *f = fp.open(filename); if(!f) return false;
+	const unsigned char conv_inst[11] = { 2,1,10,9,4,3,6,5,0,8,7 };
+	const unsigned short conv_note[12] = { 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287, 0x2AE };
+
+	int i,j,k,t=0;
+
+	// read header
+	f->readString(header.id, 12);
+	header.version = f->readInt(1);
+	f->readString(header.title, 20); f->readString(header.author, 20);
+	header.numpat = f->readInt(1); header.numinst = f->readInt(1);
+
+	// signature exists ? good version ?
+	if(memcmp(header.id,"DeFy DTM ",9) || header.version != 0x10)
+	  { fp.close (f); return false; }
+
+	header.numinst++;
+
+	// load description
+	memset(desc,0,80*16);
+
+	char bufstr[80];
+
+	for (i=0;i<16;i++)
+	{
+		// get line length
+		unsigned char bufstr_length = f->readInt(1);
+
+		// read line
+		if (bufstr_length)
+		{
+			f->readString(bufstr,bufstr_length);
+
+			for (j=0;j<bufstr_length;j++)
+				if (!bufstr[j])
+					bufstr[j] = 0x20;
+
+			bufstr[bufstr_length] = 0;
+
+			strcat(desc,bufstr);
+		}
+
+		strcat(desc,"\n");
+	}
+
+	// init CmodPlayer
+	realloc_instruments(header.numinst);
+	realloc_order(100);
+	realloc_patterns(header.numpat,64,9);
+	init_notetable(conv_note);
+	init_trackord();
+
+	// load instruments
+	for (i=0;i<header.numinst;i++)
+	{
+		unsigned char name_length = f->readInt(1);
+
+		if (name_length)
+			f->readString(instruments[i].name, name_length);
+
+		instruments[i].name[name_length] = 0;
+
+		for(j = 0; j < 12; j++)
+		  instruments[i].data[j] = f->readInt(1);
+
+		for (j=0;j<11;j++)
+			inst[i].data[conv_inst[j]] = instruments[i].data[j];
+	}
+
+	// load order
+	for(i = 0; i < 100; i++) order[i] = f->readInt(1);
+
+	nop = header.numpat;
+
+	unsigned char *pattern = new unsigned char [0x480];
+
+	// load tracks
+	for (i=0;i<nop;i++)
+	{
+		unsigned short packed_length;
+
+		packed_length = f->readInt(2);
+
+		unsigned char *packed_pattern = new unsigned char [packed_length];
+
+		for(j = 0; j < packed_length; j++)
+		  packed_pattern[j] = f->readInt(1);
+
+		long unpacked_length = unpack_pattern(packed_pattern,packed_length,pattern,0x480);
+
+		delete [] packed_pattern;
+
+		if (!unpacked_length)
+		{
+			delete pattern;
+			fp.close(f);
+			return false;
+		}
+
+		// convert pattern
+		for (j=0;j<9;j++)
+		{
+			for (k=0;k<64;k++)
+			{
+				dtm_event *event = (dtm_event *)&pattern[(k*9+j)*2];
+
+				// instrument
+				if (event->byte0 == 0x80)
+				{
+					if (event->byte1 <= 0x80)
+						tracks[t][k].inst = event->byte1 + 1;
+				}
+
+				// note + effect
+				else
+				{
+					tracks[t][k].note = event->byte0;
+
+					if ((event->byte0 != 0) && (event->byte0 != 127))
+							tracks[t][k].note++;
+
+					// convert effects
+					switch (event->byte1 >> 4)
+					{
+						case 0x0: // pattern break
+							if ((event->byte1 & 15) == 1)
+								tracks[t][k].command = 13;
+							break;
+
+						case 0x1: // freq. slide up
+							tracks[t][k].command = 28;
+							tracks[t][k].param1 = event->byte1 & 15;
+							break;
+
+						case 0x2: // freq. slide down
+							tracks[t][k].command = 28;
+							tracks[t][k].param2 = event->byte1 & 15;
+							break;
+
+						case 0xA: // set carrier volume
+						case 0xC: // set instrument volume
+							tracks[t][k].command = 22;
+							tracks[t][k].param1 = (0x3F - (event->byte1 & 15)) >> 4;
+							tracks[t][k].param2 = (0x3F - (event->byte1 & 15)) & 15;
+							break;
+
+						case 0xB: // set modulator volume
+							tracks[t][k].command = 21;
+							tracks[t][k].param1 = (0x3F - (event->byte1 & 15)) >> 4;
+							tracks[t][k].param2 = (0x3F - (event->byte1 & 15)) & 15;
+							break;
+
+						case 0xE: // set panning
+							break;
+
+						case 0xF: // set speed
+							tracks[t][k].command = 13;
+							tracks[t][k].param2 = event->byte1 & 15;
+							break;
+					}
+				}
+			}
+
+			t++;
+		}
+	}
+
+	delete [] pattern;
+	fp.close(f);
+
+	// order length
+	for (i=0;i<100;i++)
+	{
+		if (order[i] >= 0x80)
+		{
+			length = i;
+
+			if (order[i] == 0xFF)
+				restartpos = 0;
+			else
+				restartpos = order[i] - 0x80;
+
+			break;
+		}
+	}
+
+	// initial speed
+	initspeed = 2;
+
+	rewind(0);
+
+	return true;
+}
+
+void CdtmLoader::rewind(int subsong)
+{
+	CmodPlayer::rewind(subsong);
+
+	// default instruments
+	for (int i=0;i<9;i++)
+	{
+		channel[i].inst = i;
+
+		channel[i].vol1 = 63 - (inst[i].data[10] & 63);
+		channel[i].vol2 = 63 - (inst[i].data[9] & 63);
+	}
+}
+
+float CdtmLoader::getrefresh()
+{
+	return 18.2f;
+}
+
+std::string CdtmLoader::gettype()
+{
+	return std::string("DeFy Adlib Tracker");
+}
+
+std::string CdtmLoader::gettitle()
+{
+	return std::string(header.title);
+}
+
+std::string CdtmLoader::getauthor()
+{
+	return std::string(header.author);
+}
+
+std::string CdtmLoader::getdesc()
+{
+	return std::string(desc);
+}
+
+std::string CdtmLoader::getinstrument(unsigned int n)
+{
+	return std::string(instruments[n].name);
+}
+
+unsigned int CdtmLoader::getinstruments()
+{
+	return header.numinst;
+}
+
+/* -------- Private Methods ------------------------------- */
+
+long CdtmLoader::unpack_pattern(unsigned char *ibuf, long ilen, unsigned char *obuf, long olen)
+{
+	unsigned char *input = ibuf;
+	unsigned char *output = obuf;
+
+	long input_length = 0;
+	long output_length = 0;
+
+	unsigned char repeat_byte, repeat_counter;
+
+	// RLE
+	while (input_length < ilen)
+	{
+		repeat_byte = input[input_length++];
+
+		if ((repeat_byte & 0xF0) == 0xD0)
+		{
+			repeat_counter = repeat_byte & 15;
+			repeat_byte = input[input_length++];
+		}
+		else
+			repeat_counter = 1;
+
+		for (int i=0;i<repeat_counter;i++)
+		{
+			if (output_length < olen)
+				output[output_length++] = repeat_byte;
+		}
+	}
+
+	return output_length;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/dtm.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,69 @@
+/*
+  Adplug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  dtm.h - DTM loader by Riven the Mage <riven@ok.ru>
+*/
+
+#include "protrack.h"
+
+class CdtmLoader: public CmodPlayer
+{
+	public:
+		static CPlayer *factory(Copl *newopl);
+
+		CdtmLoader(Copl *newopl) : CmodPlayer(newopl) { };
+
+		bool	load(const std::string &filename, const CFileProvider &fp);
+		void	rewind(int subsong);
+		float	getrefresh();
+
+		std::string     gettype();
+		std::string     gettitle();
+		std::string     getauthor();
+		std::string     getdesc();
+		std::string     getinstrument(unsigned int n);
+		unsigned int    getinstruments();
+
+	private:
+
+		struct dtm_header
+		{
+			char            id[12];
+			unsigned char   version;
+			char            title[20];
+			char            author[20];
+			unsigned char   numpat;
+			unsigned char   numinst;
+		} header;
+
+		char desc[80*16];
+
+		struct dtm_instrument
+		{
+			char            name[13];
+			unsigned char   data[12];
+		} instruments[128];
+
+		struct dtm_event
+		{
+			unsigned char	byte0;
+			unsigned char	byte1;
+		};
+
+		long unpack_pattern(unsigned char *ibuf, long ilen, unsigned char *obuf, long olen);
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/emuopl.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,75 @@
+/*
+ * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2002 Simon Peter <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * emuopl.cpp - Emulated OPL, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "emuopl.h"
+
+CEmuopl::CEmuopl(int rate, bool bit16, bool usestereo)
+  : use16bit(bit16), stereo(usestereo)
+{
+  opl = OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
+}
+
+CEmuopl::~CEmuopl()
+{
+  OPLDestroy(opl);
+}
+
+void CEmuopl::update(short *buf, int samples)
+{
+	int i;
+
+	if(use16bit) {
+		YM3812UpdateOne(opl,buf,samples);
+
+		if(stereo)
+			for(i=samples-1;i>=0;i--) {
+				buf[i*2] = buf[i];
+				buf[i*2+1] = buf[i];
+			}
+	} else {
+		short *tempbuf = new short[stereo ? samples*2 : samples];
+		int i;
+
+		YM3812UpdateOne(opl,tempbuf,samples);
+
+		if(stereo)
+			for(i=samples-1;i>=0;i--) {
+				tempbuf[i*2] = tempbuf[i];
+				tempbuf[i*2+1] = tempbuf[i];
+			}
+
+		for(i=0;i<(stereo ? samples*2 : samples);i++)
+			((char *)buf)[i] = (tempbuf[i] >> 8) ^ 0x80;
+
+		delete [] tempbuf;
+	}
+}
+
+void CEmuopl::write(int reg, int val)
+{
+  OPLWrite(opl,0,reg);
+  OPLWrite(opl,1,val);
+}
+
+void CEmuopl::init()
+{
+  OPLResetChip(opl);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/emuopl.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,47 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * emuopl.h - Emulated OPL, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#ifndef H_ADPLUG_EMUOPL
+#define H_ADPLUG_EMUOPL
+
+#include "opl.h"
+extern "C" {
+#include "fmopl.h"
+}
+
+class CEmuopl: public Copl
+{
+public:
+	CEmuopl(int rate, bool bit16, bool usestereo);	// rate = sample rate
+	virtual ~CEmuopl();
+
+	void update(short *buf, int samples);	// fill buffer
+
+	// template methods
+	void write(int reg, int val);
+	void init();
+
+private:
+	bool	use16bit,stereo;
+	FM_OPL	*opl;				// holds emulator data
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/flash.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,230 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * [xad] FLASH player, by Riven the Mage <riven@ok.ru>
+ */
+
+/*
+    - discovery -
+
+  file(s) : LA-INTRO.EXE
+     type : Lunatic Asylum BBStro
+     tune : by Rogue [Logic Design]
+   player : by Flash [Logic Design]
+*/
+
+#include "flash.h"
+#include "debug.h"
+
+const unsigned char CxadflashPlayer::flash_adlib_registers[99] =
+{
+  0x23, 0x20, 0x43, 0x40, 0x63, 0x60, 0x83, 0x80, 0xC0, 0xE3, 0xE0,
+  0x24, 0x21, 0x44, 0x41, 0x64, 0x61, 0x84, 0x81, 0xC1, 0xE4, 0xE1,
+  0x25, 0x22, 0x45, 0x42, 0x65, 0x62, 0x85, 0x82, 0xC2, 0xE5, 0xE2,
+  0x2B, 0x28, 0x4B, 0x48, 0x6B, 0x68, 0x8B, 0x88, 0xC3, 0xEB, 0xE8,
+  0x2C, 0x29, 0x4C, 0x49, 0x6C, 0x69, 0x8C, 0x89, 0xC4, 0xEC, 0xE9,
+  0x2D, 0x2A, 0x4D, 0x4A, 0x6D, 0x6A, 0x8D, 0x8A, 0xC5, 0xED, 0xEA,
+  0x33, 0x30, 0x53, 0x50, 0x73, 0x70, 0x93, 0x90, 0xC6, 0xF3, 0xF0,
+  0x34, 0x31, 0x54, 0x51, 0x74, 0x71, 0x94, 0x91, 0xC7, 0xF4, 0xF1,
+  0x35, 0x32, 0x55, 0x52, 0x75, 0x72, 0x95, 0x92, 0xC8, 0xF5, 0xF2
+};
+
+const unsigned short CxadflashPlayer::flash_notes_encoded[268] =
+{
+  0x000,
+  0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800, 0x900, 0xA00, 0xB00, 0xC00,
+  0x101, 0x201, 0x301, 0x401, 0x501, 0x601, 0x701, 0x801, 0x901, 0xA01, 0xB01, 0xC01,
+  0x102, 0x202, 0x302, 0x402, 0x502, 0x602, 0x702, 0x802, 0x902, 0xA02, 0xB02, 0xC02,
+  0x103, 0x203, 0x303, 0x403, 0x503, 0x603, 0x703, 0x803, 0x903, 0xA03, 0xB03, 0xC03,
+  0x104, 0x204, 0x304, 0x404, 0x504, 0x604, 0x704, 0x804, 0x904, 0xA04, 0xB04, 0xC04,
+  0x105, 0x205, 0x305, 0x405, 0x505, 0x605, 0x705, 0x805, 0x905, 0xA05, 0xB05, 0xC05,
+  0x106, 0x206, 0x306, 0x406, 0x506, 0x606, 0x706, 0x806, 0x906, 0xA06, 0xB06, 0xC06,
+  0x107, 0x207, 0x307, 0x407, 0x507, 0x607, 0x707, 0x807, 0x907, 0xA07, 0xB07, 0xC07,
+  0x108, 0x208, 0x308, 0x408, 0x508, 0x608, 0x708, 0x808, 0x908, 0xA08, 0xB08, 0xC08,
+  0x109, 0x209, 0x309, 0x409, 0x509, 0x609, 0x709, 0x809, 0x909, 0xA09, 0xB09, 0xC09,
+  0x10A, 0x20A, 0x30A, 0x40A, 0x50A, 0x60A, 0x70A, 0x80A, 0x90A, 0xA0A, 0xB0A, 0xC0A,
+  0x10B, 0x20B, 0x30B, 0x40B, 0x50B, 0x60B, 0x70B, 0x80B, 0x90B, 0xA0B, 0xB0B, 0xC0B,
+  0x10C, 0x20C, 0x30C, 0x40C, 0x50C, 0x60C, 0x70C, 0x80C, 0x90C, 0xA0C, 0xB0C, 0xC0C,
+  0x10D, 0x20D, 0x30D, 0x40D, 0x50D, 0x60D, 0x70D, 0x80D, 0x90D, 0xA0D, 0xB0D, 0xC0D,
+  0x10E, 0x20E, 0x30E, 0x40E, 0x50E, 0x60E, 0x70E, 0x80E, 0x90E, 0xA0E, 0xB0E, 0xC0E,
+  0x10F, 0x20F, 0x30F, 0x40F, 0x50F, 0x60F, 0x70F, 0x80F, 0x90F, 0xA0F, 0xB0F, 0xC0F,
+  0x110, 0x210, 0x310, 0x410, 0x510, 0x610, 0x710, 0x810, 0x910, 0xA10, 0xB10, 0xC10,
+  0x111, 0x211, 0x311, 0x411, 0x511, 0x611, 0x711, 0x811, 0x911, 0xA11, 0xB11, 0xC11,
+  0x112, 0x212, 0x312, 0x412, 0x512, 0x612, 0x712, 0x812, 0x912, 0xA12, 0xB12, 0xC12,
+  0x113, 0x213, 0x313, 0x413, 0x513, 0x613, 0x713, 0x813, 0x913, 0xA13, 0xB13, 0xC13,
+  0x114, 0x214, 0x314, 0x414, 0x514, 0x614, 0x714, 0x814, 0x914, 0xA14, 0xB14, 0xC14,
+  0x115, 0x215, 0x315
+};
+
+const unsigned short CxadflashPlayer::flash_notes[12] =
+{
+  0x157, 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287
+};
+
+const unsigned char CxadflashPlayer::flash_default_instrument[8] =
+{
+  0x00, 0x00, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+CPlayer *CxadflashPlayer::factory(Copl *newopl)
+{
+  return new CxadflashPlayer(newopl);
+}
+
+void CxadflashPlayer::xadplayer_rewind(int subsong)
+{
+  int i;
+
+  plr.speed = xad.speed;
+
+  flash.order_pos = 0;
+  flash.pattern_pos = 0;
+
+  opl_write(0x08, 0x00);
+  opl_write(0xBD, 0x00);
+
+  // assign default instrument
+  for(i=0; i<9; i++)
+  {
+    opl_write(0xA0+i, 0x00);
+    opl_write(0xB0+i, 0x00);
+  }
+
+  // assign instruments
+  for(i=0; i<9; i++)
+    for(int j=0; j<11; j++)
+      opl_write(flash_adlib_registers[i*11+j], tune[i*12+j]);
+}
+
+void CxadflashPlayer::xadplayer_update()
+{
+  unsigned short event_pos = (tune[0x600+flash.order_pos]*1152) + \
+                             (flash.pattern_pos*18) + \
+                              0x633;
+
+  for (int i=0; i<9; i++)
+  {
+    unsigned short flash_channel_freq = (adlib[0xB0+i] << 8) + adlib[0xA0+i];
+
+    unsigned char event_b0 = tune[event_pos++];
+    unsigned char event_b1 = tune[event_pos++];
+#ifdef DEBUG
+  AdPlug_LogWrite("channel %02X, event %02X %02X:\n",i+1,event_b0,event_b1);
+#endif
+
+    if (event_b0 == 0x80)               // 0.0x80: Set Instrument
+    {
+      for(int j=0; j<11; j++)
+        opl_write(flash_adlib_registers[i*11+j], tune[event_b1*12+j]);
+    }
+    else
+    {
+      if (event_b1 == 0x01)
+        flash.pattern_pos = 0x3F;       // 1.0x01: Pattern Break
+
+      unsigned char fx = (event_b1 >> 4);
+      unsigned char fx_p = (event_b1 & 0x0F);
+
+      switch(fx)
+      {
+        case 0x0A:                      // 1.0xAy: Set Carrier volume
+          opl_write(flash_adlib_registers[11*i+2], fx_p << 2);
+          break;
+        case 0x0B:                      // 1.0xBy: Set Modulator volume
+          opl_write(flash_adlib_registers[11*i+3], fx_p << 2);
+          break;
+        case 0x0C:                      // 1.0xCy: Set both operators volume
+          opl_write(flash_adlib_registers[11*i+2], fx_p << 2);
+          opl_write(flash_adlib_registers[11*i+3], fx_p << 2);
+          break;
+//      case 0x0E:                      // 1.0xEy: ? (increase some value)
+        case 0x0F:                      // 1.0xFy: Set Speed
+          plr.speed = (fx_p + 1);
+          break;
+      }
+
+      if (event_b0)
+      {
+        // mute channel
+        opl_write(0xA0+i, adlib[0xA0+i]);
+        opl_write(0xB0+i, adlib[0xB0+i] & 0xDF);
+
+        // is note ?
+        if (event_b0 != 0x7F)
+        {
+          unsigned short note_encoded = flash_notes_encoded[event_b0];
+          unsigned short freq = flash_notes[(note_encoded >> 8) - 1];
+
+          flash_channel_freq = freq | ((note_encoded & 0xFF) << 10) | 0x2000;
+
+          opl_write(0xA0+i, flash_channel_freq & 0xFF);
+          opl_write(0xB0+i, flash_channel_freq >> 8);
+        }
+      }
+
+      if (fx == 0x01)                   // 1.0x1y: Fine Frequency Slide Up
+      {
+        flash_channel_freq += (fx_p << 1);
+
+        opl_write(0xA0+i, flash_channel_freq & 0xFF);
+        opl_write(0xB0+i, flash_channel_freq >> 8);
+      }
+      else if (fx == 0x02)              // 1.0x2y: Fine Frequency Slide Down
+      {
+        flash_channel_freq -= (fx_p << 1);
+
+        opl_write(0xA0+i, flash_channel_freq & 0xFF);
+        opl_write(0xB0+i, flash_channel_freq >> 8);
+      }
+    }
+  }
+
+  // next row
+  flash.pattern_pos++;
+
+  // end of pattern ?
+  if (flash.pattern_pos >= 0x40)
+  {
+    flash.pattern_pos = 0;
+
+    flash.order_pos++;
+
+    // end of module ?
+    if (tune[0x600+flash.order_pos] == 0xFF)
+    {
+      flash.order_pos = 0;
+
+      plr.looping = 1;
+    }
+  }
+}
+
+float CxadflashPlayer::xadplayer_getrefresh()
+{
+  return 17.5f;
+}
+
+std::string CxadflashPlayer::xadplayer_gettype()
+{
+  return std::string("xad: flash player");
+}
+
+unsigned int CxadflashPlayer::xadplayer_getinstruments()
+{
+  return 32;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/flash.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,57 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * [xad] FLASH player, by Riven the Mage <riven@ok.ru>
+ */
+
+#include "xad.h"
+
+class CxadflashPlayer: public CxadPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+  CxadflashPlayer(Copl *newopl): CxadPlayer(newopl)
+    { };
+
+protected:
+  struct
+  {
+    unsigned char   order_pos;
+    unsigned char   pattern_pos;
+  } flash;
+  //
+  bool		  xadplayer_load()
+    {
+      if(xad.fmt == FLASH)
+	return true;
+      else
+	return false;
+    }
+  void            xadplayer_rewind(int subsong);
+  void            xadplayer_update();
+  float           xadplayer_getrefresh();
+  std::string     xadplayer_gettype();
+  unsigned int    xadplayer_getinstruments();
+
+private:
+  static const unsigned char flash_adlib_registers[99];
+  static const unsigned short flash_notes_encoded[268];
+  static const unsigned short flash_notes[12];
+  static const unsigned char flash_default_instrument[8];
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/fmc.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,223 @@
+/*
+  Adplug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2003 Simon Peter <dn.tlp@gmx.net>, et al.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  fmc.cpp - FMC Loader by Riven the Mage <riven@ok.ru>
+*/
+
+#include "fmc.h"
+
+/* -------- Public Methods -------------------------------- */
+
+CPlayer *CfmcLoader::factory(Copl *newopl)
+{
+  return new CfmcLoader(newopl);
+}
+
+bool CfmcLoader::load(const std::string &filename, const CFileProvider &fp)
+{
+        binistream *f = fp.open(filename); if(!f) return false;
+	const unsigned char conv_fx[16] = {0,1,2,3,4,8,255,255,255,255,26,11,12,13,14,15};
+
+	int i,j,k,t=0;
+
+	// read header
+	f->readString(header.id, 4);
+	f->readString(header.title, 21);
+	header.numchan = f->readInt(1);
+
+	// 'FMC!' - signed ?
+	if (strncmp(header.id,"FMC!",4)) { fp.close(f); return false; }
+
+	// init CmodPlayer
+	realloc_instruments(32);
+	realloc_order(256);
+	realloc_patterns(64,64,header.numchan);
+	init_trackord();
+
+	// load order
+	for(i = 0; i < 256; i++) order[i] = f->readInt(1);
+
+	f->ignore(2);
+
+	// load instruments
+	for(i = 0; i < 32; i++) {
+	  instruments[i].synthesis = f->readInt(1);
+	  instruments[i].feedback = f->readInt(1);
+
+	  instruments[i].mod_attack = f->readInt(1);
+	  instruments[i].mod_decay = f->readInt(1);
+	  instruments[i].mod_sustain = f->readInt(1);
+	  instruments[i].mod_release = f->readInt(1);
+	  instruments[i].mod_volume = f->readInt(1);
+	  instruments[i].mod_ksl = f->readInt(1);
+	  instruments[i].mod_freq_multi = f->readInt(1);
+	  instruments[i].mod_waveform = f->readInt(1);
+	  instruments[i].mod_sustain_sound = f->readInt(1);
+	  instruments[i].mod_ksr = f->readInt(1);
+	  instruments[i].mod_vibrato = f->readInt(1);
+	  instruments[i].mod_tremolo = f->readInt(1);
+
+	  instruments[i].car_attack = f->readInt(1);
+	  instruments[i].car_decay = f->readInt(1);
+	  instruments[i].car_sustain = f->readInt(1);
+	  instruments[i].car_release = f->readInt(1);
+	  instruments[i].car_volume = f->readInt(1);
+	  instruments[i].car_ksl = f->readInt(1);
+	  instruments[i].car_freq_multi = f->readInt(1);
+	  instruments[i].car_waveform = f->readInt(1);
+	  instruments[i].car_sustain_sound = f->readInt(1);
+	  instruments[i].car_ksr = f->readInt(1);
+	  instruments[i].car_vibrato = f->readInt(1);
+	  instruments[i].car_tremolo = f->readInt(1);
+
+	  instruments[i].pitch_shift = f->readInt(1);
+
+	  f->readString(instruments[i].name, 21);
+	}
+
+	// load tracks
+	for (i=0;i<64;i++)
+	{
+	        if(f->ateof()) break;
+
+		for (j=0;j<header.numchan;j++)
+		{
+			for (k=0;k<64;k++)
+			{
+				fmc_event event;
+
+				// read event
+				event.byte0 = f->readInt(1);
+				event.byte1 = f->readInt(1);
+				event.byte2 = f->readInt(1);
+
+				// convert event
+				tracks[t][k].note = event.byte0 & 0x7F;
+				tracks[t][k].inst = ((event.byte0 & 0x80) >> 3) + (event.byte1 >> 4) + 1;
+				tracks[t][k].command = conv_fx[event.byte1 & 0x0F];
+				tracks[t][k].param1 = event.byte2 >> 4;
+				tracks[t][k].param2 = event.byte2 & 0x0F;
+
+				// fix effects
+				if (tracks[t][k].command == 0x0E) // 0x0E (14): Retrig
+					tracks[t][k].param1 = 3;
+				if (tracks[t][k].command == 0x1A) // 0x1A (26): Volume Slide
+					if (tracks[t][k].param1 > tracks[t][k].param2)
+					{
+						tracks[t][k].param1 -= tracks[t][k].param2;
+						tracks[t][k].param2 = 0;
+					}
+					else
+					{
+						tracks[t][k].param2 -= tracks[t][k].param1;
+						tracks[t][k].param1 = 0;
+					}
+			}
+
+			t++;
+		}
+	}
+	fp.close(f);
+
+	// convert instruments
+	for (i=0;i<31;i++)
+		buildinst(i);
+
+	// order length
+	for (i=0;i<256;i++)
+	{
+		if (order[i] >= 0xFE)
+		{
+			length = i;
+			break;
+		}
+	}
+
+	// data for Protracker
+	activechan = (0xffff >> (16 - header.numchan)) << (16 - header.numchan);
+	nop = t / header.numchan;
+	restartpos = 0;
+
+	// flags
+	flags = Faust;
+
+	rewind(0);
+
+	return true;
+}
+
+float CfmcLoader::getrefresh()
+{
+	return 50.0f;
+}
+
+std::string CfmcLoader::gettype()
+{
+	return std::string("Faust Music Creator");
+}
+
+std::string CfmcLoader::gettitle()
+{
+	return std::string(header.title);
+}
+
+std::string CfmcLoader::getinstrument(unsigned int n)
+{
+	return std::string(instruments[n].name);
+}
+
+unsigned int CfmcLoader::getinstruments()
+{
+	return 32;
+}
+
+/* -------- Private Methods ------------------------------- */
+
+void CfmcLoader::buildinst(unsigned char i)
+{
+	inst[i].data[0]   = ((instruments[i].synthesis & 1) ^ 1);
+	inst[i].data[0]  |= ((instruments[i].feedback & 7) << 1);
+
+	inst[i].data[3]   = ((instruments[i].mod_attack & 15) << 4);
+	inst[i].data[3]  |=  (instruments[i].mod_decay & 15);
+	inst[i].data[5]   = ((15 - (instruments[i].mod_sustain & 15)) << 4);
+	inst[i].data[5]  |=  (instruments[i].mod_release & 15);
+	inst[i].data[9]   =  (63 - (instruments[i].mod_volume & 63));
+	inst[i].data[9]  |= ((instruments[i].mod_ksl & 3) << 6);
+	inst[i].data[1]   =  (instruments[i].mod_freq_multi & 15);
+	inst[i].data[7]   =  (instruments[i].mod_waveform & 3);
+	inst[i].data[1]  |= ((instruments[i].mod_sustain_sound & 1) << 5);
+	inst[i].data[1]  |= ((instruments[i].mod_ksr & 1) << 4);
+	inst[i].data[1]  |= ((instruments[i].mod_vibrato & 1) << 6);
+	inst[i].data[1]  |= ((instruments[i].mod_tremolo & 1) << 7);
+
+	inst[i].data[4]   = ((instruments[i].car_attack & 15) << 4);
+	inst[i].data[4]  |=  (instruments[i].car_decay & 15);
+	inst[i].data[6]   = ((15 - (instruments[i].car_sustain & 15)) << 4);
+	inst[i].data[6]  |=  (instruments[i].car_release & 15);
+	inst[i].data[10]  =  (63 - (instruments[i].car_volume & 63));
+	inst[i].data[10] |= ((instruments[i].car_ksl & 3) << 6);
+	inst[i].data[2]   =  (instruments[i].car_freq_multi & 15);
+	inst[i].data[8]   =  (instruments[i].car_waveform & 3);
+	inst[i].data[2]  |= ((instruments[i].car_sustain_sound & 1) << 5);
+	inst[i].data[2]  |= ((instruments[i].car_ksr & 1) << 4);
+	inst[i].data[2]  |= ((instruments[i].car_vibrato & 1) << 6);
+	inst[i].data[2]  |= ((instruments[i].car_tremolo & 1) << 7);
+
+	inst[i].slide     =   instruments[i].pitch_shift;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/fmc.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,91 @@
+/*
+  Adplug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  fmc.h - FMC loader by Riven the Mage <riven@ok.ru>
+*/
+
+#include "protrack.h"
+
+class CfmcLoader: public CmodPlayer
+{
+	public:
+		static CPlayer *factory(Copl *newopl);
+
+		CfmcLoader(Copl *newopl) : CmodPlayer(newopl) { };
+
+		bool	load(const std::string &filename, const CFileProvider &fp);
+		float	getrefresh();
+
+		std::string	gettype();
+		std::string	gettitle();
+		std::string	getinstrument(unsigned int n);
+		unsigned int	getinstruments();
+
+	private:
+
+		struct fmc_event
+		{
+			unsigned char   byte0;
+			unsigned char   byte1;
+			unsigned char   byte2;
+		};
+
+		struct fmc_header
+		{
+			char            id[4];
+			char            title[21];
+			unsigned char   numchan;
+		} header;
+
+		struct fmc_instrument
+		{
+			unsigned char   synthesis;
+			unsigned char   feedback;
+
+			unsigned char   mod_attack;
+			unsigned char   mod_decay;
+			unsigned char   mod_sustain;
+			unsigned char   mod_release;
+			unsigned char   mod_volume;
+			unsigned char   mod_ksl;
+			unsigned char   mod_freq_multi;
+			unsigned char   mod_waveform;
+			unsigned char   mod_sustain_sound;
+			unsigned char   mod_ksr;
+			unsigned char   mod_vibrato;
+			unsigned char   mod_tremolo;
+			unsigned char   car_attack;
+			unsigned char   car_decay;
+			unsigned char   car_sustain;
+			unsigned char   car_release;
+			unsigned char   car_volume;
+			unsigned char   car_ksl;
+			unsigned char   car_freq_multi;
+			unsigned char   car_waveform;
+			unsigned char   car_sustain_sound;
+			unsigned char   car_ksr;
+			unsigned char   car_vibrato;
+			unsigned char   car_tremolo;
+
+			signed char     pitch_shift;
+
+			char            name[21];
+		} instruments[32];
+
+		void            buildinst(unsigned char i);
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/fmopl.c	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,1390 @@
+/*
+**
+** File: fmopl.c -- software implementation of FM sound generator
+**
+** Copyright (C) 1999,2000 Tatsuyuki Satoh , MultiArcadeMachineEmurator development
+**
+** Version 0.37a
+**
+*/
+
+/*
+	preliminary :
+	Problem :
+	note:
+*/
+
+/* This version of fmopl.c is a fork of the MAME one, relicensed under the LGPL.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define INLINE		__inline
+#define HAS_YM3812	1
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+//#include "driver.h"		/* use M.A.M.E. */
+#include "fmopl.h"
+
+#ifndef PI
+#define PI 3.14159265358979323846
+#endif
+
+/* -------------------- for debug --------------------- */
+/* #define OPL_OUTPUT_LOG */
+#ifdef OPL_OUTPUT_LOG
+static FILE *opl_dbg_fp = NULL;
+static FM_OPL *opl_dbg_opl[16];
+static int opl_dbg_maxchip,opl_dbg_chip;
+#endif
+
+/* -------------------- preliminary define section --------------------- */
+/* attack/decay rate time rate */
+#define OPL_ARRATE     141280  /* RATE 4 =  2826.24ms @ 3.6MHz */
+#define OPL_DRRATE    1956000  /* RATE 4 = 39280.64ms @ 3.6MHz */
+
+#define DELTAT_MIXING_LEVEL (1) /* DELTA-T ADPCM MIXING LEVEL */
+
+#define FREQ_BITS 24			/* frequency turn          */
+
+/* counter bits = 20 , octerve 7 */
+#define FREQ_RATE   (1<<(FREQ_BITS-20))
+#define TL_BITS    (FREQ_BITS+2)
+
+/* final output shift , limit minimum and maximum */
+#define OPL_OUTSB   (TL_BITS+3-16)		/* OPL output final shift 16bit */
+#define OPL_MAXOUT (0x7fff<<OPL_OUTSB)
+#define OPL_MINOUT (-0x8000<<OPL_OUTSB)
+
+/* -------------------- quality selection --------------------- */
+
+/* sinwave entries */
+/* used static memory = SIN_ENT * 4 (byte) */
+#define SIN_ENT 2048
+
+/* output level entries (envelope,sinwave) */
+/* envelope counter lower bits */
+#define ENV_BITS 16
+/* envelope output entries */
+#define EG_ENT   4096
+/* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
+/* used static  memory = EG_ENT*4 (byte)                     */
+
+#define EG_OFF   ((2*EG_ENT)<<ENV_BITS)  /* OFF          */
+#define EG_DED   EG_OFF
+#define EG_DST   (EG_ENT<<ENV_BITS)      /* DECAY  START */
+#define EG_AED   EG_DST
+#define EG_AST   0                       /* ATTACK START */
+
+#define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step  */
+
+/* LFO table entries */
+#define VIB_ENT 512
+#define VIB_SHIFT (32-9)
+#define AMS_ENT 512
+#define AMS_SHIFT (32-9)
+
+#define VIB_RATE 256
+
+/* -------------------- local defines , macros --------------------- */
+
+/* register number to channel number , slot offset */
+#define SLOT1 0
+#define SLOT2 1
+
+/* envelope phase */
+#define ENV_MOD_RR  0x00
+#define ENV_MOD_DR  0x01
+#define ENV_MOD_AR  0x02
+
+/* -------------------- tables --------------------- */
+static const int slot_array[32]=
+{
+	 0, 2, 4, 1, 3, 5,-1,-1,
+	 6, 8,10, 7, 9,11,-1,-1,
+	12,14,16,13,15,17,-1,-1,
+	-1,-1,-1,-1,-1,-1,-1,-1
+};
+
+/* key scale level */
+/* table is 3dB/OCT , DV converts this in TL step at 6dB/OCT */
+#define DV (EG_STEP/2)
+static const UINT32 KSL_TABLE[8*16]=
+{
+	/* OCT 0 */
+	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
+	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
+	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
+	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
+	/* OCT 1 */
+	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
+	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
+	 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV,
+	 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV,
+	/* OCT 2 */
+	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
+	 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV,
+	 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV,
+	 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV,
+	/* OCT 3 */
+	 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV,
+	 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV,
+	 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV,
+	 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV,
+	/* OCT 4 */
+	 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV,
+	 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV,
+	 9.000/DV, 9.750/DV,10.125/DV,10.500/DV,
+	10.875/DV,11.250/DV,11.625/DV,12.000/DV,
+	/* OCT 5 */
+	 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV,
+	 9.000/DV,10.125/DV,10.875/DV,11.625/DV,
+	12.000/DV,12.750/DV,13.125/DV,13.500/DV,
+	13.875/DV,14.250/DV,14.625/DV,15.000/DV,
+	/* OCT 6 */
+	 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV,
+	12.000/DV,13.125/DV,13.875/DV,14.625/DV,
+	15.000/DV,15.750/DV,16.125/DV,16.500/DV,
+	16.875/DV,17.250/DV,17.625/DV,18.000/DV,
+	/* OCT 7 */
+	 0.000/DV, 9.000/DV,12.000/DV,13.875/DV,
+	15.000/DV,16.125/DV,16.875/DV,17.625/DV,
+	18.000/DV,18.750/DV,19.125/DV,19.500/DV,
+	19.875/DV,20.250/DV,20.625/DV,21.000/DV
+};
+#undef DV
+
+/* sustain lebel table (3db per step) */
+/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
+#define SC(db) (db*((3/EG_STEP)*(1<<ENV_BITS)))+EG_DST
+static const INT32 SL_TABLE[16]={
+ SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
+ SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
+};
+#undef SC
+
+#define TL_MAX (EG_ENT*2) /* limit(tl + ksr + envelope) + sinwave */
+/* TotalLevel : 48 24 12  6  3 1.5 0.75 (dB) */
+/* TL_TABLE[ 0      to TL_MAX          ] : plus  section */
+/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
+static INT32 *TL_TABLE;
+
+/* pointers to TL_TABLE with sinwave output offset */
+static INT32 **SIN_TABLE;
+
+/* LFO table */
+static INT32 *AMS_TABLE;
+static INT32 *VIB_TABLE;
+
+/* envelope output curve table */
+/* attack + decay + OFF */
+static INT32 ENV_CURVE[2*EG_ENT+1];
+
+/* multiple table */
+#define ML 2
+static const UINT32 MUL_TABLE[16]= {
+/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
+   0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,
+   8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML
+};
+#undef ML
+
+/* dummy attack / decay rate ( when rate == 0 ) */
+static INT32 RATE_0[16]=
+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+/* -------------------- static state --------------------- */
+
+/* lock level of common table */
+static int num_lock = 0;
+
+/* work table */
+static void *cur_chip = NULL;	/* current chip point */
+/* currenct chip state */
+/* static OPLSAMPLE  *bufL,*bufR; */
+static OPL_CH *S_CH;
+static OPL_CH *E_CH;
+OPL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;
+
+static INT32 outd[1];
+static INT32 ams;
+static INT32 vib;
+INT32  *ams_table;
+INT32  *vib_table;
+static INT32 amsIncr;
+static INT32 vibIncr;
+static INT32 feedback2;		/* connect for SLOT 2 */
+
+/* log output level */
+#define LOG_ERR  3      /* ERROR       */
+#define LOG_WAR  2      /* WARNING     */
+#define LOG_INF  1      /* INFORMATION */
+
+//#define LOG_LEVEL LOG_INF
+#define LOG_LEVEL	LOG_ERR
+
+//#define LOG(n,x) if( (n)>=LOG_LEVEL ) logerror x
+#define LOG(n,x)
+
+/* --------------------- subroutines  --------------------- */
+
+INLINE int Limit( int val, int max, int min ) {
+	if ( val > max )
+		val = max;
+	else if ( val < min )
+		val = min;
+
+	return val;
+}
+
+/* status set and IRQ handling */
+INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag)
+{
+	/* set status flag */
+	OPL->status |= flag;
+	if(!(OPL->status & 0x80))
+	{
+		if(OPL->status & OPL->statusmask)
+		{	/* IRQ on */
+			OPL->status |= 0x80;
+			/* callback user interrupt handler (IRQ is OFF to ON) */
+			if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1);
+		}
+	}
+}
+
+/* status reset and IRQ handling */
+INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
+{
+	/* reset status flag */
+	OPL->status &=~flag;
+	if((OPL->status & 0x80))
+	{
+		if (!(OPL->status & OPL->statusmask) )
+		{
+			OPL->status &= 0x7f;
+			/* callback user interrupt handler (IRQ is ON to OFF) */
+			if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
+		}
+	}
+}
+
+/* IRQ mask set */
+INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
+{
+	OPL->statusmask = flag;
+	/* IRQ handling check */
+	OPL_STATUS_SET(OPL,0);
+	OPL_STATUS_RESET(OPL,0);
+}
+
+/* ----- key on  ----- */
+INLINE void OPL_KEYON(OPL_SLOT *SLOT)
+{
+	/* sin wave restart */
+	SLOT->Cnt = 0;
+	/* set attack */
+	SLOT->evm = ENV_MOD_AR;
+	SLOT->evs = SLOT->evsa;
+	SLOT->evc = EG_AST;
+	SLOT->eve = EG_AED;
+}
+/* ----- key off ----- */
+INLINE void OPL_KEYOFF(OPL_SLOT *SLOT)
+{
+	if( SLOT->evm > ENV_MOD_RR)
+	{
+		/* set envelope counter from envleope output */
+		SLOT->evm = ENV_MOD_RR;
+		if( !(SLOT->evc&EG_DST) )
+			//SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
+			SLOT->evc = EG_DST;
+		SLOT->eve = EG_DED;
+		SLOT->evs = SLOT->evsr;
+	}
+}
+
+/* ---------- calcrate Envelope Generator & Phase Generator ---------- */
+/* return : envelope output */
+INLINE UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT )
+{
+	/* calcrate envelope generator */
+	if( (SLOT->evc+=SLOT->evs) >= SLOT->eve )
+	{
+		switch( SLOT->evm ){
+		case ENV_MOD_AR: /* ATTACK -> DECAY1 */
+			/* next DR */
+			SLOT->evm = ENV_MOD_DR;
+			SLOT->evc = EG_DST;
+			SLOT->eve = SLOT->SL;
+			SLOT->evs = SLOT->evsd;
+			break;
+		case ENV_MOD_DR: /* DECAY -> SL or RR */
+			SLOT->evc = SLOT->SL;
+			SLOT->eve = EG_DED;
+			if(SLOT->eg_typ)
+			{
+				SLOT->evs = 0;
+			}
+			else
+			{
+				SLOT->evm = ENV_MOD_RR;
+				SLOT->evs = SLOT->evsr;
+			}
+			break;
+		case ENV_MOD_RR: /* RR -> OFF */
+			SLOT->evc = EG_OFF;
+			SLOT->eve = EG_OFF+1;
+			SLOT->evs = 0;
+			break;
+		}
+	}
+	/* calcrate envelope */
+	return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]+(SLOT->ams ? ams : 0);
+}
+
+/* set algorythm connection */
+static void set_algorythm( OPL_CH *CH)
+{
+	INT32 *carrier = &outd[0];
+	CH->connect1 = CH->CON ? carrier : &feedback2;
+	CH->connect2 = carrier;
+}
+
+/* ---------- frequency counter for operater update ---------- */
+INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
+{
+	int ksr;
+
+	/* frequency step counter */
+	SLOT->Incr = CH->fc * SLOT->mul;
+	ksr = CH->kcode >> SLOT->KSR;
+
+	if( SLOT->ksr != ksr )
+	{
+		SLOT->ksr = ksr;
+		/* attack , decay rate recalcration */
+		SLOT->evsa = SLOT->AR[ksr];
+		SLOT->evsd = SLOT->DR[ksr];
+		SLOT->evsr = SLOT->RR[ksr];
+	}
+	SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
+}
+
+/* set multi,am,vib,EG-TYP,KSR,mul */
+INLINE void set_mul(FM_OPL *OPL,int slot,int v)
+{
+	OPL_CH   *CH   = &OPL->P_CH[slot/2];
+	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
+
+	SLOT->mul    = MUL_TABLE[v&0x0f];
+	SLOT->KSR    = (v&0x10) ? 0 : 2;
+	SLOT->eg_typ = (v&0x20)>>5;
+	SLOT->vib    = (v&0x40);
+	SLOT->ams    = (v&0x80);
+	CALC_FCSLOT(CH,SLOT);
+}
+
+/* set ksl & tl */
+INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v)
+{
+	OPL_CH   *CH   = &OPL->P_CH[slot/2];
+	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
+	int ksl = v>>6; /* 0 / 1.5 / 3 / 6 db/OCT */
+
+	SLOT->ksl = ksl ? 3-ksl : 31;
+	SLOT->TL  = (v&0x3f)*(0.75/EG_STEP); /* 0.75db step */
+
+	if( !(OPL->mode&0x80) )
+	{	/* not CSM latch total level */
+		SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
+	}
+}
+
+/* set attack rate & decay rate  */
+INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v)
+{
+	OPL_CH   *CH   = &OPL->P_CH[slot/2];
+	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
+	int ar = v>>4;
+	int dr = v&0x0f;
+
+	SLOT->AR = ar ? &OPL->AR_TABLE[ar<<2] : RATE_0;
+	SLOT->evsa = SLOT->AR[SLOT->ksr];
+	if( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa;
+
+	SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0;
+	SLOT->evsd = SLOT->DR[SLOT->ksr];
+	if( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd;
+}
+
+/* set sustain level & release rate */
+INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v)
+{
+	OPL_CH   *CH   = &OPL->P_CH[slot/2];
+	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
+	int sl = v>>4;
+	int rr = v & 0x0f;
+
+	SLOT->SL = SL_TABLE[sl];
+	if( SLOT->evm == ENV_MOD_DR ) SLOT->eve = SLOT->SL;
+	SLOT->RR = &OPL->DR_TABLE[rr<<2];
+	SLOT->evsr = SLOT->RR[SLOT->ksr];
+	if( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr;
+}
+
+/* operator output calcrator */
+#define OP_OUT(slot,env,con)   slot->wavetable[((slot->Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env]
+/* ---------- calcrate one of channel ---------- */
+INLINE void OPL_CALC_CH( OPL_CH *CH )
+{
+	UINT32 env_out;
+	OPL_SLOT *SLOT;
+
+	feedback2 = 0;
+	/* SLOT 1 */
+	SLOT = &CH->SLOT[SLOT1];
+	env_out=OPL_CALC_SLOT(SLOT);
+	if( env_out < EG_ENT-1 )
+	{
+		/* PG */
+		if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
+		else          SLOT->Cnt += SLOT->Incr;
+		/* connectoion */
+		if(CH->FB)
+		{
+			int feedback1 = (CH->op1_out[0]+CH->op1_out[1])>>CH->FB;
+			CH->op1_out[1] = CH->op1_out[0];
+			*CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
+		}
+		else
+		{
+			*CH->connect1 += OP_OUT(SLOT,env_out,0);
+		}
+	}else
+	{
+		CH->op1_out[1] = CH->op1_out[0];
+		CH->op1_out[0] = 0;
+	}
+	/* SLOT 2 */
+	SLOT = &CH->SLOT[SLOT2];
+	env_out=OPL_CALC_SLOT(SLOT);
+	if( env_out < EG_ENT-1 )
+	{
+		/* PG */
+		if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
+		else          SLOT->Cnt += SLOT->Incr;
+		/* connectoion */
+		outd[0] += OP_OUT(SLOT,env_out, feedback2);
+	}
+}
+
+/* ---------- calcrate rythm block ---------- */
+#define WHITE_NOISE_db 6.0
+INLINE void OPL_CALC_RH( OPL_CH *CH )
+{
+	UINT32 env_tam,env_sd,env_top,env_hh;
+	int whitenoise = (rand()&1)*(WHITE_NOISE_db/EG_STEP);
+	INT32 tone8;
+
+	OPL_SLOT *SLOT;
+	int env_out;
+
+	/* BD : same as FM serial mode and output level is large */
+	feedback2 = 0;
+	/* SLOT 1 */
+	SLOT = &CH[6].SLOT[SLOT1];
+	env_out=OPL_CALC_SLOT(SLOT);
+	if( env_out < EG_ENT-1 )
+	{
+		/* PG */
+		if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
+		else          SLOT->Cnt += SLOT->Incr;
+		/* connectoion */
+		if(CH[6].FB)
+		{
+			int feedback1 = (CH[6].op1_out[0]+CH[6].op1_out[1])>>CH[6].FB;
+			CH[6].op1_out[1] = CH[6].op1_out[0];
+			feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
+		}
+		else
+		{
+			feedback2 = OP_OUT(SLOT,env_out,0);
+		}
+	}else
+	{
+		feedback2 = 0;
+		CH[6].op1_out[1] = CH[6].op1_out[0];
+		CH[6].op1_out[0] = 0;
+	}
+	/* SLOT 2 */
+	SLOT = &CH[6].SLOT[SLOT2];
+	env_out=OPL_CALC_SLOT(SLOT);
+	if( env_out < EG_ENT-1 )
+	{
+		/* PG */
+		if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
+		else          SLOT->Cnt += SLOT->Incr;
+		/* connectoion */
+		outd[0] += OP_OUT(SLOT,env_out, feedback2)*2;
+	}
+
+	// SD  (17) = mul14[fnum7] + white noise
+	// TAM (15) = mul15[fnum8]
+	// TOP (18) = fnum6(mul18[fnum8]+whitenoise)
+	// HH  (14) = fnum7(mul18[fnum8]+whitenoise) + white noise
+	env_sd =OPL_CALC_SLOT(SLOT7_2) + whitenoise;
+	env_tam=OPL_CALC_SLOT(SLOT8_1);
+	env_top=OPL_CALC_SLOT(SLOT8_2);
+	env_hh =OPL_CALC_SLOT(SLOT7_1) + whitenoise;
+
+	/* PG */
+	if(SLOT7_1->vib) SLOT7_1->Cnt += (2*SLOT7_1->Incr*vib/VIB_RATE);
+	else             SLOT7_1->Cnt += 2*SLOT7_1->Incr;
+	if(SLOT7_2->vib) SLOT7_2->Cnt += ((CH[7].fc*8)*vib/VIB_RATE);
+	else             SLOT7_2->Cnt += (CH[7].fc*8);
+	if(SLOT8_1->vib) SLOT8_1->Cnt += (SLOT8_1->Incr*vib/VIB_RATE);
+	else             SLOT8_1->Cnt += SLOT8_1->Incr;
+	if(SLOT8_2->vib) SLOT8_2->Cnt += ((CH[8].fc*48)*vib/VIB_RATE);
+	else             SLOT8_2->Cnt += (CH[8].fc*48);
+
+	tone8 = OP_OUT(SLOT8_2,whitenoise,0 );
+
+	/* SD */
+	if( env_sd < EG_ENT-1 )
+		outd[0] += OP_OUT(SLOT7_1,env_sd, 0)*8;
+	/* TAM */
+	if( env_tam < EG_ENT-1 )
+		outd[0] += OP_OUT(SLOT8_1,env_tam, 0)*2;
+	/* TOP-CY */
+	if( env_top < EG_ENT-1 )
+		outd[0] += OP_OUT(SLOT7_2,env_top,tone8)*2;
+	/* HH */
+	if( env_hh  < EG_ENT-1 )
+		outd[0] += OP_OUT(SLOT7_2,env_hh,tone8)*2;
+}
+
+/* ----------- initialize time tabls ----------- */
+static void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE )
+{
+	int i;
+	double rate;
+
+	/* make attack rate & decay rate tables */
+	for (i = 0;i < 4;i++) OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0;
+	for (i = 4;i <= 60;i++){
+		rate  = OPL->freqbase;						/* frequency rate */
+		if( i < 60 ) rate *= 1.0+(i&3)*0.25;		/* b0-1 : x1 , x1.25 , x1.5 , x1.75 */
+		rate *= 1<<((i>>2)-1);						/* b2-5 : shift bit */
+		rate *= (double)(EG_ENT<<ENV_BITS);
+		OPL->AR_TABLE[i] = rate / ARRATE;
+		OPL->DR_TABLE[i] = rate / DRRATE;
+	}
+	for (i = 60;i < 76;i++)
+	{
+		OPL->AR_TABLE[i] = EG_AED-1;
+		OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
+	}
+#if 0
+	for (i = 0;i < 64 ;i++){	/* make for overflow area */
+		LOG(LOG_WAR,("rate %2d , ar %f ms , dr %f ms \n",i,
+			((double)(EG_ENT<<ENV_BITS) / OPL->AR_TABLE[i]) * (1000.0 / OPL->rate),
+			((double)(EG_ENT<<ENV_BITS) / OPL->DR_TABLE[i]) * (1000.0 / OPL->rate) ));
+	}
+#endif
+}
+
+/* ---------- generic table initialize ---------- */
+static int OPLOpenTable( void )
+{
+	int s,t;
+	double rate;
+	int i,j;
+	double pom;
+
+	/* allocate dynamic tables */
+	if( (TL_TABLE = malloc(TL_MAX*2*sizeof(INT32))) == NULL)
+		return 0;
+	if( (SIN_TABLE = malloc(SIN_ENT*4 *sizeof(INT32 *))) == NULL)
+	{
+		free(TL_TABLE);
+		return 0;
+	}
+	if( (AMS_TABLE = malloc(AMS_ENT*2 *sizeof(INT32))) == NULL)
+	{
+		free(TL_TABLE);
+		free(SIN_TABLE);
+		return 0;
+	}
+	if( (VIB_TABLE = malloc(VIB_ENT*2 *sizeof(INT32))) == NULL)
+	{
+		free(TL_TABLE);
+		free(SIN_TABLE);
+		free(AMS_TABLE);
+		return 0;
+	}
+	/* make total level table */
+	for (t = 0;t < EG_ENT-1 ;t++){
+		rate = ((1<<TL_BITS)-1)/pow(10,EG_STEP*t/20);	/* dB -> voltage */
+		TL_TABLE[       t] =  (int)rate;
+		TL_TABLE[TL_MAX+t] = -TL_TABLE[t];
+/*		LOG(LOG_INF,("TotalLevel(%3d) = %x\n",t,TL_TABLE[t]));*/
+	}
+	/* fill volume off area */
+	for ( t = EG_ENT-1; t < TL_MAX ;t++){
+		TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0;
+	}
+
+	/* make sinwave table (total level offet) */
+	/* degree 0 = degree 180                   = off */
+	SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2]         = &TL_TABLE[EG_ENT-1];
+	for (s = 1;s <= SIN_ENT/4;s++){
+		pom = sin(2*PI*s/SIN_ENT); /* sin     */
+		pom = 20*log10(1/pom);	   /* decibel */
+		j = pom / EG_STEP;         /* TL_TABLE steps */
+
+        /* degree 0   -  90    , degree 180 -  90 : plus section */
+		SIN_TABLE[          s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j];
+        /* degree 180 - 270    , degree 360 - 270 : minus section */
+		SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT  -s] = &TL_TABLE[TL_MAX+j];
+/*		LOG(LOG_INF,("sin(%3d) = %f:%f db\n",s,pom,(double)j * EG_STEP));*/
+	}
+	for (s = 0;s < SIN_ENT;s++)
+	{
+		SIN_TABLE[SIN_ENT*1+s] = s<(SIN_ENT/2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];
+		SIN_TABLE[SIN_ENT*2+s] = SIN_TABLE[s % (SIN_ENT/2)];
+		SIN_TABLE[SIN_ENT*3+s] = (s/(SIN_ENT/4))&1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT*2+s];
+	}
+
+	/* envelope counter -> envelope output table */
+	for (i=0; i<EG_ENT; i++)
+	{
+		/* ATTACK curve */
+		pom = pow( ((double)(EG_ENT-1-i)/EG_ENT) , 8 ) * EG_ENT;
+		/* if( pom >= EG_ENT ) pom = EG_ENT-1; */
+		ENV_CURVE[i] = (int)pom;
+		/* DECAY ,RELEASE curve */
+		ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i;
+	}
+	/* off */
+	ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1;
+	/* make LFO ams table */
+	for (i=0; i<AMS_ENT; i++)
+	{
+		pom = (1.0+sin(2*PI*i/AMS_ENT))/2; /* sin */
+		AMS_TABLE[i]         = (1.0/EG_STEP)*pom; /* 1dB   */
+		AMS_TABLE[AMS_ENT+i] = (4.8/EG_STEP)*pom; /* 4.8dB */
+	}
+	/* make LFO vibrate table */
+	for (i=0; i<VIB_ENT; i++)
+	{
+		/* 100cent = 1seminote = 6% ?? */
+		pom = (double)VIB_RATE*0.06*sin(2*PI*i/VIB_ENT); /* +-100sect step */
+		VIB_TABLE[i]         = VIB_RATE + (pom*0.07); /* +- 7cent */
+		VIB_TABLE[VIB_ENT+i] = VIB_RATE + (pom*0.14); /* +-14cent */
+		/* LOG(LOG_INF,("vib %d=%d\n",i,VIB_TABLE[VIB_ENT+i])); */
+	}
+	return 1;
+}
+
+
+static void OPLCloseTable( void )
+{
+	free(TL_TABLE);
+	free(SIN_TABLE);
+	free(AMS_TABLE);
+	free(VIB_TABLE);
+}
+
+/* CSM Key Controll */
+INLINE void CSMKeyControll(OPL_CH *CH)
+{
+	OPL_SLOT *slot1 = &CH->SLOT[SLOT1];
+	OPL_SLOT *slot2 = &CH->SLOT[SLOT2];
+	/* all key off */
+	OPL_KEYOFF(slot1);
+	OPL_KEYOFF(slot2);
+	/* total level latch */
+	slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
+	slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
+	/* key on */
+	CH->op1_out[0] = CH->op1_out[1] = 0;
+	OPL_KEYON(slot1);
+	OPL_KEYON(slot2);
+}
+
+/* ---------- opl initialize ---------- */
+static void OPL_initalize(FM_OPL *OPL)
+{
+	int fn;
+
+	/* frequency base */
+	OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72  : 0;
+	/* Timer base time */
+	OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 );
+	/* make time tables */
+	init_timetables( OPL , OPL_ARRATE , OPL_DRRATE );
+	/* make fnumber -> increment counter table */
+	for( fn=0 ; fn < 1024 ; fn++ )
+	{
+		OPL->FN_TABLE[fn] = OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2;
+	}
+	/* LFO freq.table */
+	OPL->amsIncr = OPL->rate ? (double)AMS_ENT*(1<<AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0;
+	OPL->vibIncr = OPL->rate ? (double)VIB_ENT*(1<<VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0;
+}
+
+/* ---------- write a OPL registers ---------- */
+static void OPLWriteReg(FM_OPL *OPL, int r, int v)
+{
+	OPL_CH *CH;
+	int slot;
+	int block_fnum;
+
+	switch(r&0xe0)
+	{
+	case 0x00: /* 00-1f:controll */
+		switch(r&0x1f)
+		{
+		case 0x01:
+			/* wave selector enable */
+			if(OPL->type&OPL_TYPE_WAVESEL)
+			{
+				OPL->wavesel = v&0x20;
+				if(!OPL->wavesel)
+				{
+					/* preset compatible mode */
+					int c;
+					for(c=0;c<OPL->max_ch;c++)
+					{
+						OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
+						OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
+					}
+				}
+			}
+			return;
+		case 0x02:	/* Timer 1 */
+			OPL->T[0] = (256-v)*4;
+			break;
+		case 0x03:	/* Timer 2 */
+			OPL->T[1] = (256-v)*16;
+			return;
+		case 0x04:	/* IRQ clear / mask and Timer enable */
+			if(v&0x80)
+			{	/* IRQ flag clear */
+				OPL_STATUS_RESET(OPL,0x7f);
+			}
+			else
+			{	/* set IRQ mask ,timer enable*/
+				UINT8 st1 = v&1;
+				UINT8 st2 = (v>>1)&1;
+				/* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
+				OPL_STATUS_RESET(OPL,v&0x78);
+				OPL_STATUSMASK_SET(OPL,((~v)&0x78)|0x01);
+				/* timer 2 */
+				if(OPL->st[1] != st2)
+				{
+					double interval = st2 ? (double)OPL->T[1]*OPL->TimerBase : 0.0;
+					OPL->st[1] = st2;
+					if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+1,interval);
+				}
+				/* timer 1 */
+				if(OPL->st[0] != st1)
+				{
+					double interval = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0;
+					OPL->st[0] = st1;
+					if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+0,interval);
+				}
+			}
+			return;
+#if BUILD_Y8950
+		case 0x06:		/* Key Board OUT */
+			if(OPL->type&OPL_TYPE_KEYBOARD)
+			{
+				if(OPL->keyboardhandler_w)
+					OPL->keyboardhandler_w(OPL->keyboard_param,v);
+				else
+					LOG(LOG_WAR,("OPL:write unmapped KEYBOARD port\n"));
+			}
+			return;
+		case 0x07:	/* DELTA-T controll : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */
+			if(OPL->type&OPL_TYPE_ADPCM)
+				YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
+			return;
+		case 0x08:	/* MODE,DELTA-T : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */
+			OPL->mode = v;
+			v&=0x1f;	/* for DELTA-T unit */
+		case 0x09:		/* START ADD */
+		case 0x0a:
+		case 0x0b:		/* STOP ADD  */
+		case 0x0c:
+		case 0x0d:		/* PRESCALE   */
+		case 0x0e:
+		case 0x0f:		/* ADPCM data */
+		case 0x10: 		/* DELTA-N    */
+		case 0x11: 		/* DELTA-N    */
+		case 0x12: 		/* EG-CTRL    */
+			if(OPL->type&OPL_TYPE_ADPCM)
+				YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
+			return;
+#if 0
+		case 0x15:		/* DAC data    */
+		case 0x16:
+		case 0x17:		/* SHIFT    */
+			return;
+		case 0x18:		/* I/O CTRL (Direction) */
+			if(OPL->type&OPL_TYPE_IO)
+				OPL->portDirection = v&0x0f;
+			return;
+		case 0x19:		/* I/O DATA */
+			if(OPL->type&OPL_TYPE_IO)
+			{
+				OPL->portLatch = v;
+				if(OPL->porthandler_w)
+					OPL->porthandler_w(OPL->port_param,v&OPL->portDirection);
+			}
+			return;
+		case 0x1a:		/* PCM data */
+			return;
+#endif
+#endif
+		}
+		break;
+	case 0x20:	/* am,vib,ksr,eg type,mul */
+		slot = slot_array[r&0x1f];
+		if(slot == -1) return;
+		set_mul(OPL,slot,v);
+		return;
+	case 0x40:
+		slot = slot_array[r&0x1f];
+		if(slot == -1) return;
+		set_ksl_tl(OPL,slot,v);
+		return;
+	case 0x60:
+		slot = slot_array[r&0x1f];
+		if(slot == -1) return;
+		set_ar_dr(OPL,slot,v);
+		return;
+	case 0x80:
+		slot = slot_array[r&0x1f];
+		if(slot == -1) return;
+		set_sl_rr(OPL,slot,v);
+		return;
+	case 0xa0:
+		switch(r)
+		{
+		case 0xbd:
+			/* amsep,vibdep,r,bd,sd,tom,tc,hh */
+			{
+			UINT8 rkey = OPL->rythm^v;
+			OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0];
+			OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0];
+			OPL->rythm  = v&0x3f;
+			if(OPL->rythm&0x20)
+			{
+#if 0
+				usrintf_showmessage("OPL Rythm mode select");
+#endif
+				/* BD key on/off */
+				if(rkey&0x10)
+				{
+					if(v&0x10)
+					{
+						OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0;
+						OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]);
+						OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]);
+					}
+					else
+					{
+						OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]);
+						OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]);
+					}
+				}
+				/* SD key on/off */
+				if(rkey&0x08)
+				{
+					if(v&0x08) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]);
+					else       OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]);
+				}/* TAM key on/off */
+				if(rkey&0x04)
+				{
+					if(v&0x04) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]);
+					else       OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]);
+				}
+				/* TOP-CY key on/off */
+				if(rkey&0x02)
+				{
+					if(v&0x02) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);
+					else       OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);
+				}
+				/* HH key on/off */
+				if(rkey&0x01)
+				{
+					if(v&0x01) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]);
+					else       OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]);
+				}
+			}
+			}
+			return;
+		}
+		/* keyon,block,fnum */
+		if( (r&0x0f) > 8) return;
+		CH = &OPL->P_CH[r&0x0f];
+		if(!(r&0x10))
+		{	/* a0-a8 */
+			block_fnum  = (CH->block_fnum&0x1f00) | v;
+		}
+		else
+		{	/* b0-b8 */
+			int keyon = (v>>5)&1;
+			block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);
+			if(CH->keyon != keyon)
+			{
+				if( (CH->keyon=keyon) )
+				{
+					CH->op1_out[0] = CH->op1_out[1] = 0;
+					OPL_KEYON(&CH->SLOT[SLOT1]);
+					OPL_KEYON(&CH->SLOT[SLOT2]);
+				}
+				else
+				{
+					OPL_KEYOFF(&CH->SLOT[SLOT1]);
+					OPL_KEYOFF(&CH->SLOT[SLOT2]);
+				}
+			}
+		}
+		/* update */
+		if(CH->block_fnum != block_fnum)
+		{
+			int blockRv = 7-(block_fnum>>10);
+			int fnum   = block_fnum&0x3ff;
+			CH->block_fnum = block_fnum;
+
+			CH->ksl_base = KSL_TABLE[block_fnum>>6];
+			CH->fc = OPL->FN_TABLE[fnum]>>blockRv;
+			CH->kcode = CH->block_fnum>>9;
+			if( (OPL->mode&0x40) && CH->block_fnum&0x100) CH->kcode |=1;
+			CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
+			CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
+		}
+		return;
+	case 0xc0:
+		/* FB,C */
+		if( (r&0x0f) > 8) return;
+		CH = &OPL->P_CH[r&0x0f];
+		{
+		int feedback = (v>>1)&7;
+		CH->FB   = feedback ? (8+1) - feedback : 0;
+		CH->CON = v&1;
+		set_algorythm(CH);
+		}
+		return;
+	case 0xe0: /* wave type */
+		slot = slot_array[r&0x1f];
+		if(slot == -1) return;
+		CH = &OPL->P_CH[slot/2];
+		if(OPL->wavesel)
+		{
+			/* LOG(LOG_INF,("OPL SLOT %d wave select %d\n",slot,v&3)); */
+			CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v&0x03)*SIN_ENT];
+		}
+		return;
+	}
+}
+
+/* lock/unlock for common table */
+static int OPL_LockTable(void)
+{
+	num_lock++;
+	if(num_lock>1) return 0;
+	/* first time */
+	cur_chip = NULL;
+	/* allocate total level table (128kb space) */
+	if( !OPLOpenTable() )
+	{
+		num_lock--;
+		return -1;
+	}
+	return 0;
+}
+
+static void OPL_UnLockTable(void)
+{
+	if(num_lock) num_lock--;
+	if(num_lock) return;
+	/* last time */
+	cur_chip = NULL;
+	OPLCloseTable();
+}
+
+#if (BUILD_YM3812 || BUILD_YM3526)
+/*******************************************************************************/
+/*		YM3812 local section                                                   */
+/*******************************************************************************/
+
+/* ---------- update one of chip ----------- */
+void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
+{
+    int i;
+	int data;
+	OPLSAMPLE *buf = buffer;
+	UINT32 amsCnt  = OPL->amsCnt;
+	UINT32 vibCnt  = OPL->vibCnt;
+	UINT8 rythm = OPL->rythm&0x20;
+	OPL_CH *CH,*R_CH;
+
+	if( (void *)OPL != cur_chip ){
+		cur_chip = (void *)OPL;
+		/* channel pointers */
+		S_CH = OPL->P_CH;
+		E_CH = &S_CH[9];
+		/* rythm slot */
+		SLOT7_1 = &S_CH[7].SLOT[SLOT1];
+		SLOT7_2 = &S_CH[7].SLOT[SLOT2];
+		SLOT8_1 = &S_CH[8].SLOT[SLOT1];
+		SLOT8_2 = &S_CH[8].SLOT[SLOT2];
+		/* LFO state */
+		amsIncr = OPL->amsIncr;
+		vibIncr = OPL->vibIncr;
+		ams_table = OPL->ams_table;
+		vib_table = OPL->vib_table;
+	}
+	R_CH = rythm ? &S_CH[6] : E_CH;
+    for( i=0; i < length ; i++ )
+	{
+		/*            channel A         channel B         channel C      */
+		/* LFO */
+		ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
+		vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
+		outd[0] = 0;
+		/* FM part */
+		for(CH=S_CH ; CH < R_CH ; CH++)
+			OPL_CALC_CH(CH);
+		/* Rythn part */
+		if(rythm)
+			OPL_CALC_RH(S_CH);
+		/* limit check */
+		data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
+		/* store to sound buffer */
+		buf[i] = data >> OPL_OUTSB;
+	}
+
+	OPL->amsCnt = amsCnt;
+	OPL->vibCnt = vibCnt;
+#ifdef OPL_OUTPUT_LOG
+	if(opl_dbg_fp)
+	{
+		for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++)
+			if( opl_dbg_opl[opl_dbg_chip] == OPL) break;
+		fprintf(opl_dbg_fp,"%c%c%c",0x20+opl_dbg_chip,length&0xff,length/256);
+	}
+#endif
+}
+#endif /* (BUILD_YM3812 || BUILD_YM3526) */
+
+#if BUILD_Y8950
+
+void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
+{
+    int i;
+	int data;
+	OPLSAMPLE *buf = buffer;
+	UINT32 amsCnt  = OPL->amsCnt;
+	UINT32 vibCnt  = OPL->vibCnt;
+	UINT8 rythm = OPL->rythm&0x20;
+	OPL_CH *CH,*R_CH;
+	YM_DELTAT *DELTAT = OPL->deltat;
+
+	/* setup DELTA-T unit */
+	YM_DELTAT_DECODE_PRESET(DELTAT);
+
+	if( (void *)OPL != cur_chip ){
+		cur_chip = (void *)OPL;
+		/* channel pointers */
+		S_CH = OPL->P_CH;
+		E_CH = &S_CH[9];
+		/* rythm slot */
+		SLOT7_1 = &S_CH[7].SLOT[SLOT1];
+		SLOT7_2 = &S_CH[7].SLOT[SLOT2];
+		SLOT8_1 = &S_CH[8].SLOT[SLOT1];
+		SLOT8_2 = &S_CH[8].SLOT[SLOT2];
+		/* LFO state */
+		amsIncr = OPL->amsIncr;
+		vibIncr = OPL->vibIncr;
+		ams_table = OPL->ams_table;
+		vib_table = OPL->vib_table;
+	}
+	R_CH = rythm ? &S_CH[6] : E_CH;
+    for( i=0; i < length ; i++ )
+	{
+		/*            channel A         channel B         channel C      */
+		/* LFO */
+		ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
+		vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
+		outd[0] = 0;
+		/* deltaT ADPCM */
+		if( DELTAT->portstate )
+			YM_DELTAT_ADPCM_CALC(DELTAT);
+		/* FM part */
+		for(CH=S_CH ; CH < R_CH ; CH++)
+			OPL_CALC_CH(CH);
+		/* Rythn part */
+		if(rythm)
+			OPL_CALC_RH(S_CH);
+		/* limit check */
+		data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
+		/* store to sound buffer */
+		buf[i] = data >> OPL_OUTSB;
+	}
+	OPL->amsCnt = amsCnt;
+	OPL->vibCnt = vibCnt;
+	/* deltaT START flag */
+	if( !DELTAT->portstate )
+		OPL->status &= 0xfe;
+}
+#endif
+
+/* ---------- reset one of chip ---------- */
+void OPLResetChip(FM_OPL *OPL)
+{
+	int c,s;
+	int i;
+
+	/* reset chip */
+	OPL->mode   = 0;	/* normal mode */
+	OPL_STATUS_RESET(OPL,0x7f);
+	/* reset with register write */
+	OPLWriteReg(OPL,0x01,0); /* wabesel disable */
+	OPLWriteReg(OPL,0x02,0); /* Timer1 */
+	OPLWriteReg(OPL,0x03,0); /* Timer2 */
+	OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */
+	for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);
+	/* reset OPerator paramater */
+	for( c = 0 ; c < OPL->max_ch ; c++ )
+	{
+		OPL_CH *CH = &OPL->P_CH[c];
+		/* OPL->P_CH[c].PAN = OPN_CENTER; */
+		for(s = 0 ; s < 2 ; s++ )
+		{
+			/* wave table */
+			CH->SLOT[s].wavetable = &SIN_TABLE[0];
+			/* CH->SLOT[s].evm = ENV_MOD_RR; */
+			CH->SLOT[s].evc = EG_OFF;
+			CH->SLOT[s].eve = EG_OFF+1;
+			CH->SLOT[s].evs = 0;
+		}
+	}
+#if BUILD_Y8950
+	if(OPL->type&OPL_TYPE_ADPCM)
+	{
+		YM_DELTAT *DELTAT = OPL->deltat;
+
+		DELTAT->freqbase = OPL->freqbase;
+		DELTAT->output_pointer = outd;
+		DELTAT->portshift = 5;
+		DELTAT->output_range = DELTAT_MIXING_LEVEL<<TL_BITS;
+		YM_DELTAT_ADPCM_Reset(DELTAT,0);
+	}
+#endif
+}
+
+/* ----------  Create one of vietual YM3812 ----------       */
+/* 'rate'  is sampling rate and 'bufsiz' is the size of the  */
+FM_OPL *OPLCreate(int type, int clock, int rate)
+{
+	char *ptr;
+	FM_OPL *OPL;
+	int state_size;
+	int max_ch = 9; /* normaly 9 channels */
+
+	if( OPL_LockTable() ==-1) return NULL;
+	/* allocate OPL state space */
+	state_size  = sizeof(FM_OPL);
+	state_size += sizeof(OPL_CH)*max_ch;
+#if BUILD_Y8950
+	if(type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT);
+#endif
+	/* allocate memory block */
+	ptr = malloc(state_size);
+	if(ptr==NULL) return NULL;
+	/* clear */
+	memset(ptr,0,state_size);
+	OPL        = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL);
+	OPL->P_CH  = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch;
+#if BUILD_Y8950
+	if(type&OPL_TYPE_ADPCM) OPL->deltat = (YM_DELTAT *)ptr; ptr+=sizeof(YM_DELTAT);
+#endif
+	/* set channel state pointer */
+	OPL->type  = type;
+	OPL->clock = clock;
+	OPL->rate  = rate;
+	OPL->max_ch = max_ch;
+	/* init grobal tables */
+	OPL_initalize(OPL);
+	/* reset chip */
+	OPLResetChip(OPL);
+#ifdef OPL_OUTPUT_LOG
+	if(!opl_dbg_fp)
+	{
+		opl_dbg_fp = fopen("opllog.opl","wb");
+		opl_dbg_maxchip = 0;
+	}
+	if(opl_dbg_fp)
+	{
+		opl_dbg_opl[opl_dbg_maxchip] = OPL;
+		fprintf(opl_dbg_fp,"%c%c%c%c%c%c",0x00+opl_dbg_maxchip,
+			type,
+			clock&0xff,
+			(clock/0x100)&0xff,
+			(clock/0x10000)&0xff,
+			(clock/0x1000000)&0xff);
+		opl_dbg_maxchip++;
+	}
+#endif
+	return OPL;
+}
+
+/* ----------  Destroy one of vietual YM3812 ----------       */
+void OPLDestroy(FM_OPL *OPL)
+{
+#ifdef OPL_OUTPUT_LOG
+	if(opl_dbg_fp)
+	{
+		fclose(opl_dbg_fp);
+		opl_dbg_fp = NULL;
+	}
+#endif
+	OPL_UnLockTable();
+	free(OPL);
+}
+
+/* ----------  Option handlers ----------       */
+
+void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset)
+{
+	OPL->TimerHandler   = TimerHandler;
+	OPL->TimerParam = channelOffset;
+}
+void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param)
+{
+	OPL->IRQHandler     = IRQHandler;
+	OPL->IRQParam = param;
+}
+void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param)
+{
+	OPL->UpdateHandler = UpdateHandler;
+	OPL->UpdateParam = param;
+}
+#if BUILD_Y8950
+void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param)
+{
+	OPL->porthandler_w = PortHandler_w;
+	OPL->porthandler_r = PortHandler_r;
+	OPL->port_param = param;
+}
+
+void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param)
+{
+	OPL->keyboardhandler_w = KeyboardHandler_w;
+	OPL->keyboardhandler_r = KeyboardHandler_r;
+	OPL->keyboard_param = param;
+}
+#endif
+/* ---------- YM3812 I/O interface ---------- */
+int OPLWrite(FM_OPL *OPL,int a,int v)
+{
+	if( !(a&1) )
+	{	/* address port */
+		OPL->address = v & 0xff;
+	}
+	else
+	{	/* data port */
+		if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
+#ifdef OPL_OUTPUT_LOG
+	if(opl_dbg_fp)
+	{
+		for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++)
+			if( opl_dbg_opl[opl_dbg_chip] == OPL) break;
+		fprintf(opl_dbg_fp,"%c%c%c",0x10+opl_dbg_chip,OPL->address,v);
+	}
+#endif
+		OPLWriteReg(OPL,OPL->address,v);
+	}
+	return OPL->status>>7;
+}
+
+unsigned char OPLRead(FM_OPL *OPL,int a)
+{
+	if( !(a&1) )
+	{	/* status port */
+		return OPL->status & (OPL->statusmask|0x80);
+	}
+	/* data port */
+	switch(OPL->address)
+	{
+	case 0x05: /* KeyBoard IN */
+		if(OPL->type&OPL_TYPE_KEYBOARD)
+		{
+			if(OPL->keyboardhandler_r)
+				return OPL->keyboardhandler_r(OPL->keyboard_param);
+			else
+				LOG(LOG_WAR,("OPL:read unmapped KEYBOARD port\n"));
+		}
+		return 0;
+#if 0
+	case 0x0f: /* ADPCM-DATA  */
+		return 0;
+#endif
+	case 0x19: /* I/O DATA    */
+		if(OPL->type&OPL_TYPE_IO)
+		{
+			if(OPL->porthandler_r)
+				return OPL->porthandler_r(OPL->port_param);
+			else
+				LOG(LOG_WAR,("OPL:read unmapped I/O port\n"));
+		}
+		return 0;
+	case 0x1a: /* PCM-DATA    */
+		return 0;
+	}
+	return 0;
+}
+
+int OPLTimerOver(FM_OPL *OPL,int c)
+{
+	if( c )
+	{	/* Timer B */
+		OPL_STATUS_SET(OPL,0x20);
+	}
+	else
+	{	/* Timer A */
+		OPL_STATUS_SET(OPL,0x40);
+		/* CSM mode key,TL controll */
+		if( OPL->mode & 0x80 )
+		{	/* CSM mode total level latch and auto key on */
+			int ch;
+			if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
+			for(ch=0;ch<9;ch++)
+				CSMKeyControll( &OPL->P_CH[ch] );
+		}
+	}
+	/* reload timer */
+	if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase);
+	return OPL->status>>7;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/fmopl.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,174 @@
+#ifndef __FMOPL_H_
+#define __FMOPL_H_
+
+/* --- select emulation chips --- */
+#define BUILD_YM3812 (HAS_YM3812)
+//#define BUILD_YM3526 (HAS_YM3526)
+//#define BUILD_Y8950  (HAS_Y8950)
+
+/* --- system optimize --- */
+/* select bit size of output : 8 or 16 */
+#define OPL_OUTPUT_BIT 16
+
+/* compiler dependence */
+#ifndef OSD_CPU_H
+#define OSD_CPU_H
+typedef unsigned char	UINT8;   /* unsigned  8bit */
+typedef unsigned short	UINT16;  /* unsigned 16bit */
+typedef unsigned int	UINT32;  /* unsigned 32bit */
+typedef signed char		INT8;    /* signed  8bit   */
+typedef signed short	INT16;   /* signed 16bit   */
+typedef signed int		INT32;   /* signed 32bit   */
+#endif
+
+#if (OPL_OUTPUT_BIT==16)
+typedef INT16 OPLSAMPLE;
+#endif
+#if (OPL_OUTPUT_BIT==8)
+typedef unsigned char  OPLSAMPLE;
+#endif
+
+
+#if BUILD_Y8950
+#include "ymdeltat.h"
+#endif
+
+typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
+typedef void (*OPL_IRQHANDLER)(int param,int irq);
+typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);
+typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data);
+typedef unsigned char (*OPL_PORTHANDLER_R)(int param);
+
+/* !!!!! here is private section , do not access there member direct !!!!! */
+
+#define OPL_TYPE_WAVESEL   0x01  /* waveform select    */
+#define OPL_TYPE_ADPCM     0x02  /* DELTA-T ADPCM unit */
+#define OPL_TYPE_KEYBOARD  0x04  /* keyboard interface */
+#define OPL_TYPE_IO        0x08  /* I/O port */
+
+/* Saving is necessary for member of the 'R' mark for suspend/resume */
+/* ---------- OPL one of slot  ---------- */
+typedef struct fm_opl_slot {
+	INT32 TL;		/* total level     :TL << 8            */
+	INT32 TLL;		/* adjusted now TL                     */
+	UINT8  KSR;		/* key scale rate  :(shift down bit)   */
+	INT32 *AR;		/* attack rate     :&AR_TABLE[AR<<2]   */
+	INT32 *DR;		/* decay rate      :&DR_TALBE[DR<<2]   */
+	INT32 SL;		/* sustin level    :SL_TALBE[SL]       */
+	INT32 *RR;		/* release rate    :&DR_TABLE[RR<<2]   */
+	UINT8 ksl;		/* keyscale level  :(shift down bits)  */
+	UINT8 ksr;		/* key scale rate  :kcode>>KSR         */
+	UINT32 mul;		/* multiple        :ML_TABLE[ML]       */
+	UINT32 Cnt;		/* frequency count :                   */
+	UINT32 Incr;	/* frequency step  :                   */
+	/* envelope generator state */
+	UINT8 eg_typ;	/* envelope type flag                  */
+	UINT8 evm;		/* envelope phase                      */
+	INT32 evc;		/* envelope counter                    */
+	INT32 eve;		/* envelope counter end point          */
+	INT32 evs;		/* envelope counter step               */
+	INT32 evsa;	/* envelope step for AR :AR[ksr]           */
+	INT32 evsd;	/* envelope step for DR :DR[ksr]           */
+	INT32 evsr;	/* envelope step for RR :RR[ksr]           */
+	/* LFO */
+	UINT8 ams;		/* ams flag                            */
+	UINT8 vib;		/* vibrate flag                        */
+	/* wave selector */
+	INT32 **wavetable;
+}OPL_SLOT;
+
+/* ---------- OPL one of channel  ---------- */
+typedef struct fm_opl_channel {
+	OPL_SLOT SLOT[2];
+	UINT8 CON;			/* connection type                     */
+	UINT8 FB;			/* feed back       :(shift down bit)   */
+	INT32 *connect1;	/* slot1 output pointer                */
+	INT32 *connect2;	/* slot2 output pointer                */
+	INT32 op1_out[2];	/* slot1 output for selfeedback        */
+	/* phase generator state */
+	UINT32  block_fnum;	/* block+fnum      :                   */
+	UINT8 kcode;		/* key code        : KeyScaleCode      */
+	UINT32  fc;			/* Freq. Increment base                */
+	UINT32  ksl_base;	/* KeyScaleLevel Base step             */
+	UINT8 keyon;		/* key on/off flag                     */
+} OPL_CH;
+
+/* OPL state */
+typedef struct fm_opl_f {
+	UINT8 type;			/* chip type                         */
+	int clock;			/* master clock  (Hz)                */
+	int rate;			/* sampling rate (Hz)                */
+	double freqbase;	/* frequency base                    */
+	double TimerBase;	/* Timer base time (==sampling time) */
+	UINT8 address;		/* address register                  */
+	UINT8 status;		/* status flag                       */
+	UINT8 statusmask;	/* status mask                       */
+	UINT32 mode;		/* Reg.08 : CSM , notesel,etc.       */
+	/* Timer */
+	int T[2];			/* timer counter                     */
+	UINT8 st[2];		/* timer enable                      */
+	/* FM channel slots */
+	OPL_CH *P_CH;		/* pointer of CH                     */
+	int	max_ch;			/* maximum channel                   */
+	/* Rythm sention */
+	UINT8 rythm;		/* Rythm mode , key flag */
+#if BUILD_Y8950
+	/* Delta-T ADPCM unit (Y8950) */
+	YM_DELTAT *deltat;			/* DELTA-T ADPCM       */
+#endif
+	/* Keyboard / I/O interface unit (Y8950) */
+	UINT8 portDirection;
+	UINT8 portLatch;
+	OPL_PORTHANDLER_R porthandler_r;
+	OPL_PORTHANDLER_W porthandler_w;
+	int port_param;
+	OPL_PORTHANDLER_R keyboardhandler_r;
+	OPL_PORTHANDLER_W keyboardhandler_w;
+	int keyboard_param;
+	/* time tables */
+	INT32 AR_TABLE[75];	/* atttack rate tables */
+	INT32 DR_TABLE[75];	/* decay rate tables   */
+	UINT32 FN_TABLE[1024];  /* fnumber -> increment counter */
+	/* LFO */
+	INT32 *ams_table;
+	INT32 *vib_table;
+	INT32 amsCnt;
+	INT32 amsIncr;
+	INT32 vibCnt;
+	INT32 vibIncr;
+	/* wave selector enable flag */
+	UINT8 wavesel;
+	/* external event callback handler */
+	OPL_TIMERHANDLER  TimerHandler;		/* TIMER handler   */
+	int TimerParam;						/* TIMER parameter */
+	OPL_IRQHANDLER    IRQHandler;		/* IRQ handler    */
+	int IRQParam;						/* IRQ parameter  */
+	OPL_UPDATEHANDLER UpdateHandler;	/* stream update handler   */
+	int UpdateParam;					/* stream update parameter */
+} FM_OPL;
+
+/* ---------- Generic interface section ---------- */
+#define OPL_TYPE_YM3526 (0)
+#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
+#define OPL_TYPE_Y8950  (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)
+
+FM_OPL *OPLCreate(int type, int clock, int rate);
+void OPLDestroy(FM_OPL *OPL);
+void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset);
+void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param);
+void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param);
+/* Y8950 port handlers */
+void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param);
+void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param);
+
+void OPLResetChip(FM_OPL *OPL);
+int OPLWrite(FM_OPL *OPL,int a,int v);
+unsigned char OPLRead(FM_OPL *OPL,int a);
+int OPLTimerOver(FM_OPL *OPL,int c);
+
+/* YM3626/YM3812 local section */
+void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
+
+void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/fprovide.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,76 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2002 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * fprovide.cpp - File provider class framework, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include <string.h>
+#include <binio.h>
+#include <binfile.h>
+
+#include "fprovide.h"
+
+/***** CFileProvider *****/
+
+bool CFileProvider::extension(const std::string &filename,
+			      const std::string &extension)
+{
+  const char *fname = filename.c_str(), *ext = extension.c_str();
+
+  if(strlen(fname) < strlen(ext) ||
+     stricmp(fname + strlen(fname) - strlen(ext), ext))
+    return false;
+  else
+    return true;
+}
+
+unsigned long CFileProvider::filesize(binistream *f)
+{
+  unsigned long oldpos = f->pos(), size;
+
+  f->seek(0, binio::End);
+  size = f->pos();
+  f->seek(oldpos, binio::Set);
+
+  return size;
+}
+
+/***** CProvider_Filesystem *****/
+
+binistream *CProvider_Filesystem::open(std::string filename) const
+{
+  binifstream *f = new binifstream(filename);
+
+  if(!f) return 0;
+  if(f->error()) { delete f; return 0; }
+
+  // Open all files as little endian with IEEE floats by default
+  f->setFlag(binio::BigEndian, false); f->setFlag(binio::FloatIEEE);
+
+  return f;
+}
+
+void CProvider_Filesystem::close(binistream *f) const
+{
+  binifstream *ff = (binifstream *)f;
+
+  if(f) {
+    ff->close();
+    delete ff;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/fprovide.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,46 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2002 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * fprovide.h - File provider class framework, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#ifndef H_ADPLUG_FILEPROVIDER
+#define H_ADPLUG_FILEPROVIDER
+
+#include <string>
+#include <binio.h>
+
+class CFileProvider
+{
+public:
+  virtual binistream *open(std::string) const = 0;
+  virtual void close(binistream *) const = 0;
+
+  static bool extension(const std::string &filename,
+			const std::string &extension);
+  static unsigned long filesize(binistream *f);
+};
+
+class CProvider_Filesystem: public CFileProvider
+{
+public:
+  virtual binistream *open(std::string filename) const;
+  virtual void close(binistream *f) const;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/hsc.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,317 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * hsc.cpp - HSC Player by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include <string.h>
+
+#include "hsc.h"
+#include "debug.h"
+
+/*** public methods **************************************/
+
+CPlayer *ChscPlayer::factory(Copl *newopl)
+{
+  return new ChscPlayer(newopl);
+}
+
+bool ChscPlayer::load(const std::string &filename, const CFileProvider &fp)
+{
+  binistream	*f = fp.open(filename);
+  int		i;
+
+  // file validation section
+  if(!f || !fp.extension(filename, ".hsc") || fp.filesize(f) > 59187) {
+    AdPlug_LogWrite("ChscPlayer::load(\"%s\"): Not a HSC file!\n", filename.c_str());
+    fp.close(f);
+    return false;
+  }
+
+  // load section
+  for(i=0;i<128*12;i++)		// load instruments
+    *((unsigned char *)instr + i) = f->readInt(1);
+  for (i=0;i<128;i++) {			// correct instruments
+    instr[i][2] ^= (instr[i][2] & 0x40) << 1;
+    instr[i][3] ^= (instr[i][3] & 0x40) << 1;
+    instr[i][11] >>= 4;			// slide
+  }
+  for(i=0;i<51;i++) song[i] = f->readInt(1);	// load tracklist
+  for(i=0;i<50*64*9;i++)			// load patterns
+    *((char *)patterns + i) = f->readInt(1);
+
+  fp.close(f);
+  rewind(0);					// rewind module
+  return true;
+}
+
+bool ChscPlayer::update()
+{
+  // general vars
+  unsigned char		chan,pattnr,note,effect,eff_op,inst,vol,Okt,db;
+  unsigned short	Fnr;
+  unsigned long		pattoff;
+
+  del--;                      // player speed handling
+  if(del)
+    return !songend;		// nothing done
+
+  if(fadein)					// fade-in handling
+    fadein--;
+
+  pattnr = song[songpos];
+  if(pattnr == 0xff) {			// arrangement handling
+    songend = 1;				// set end-flag
+    songpos = 0;
+    pattnr = song[songpos];
+  } else
+    if ((pattnr & 128) && (pattnr <= 0xb1)) { // goto pattern "nr"
+      songpos = song[songpos] & 127;
+      pattpos = 0;
+      pattnr = song[songpos];
+      songend = 1;
+    }
+
+  pattoff = pattpos*9;
+  for (chan=0;chan<9;chan++) {			// handle all channels
+    note = patterns[pattnr][pattoff].note;
+    effect = patterns[pattnr][pattoff].effect;
+    pattoff++;
+
+    if(note & 128) {                    // set instrument
+      setinstr(chan,effect);
+      continue;
+    }
+    eff_op = effect & 0x0f;
+    inst = channel[chan].inst;
+    if(note)
+      channel[chan].slide = 0;
+
+    switch (effect & 0xf0) {			// effect handling
+    case 0:								// global effect
+      /* The following fx are unimplemented on purpose:
+       * 02 - Slide Mainvolume up
+       * 03 - Slide Mainvolume down (here: fade in)
+       * 04 - Set Mainvolume to 0
+       *
+       * This is because i've never seen any HSC modules using the fx this way.
+       * All modules use the fx the way, i've implemented it.
+       */
+      switch(eff_op) {
+      case 1: pattbreak++; break;	// jump to next pattern
+      case 3: fadein = 31; break;	// fade in (divided by 2)
+      case 5: mode6 = 1; break;	// 6 voice mode on
+      case 6: mode6 = 0; break;	// 6 voice mode off
+      }
+      break;
+    case 0x20:
+    case 0x10:		                    // manual slides
+      if (effect & 0x10) {
+	channel[chan].freq += eff_op;
+	channel[chan].slide += eff_op;
+      } else {
+	channel[chan].freq -= eff_op;
+	channel[chan].slide -= eff_op;
+      }
+      if(!note)
+	setfreq(chan,channel[chan].freq);
+      break;
+    case 0x50:							// set percussion instrument (unimplemented)
+      break;
+    case 0x60:							// set feedback
+      opl->write(0xc0 + chan, (instr[channel[chan].inst][8] & 1) + (eff_op << 1));
+      break;
+    case 0xa0:		                    // set carrier volume
+      vol = eff_op << 2;
+      opl->write(0x43 + op_table[chan], vol | (instr[channel[chan].inst][2] & ~63));
+      break;
+    case 0xb0:		                    // set modulator volume
+      vol = eff_op << 2;
+      if (instr[inst][8] & 1)
+	opl->write(0x40 + op_table[chan], vol | (instr[channel[chan].inst][3] & ~63));
+      else
+	opl->write(0x40 + op_table[chan],vol | (instr[inst][3] & ~63));
+      break;
+    case 0xc0:		                    // set instrument volume
+      db = eff_op << 2;
+      opl->write(0x43 + op_table[chan], db | (instr[channel[chan].inst][2] & ~63));
+      if (instr[inst][8] & 1)
+	opl->write(0x40 + op_table[chan], db | (instr[channel[chan].inst][3] & ~63));
+      break;
+    case 0xd0: pattbreak++; songpos = eff_op; songend = 1; break;	// position jump
+    case 0xf0:							// set speed
+      speed = eff_op;
+      del = ++speed;
+      break;
+    }
+
+    if(fadein)						// fade-in volume setting
+      setvolume(chan,fadein*2,fadein*2);
+
+    if(!note)						// note handling
+      continue;
+    note--;
+
+    if ((note == 0x7f-1) || ((note/12) & ~7)) {    // pause (7fh)
+      adl_freq[chan] &= ~32;
+      opl->write(0xb0 + chan,adl_freq[chan]);
+      continue;
+    }
+
+    // play the note
+    if(mtkmode)		// imitate MPU-401 Trakker bug
+      note--;
+    Okt = ((note/12) & 7) << 2;
+    Fnr = note_table[(note % 12)] + instr[inst][11] + channel[chan].slide;
+    channel[chan].freq = Fnr;
+    if(!mode6 || chan < 6)
+      adl_freq[chan] = Okt | 32;
+    else
+      adl_freq[chan] = Okt;		// never set key for drums
+    opl->write(0xb0 + chan, 0);
+    setfreq(chan,Fnr);
+    if(mode6) {
+      switch(chan) {		// play drums
+      case 6: opl->write(0xbd,bd & ~16); bd |= 48; break;	// bass drum
+      case 7: opl->write(0xbd,bd & ~1); bd |= 33; break;	// hihat
+      case 8: opl->write(0xbd,bd & ~2); bd |= 34; break;	// cymbal
+      }
+      opl->write(0xbd,bd);
+    }
+  }
+
+  del = speed;		// player speed-timing
+  if(pattbreak) {		// do post-effect handling
+    pattpos=0;			// pattern break!
+    pattbreak=0;
+    songpos++;
+    songpos %= 50;
+    if(!songpos)
+      songend = 1;
+  } else {
+    pattpos++;
+    pattpos &= 63;		// advance in pattern data
+    if (!pattpos) {
+      songpos++;
+      songpos %= 50;
+      if(!songpos)
+	songend = 1;
+    }
+  }
+  return !songend;		// still playing
+}
+
+void ChscPlayer::rewind(int subsong)
+{
+  int i;								// counter
+
+  // rewind HSC player
+  pattpos = 0; songpos = 0; pattbreak = 0; speed = 2;
+  del = 1; songend = 0; mode6 = 0; bd = 0; fadein = 0;
+
+  opl->init();						// reset OPL chip
+  opl->write(1,32); opl->write(8,128); opl->write(0xbd,0);
+
+  for(i=0;i<9;i++)
+    setinstr((char) i,(char) i);	// init channels
+}
+
+unsigned int ChscPlayer::getpatterns()
+{
+  unsigned char	poscnt,pattcnt=0;
+
+  // count patterns
+  for(poscnt=0;poscnt<51 && song[poscnt] != 0xff;poscnt++)
+    if(song[poscnt] > pattcnt)
+      pattcnt = song[poscnt];
+
+  return (pattcnt+1);
+}
+
+unsigned int ChscPlayer::getorders()
+{
+  unsigned char poscnt;
+
+  // count positions
+  for(poscnt=0;poscnt<51;poscnt++)
+    if(song[poscnt] == 0xff)
+      break;
+
+  return poscnt;
+}
+
+unsigned int ChscPlayer::getinstruments()
+{
+  unsigned char	instcnt,instnum=0,i;
+  bool		isinst;
+
+  // count instruments
+  for(instcnt=0;instcnt<128;instcnt++) {
+    isinst = false;
+    for(i=0;i<12;i++)
+      if(instr[instcnt][i])
+	isinst = true;
+    if(isinst)
+      instnum++;
+  }
+
+  return instnum;
+}
+
+/*** private methods *************************************/
+
+void ChscPlayer::setfreq(unsigned char chan, unsigned short freq)
+{
+  adl_freq[chan] = (adl_freq[chan] & ~3) | (freq >> 8);
+
+  opl->write(0xa0 + chan, freq & 0xff);
+  opl->write(0xb0 + chan, adl_freq[chan]);
+}
+
+void ChscPlayer::setvolume(unsigned char chan, int volc, int volm)
+{
+  unsigned char	*ins = instr[channel[chan].inst];
+  char		op = op_table[chan];
+
+  opl->write(0x43 + op,volc | (ins[2] & ~63));
+  if (ins[8] & 1)							// carrier
+    opl->write(0x40 + op,volm | (ins[3] & ~63));
+  else
+    opl->write(0x40 + op, ins[3]);		// modulator
+}
+
+void ChscPlayer::setinstr(unsigned char chan, unsigned char insnr)
+{
+  unsigned char	*ins = instr[insnr];
+  char		op = op_table[chan];
+
+  channel[chan].inst = insnr;		// set internal instrument
+  opl->write(0xb0 + chan,0);			// stop old note
+
+  // set instrument
+  opl->write(0xc0 + chan, ins[8]);
+  opl->write(0x23 + op, ins[0]);        // carrier
+  opl->write(0x20 + op, ins[1]);        // modulator
+  opl->write(0x63 + op, ins[4]);        // bits 0..3 = decay; 4..7 = attack
+  opl->write(0x60 + op, ins[5]);
+  opl->write(0x83 + op, ins[6]);        // 0..3 = release; 4..7 = sustain
+  opl->write(0x80 + op, ins[7]);
+  opl->write(0xe3 + op, ins[9]);        // bits 0..1 = Wellenform
+  opl->write(0xe0 + op, ins[10]);
+  setvolume(chan, ins[2] & 63, ins[3] & 63);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/hsc.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,75 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2002 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * hsc.h - HSC Player by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#ifndef H_ADPLUG_HSCPLAYER
+#define H_ADPLUG_HSCPLAYER
+
+#include "player.h"
+
+class ChscPlayer: public CPlayer
+{
+ public:
+  static CPlayer *factory(Copl *newopl);
+
+  ChscPlayer(Copl *newopl): CPlayer(newopl), mtkmode(0) {}
+
+  bool load(const std::string &filename, const CFileProvider &fp);
+  bool update();
+  void rewind(int subsong);
+  float getrefresh() { return 18.2f; };	// refresh rate is fixed at 18.2Hz
+
+  std::string gettype() { return std::string("HSC Adlib Composer / HSC-Tracker"); }
+  unsigned int getpatterns();
+  unsigned int getpattern() { return song[songpos]; }
+  unsigned int getorders();
+  unsigned int getorder() { return songpos; }
+  unsigned int getrow() { return pattpos; }
+  unsigned int getspeed() { return speed; }
+  unsigned int getinstruments();
+
+ protected:
+  struct hscnote {
+    unsigned char note, effect;
+  };			// note type in HSC pattern
+
+  struct hscchan {
+    unsigned char inst;			// current instrument
+    signed char slide;			// used for manual slide-effects
+    unsigned short freq;		// actual replaying frequency
+  };			// HSC channel data
+
+  hscchan channel[9];				// player channel-info
+  unsigned char instr[128][12];	// instrument data
+  unsigned char song[0x80];		// song-arrangement (MPU-401 Trakker enhanced)
+  hscnote patterns[50][64*9];		// pattern data
+  unsigned char pattpos,songpos,	// various bytes & flags
+    pattbreak,songend,mode6,bd,fadein;
+  unsigned int speed,del;
+  unsigned char adl_freq[9];		// adlib frequency registers
+  int mtkmode;				// flag: MPU-401 Trakker mode on/off
+
+ private:
+  void setfreq(unsigned char chan, unsigned short freq);
+  void setvolume(unsigned char chan, int volc, int volm);
+  void setinstr(unsigned char chan, unsigned char insnr);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/hsp.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,68 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * hsp.cpp - HSP Loader by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include <string.h>
+
+#include "hsp.h"
+
+CPlayer *ChspLoader::factory(Copl *newopl)
+{
+  return new ChspLoader(newopl);
+}
+
+bool ChspLoader::load(const std::string &filename, const CFileProvider &fp)
+{
+  binistream	*f = fp.open(filename); if(!f) return false;
+  unsigned long	i, j, orgsize, filesize;
+  unsigned char	*cmp, *org;
+
+  // file validation section
+  if(!fp.extension(filename, ".hsp")) { fp.close(f); return false; }
+
+  filesize = fp.filesize(f);
+  orgsize = f->readInt(2);
+  if(orgsize > 59187) { fp.close(f); return false; }
+
+  // load section
+  cmp = new unsigned char[filesize];
+  for(i = 0; i < filesize; i++) cmp[i] = f->readInt(1);
+  fp.close(f);
+
+  org = new unsigned char[orgsize];
+  for(i = 0, j = 0; i < filesize; j += cmp[i], i += 2) {	// RLE decompress
+    if(j >= orgsize) break;	// memory boundary check
+    memset(org + j, cmp[i + 1], j + cmp[i] < orgsize ? cmp[i] : orgsize - j - 1);
+  }
+  delete [] cmp;
+
+  memcpy(instr, org, 128 * 12);		// instruments
+  for(i = 0; i < 128; i++) {		// correct instruments
+    instr[i][2] ^= (instr[i][2] & 0x40) << 1;
+    instr[i][3] ^= (instr[i][3] & 0x40) << 1;
+    instr[i][11] >>= 4;		// slide
+  }
+  memcpy(song, org + 128 * 12, 51);	// tracklist
+  memcpy(patterns, org + 128 * 12 + 51, orgsize - 128 * 12 - 51);	// patterns
+  delete [] org;
+
+  rewind(0);
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/hsp.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,39 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * hsp.h: HSC Packed Loader by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#ifndef H_ADPLUG_HSPLOADER
+#define H_ADPLUG_HSPLOADER
+
+#include "hsc.h"
+
+class ChspLoader: public ChscPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	ChspLoader(Copl *newopl)
+		: ChscPlayer(newopl)
+	{};
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/hybrid.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,247 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * [xad] HYBRID player, by Riven the Mage <riven@ok.ru>
+ */
+
+/*
+    - discovery -
+
+  file(s) : HYBRID.EXE
+     type : Hybrid cracktro for Apache Longbow CD-RIP
+     tune : from 'Mig-29 Super Fulcrum' game by Domark
+   player : from 'Mig-29 Super Fulcrum' game by Domark
+*/
+
+#include "hybrid.h"
+#include "debug.h"
+
+const unsigned char CxadhybridPlayer::hyb_adlib_registers[99] = 
+{
+  0xE0, 0x60, 0x80, 0x20, 0x40, 0xE3, 0x63, 0x83, 0x23, 0x43, 0xC0,
+  0xE1, 0x61, 0x81, 0x21, 0x41, 0xE4, 0x64, 0x84, 0x24, 0x44, 0xC1,
+  0xE2, 0x62, 0x82, 0x22, 0x42, 0xE5, 0x65, 0x85, 0x25, 0x45, 0xC2,
+  0xE8, 0x68, 0x88, 0x28, 0x48, 0xEB, 0x6B, 0x8B, 0x2B, 0x4B, 0xC3,
+  0xE9, 0x69, 0x89, 0x29, 0x49, 0xEC, 0x6C, 0x8C, 0x2C, 0x4C, 0xC4,
+  0xEA, 0x6A, 0x8A, 0x2A, 0x4A, 0xED, 0x6D, 0x8D, 0x2D, 0x4D, 0xC5,
+  0xF0, 0x70, 0x90, 0x30, 0x50, 0xF3, 0x73, 0x93, 0x33, 0x53, 0xC6,
+  0xF1, 0x71, 0x91, 0x31, 0x51, 0xF4, 0x74, 0x94, 0x34, 0x54, 0xC7,
+  0xF2, 0x72, 0x92, 0x32, 0x52, 0xF5, 0x75, 0x95, 0x35, 0x55, 0xC8
+};
+
+const unsigned short CxadhybridPlayer::hyb_notes[98] =
+{
+  0x0000, 0x0000,
+  0x016B, 0x0181, 0x0198, 0x01B0, 0x01CA, 0x01E5, 0x0202, 0x0220, 0x0241, 0x0263, 0x0287, 0x02AE,
+  0x056B, 0x0581, 0x0598, 0x05B0, 0x05CA, 0x05E5, 0x0602, 0x0620, 0x0641, 0x0663, 0x0687, 0x06AE,
+  0x096B, 0x0981, 0x0998, 0x09B0, 0x09CA, 0x09E5, 0x0A02, 0x0A20, 0x0A41, 0x0A63, 0x0A87, 0x0AAE,
+  0x0D6B, 0x0D81, 0x0D98, 0x0DB0, 0x0DCA, 0x0DE5, 0x0E02, 0x0E20, 0x0E41, 0x0E63, 0x0E87, 0x0EAE,
+  0x116B, 0x1181, 0x1198, 0x11B0, 0x11CA, 0x11E5, 0x1202, 0x1220, 0x1241, 0x1263, 0x1287, 0x12AE,
+  0x156B, 0x1581, 0x1598, 0x15B0, 0x15CA, 0x15E5, 0x1602, 0x1620, 0x1641, 0x1663, 0x1687, 0x16AE,
+  0x196B, 0x1981, 0x1998, 0x19B0, 0x19CA, 0x19E5, 0x1A02, 0x1A20, 0x1A41, 0x1A63, 0x1A87, 0x1AAE,
+  0x1D6B, 0x1D81, 0x1D98, 0x1DB0, 0x1DCA, 0x1DE5, 0x1E02, 0x1E20, 0x1E41, 0x1E63, 0x1E87, 0x1EAE
+};
+
+const unsigned char CxadhybridPlayer::hyb_default_instrument[11] = 
+{
+  0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00
+};
+
+CPlayer *CxadhybridPlayer::factory(Copl *newopl)
+{
+  return new CxadhybridPlayer(newopl);
+}
+
+bool CxadhybridPlayer::xadplayer_load()
+{
+  if(xad.fmt != HYBRID)
+    return false;
+
+  // load instruments
+  hyb.inst = (hyb_instrument *)&tune[0];
+
+  // load order
+  hyb.order = &tune[0x1D4];
+
+  return true;
+}
+
+void CxadhybridPlayer::xadplayer_rewind(int subsong)
+{
+  int i;
+
+  hyb.order_pos = 0;
+  hyb.pattern_pos = 0;
+
+  hyb.speed = 6;
+  hyb.speed_counter = 1;
+
+  plr.speed = 1;
+
+  // init channel data
+  for(i=0;i<9;i++)
+  {
+    hyb.channel[i].freq       = 0x2000;
+    hyb.channel[i].freq_slide = 0x0000;
+  }
+
+  // basic OPL init
+  opl_write(0x01, 0x20);
+  opl_write(0xBD, 0x40);
+  opl_write(0x08, 0x00);
+
+  // init OPL channels
+  for(i=0;i<9;i++)
+  {
+    for(int j=0;j<11;j++)
+      opl_write(hyb_adlib_registers[i*11+j], 0x00 /* hyb_default_instrument[j] */ );
+
+	opl_write(0xA0+i, 0x00);
+	opl_write(0xB0+i, 0x20);
+  }
+}
+
+void CxadhybridPlayer::xadplayer_update()
+{
+  int i,j;
+  unsigned char patpos,ordpos;
+
+  if (--hyb.speed_counter)
+    goto update_slides;
+
+  hyb.speed_counter = hyb.speed;
+
+  patpos = hyb.pattern_pos;
+  ordpos = hyb.order_pos;
+
+  // process channels
+  for(i=0;i<9;i++)
+  {
+    // read event
+    unsigned short event = *(unsigned short *)&tune[0xADE + (hyb.order[hyb.order_pos*9 + i] * 64 * 2) + (patpos * 2)];
+
+#ifdef DEBUG
+   AdPlug_LogWrite("track %02X, channel %02X, event %04X:\n", hyb.order[hyb.order_pos*9 + i], i, event );
+#endif
+
+    // calculate variables
+	unsigned char  note  =   event >> 9;
+	unsigned char  ins   = ((event & 0x01F0) >> 4);
+    unsigned char  slide =   event & 0x000F;
+
+    // play event
+    switch(note)
+    {
+      case 0x7D: // 0x7D: Set Speed
+        hyb.speed = event & 0xFF;
+        break;
+      case 0x7E: // 0x7E: Jump Position
+        hyb.order_pos = event & 0xFF;
+        hyb.pattern_pos = 0x3F;
+
+        // jumpback ?
+        if (hyb.order_pos <= ordpos)
+          plr.looping = 1;
+
+        break;
+      case 0x7F: // 0x7F: Pattern Break
+        hyb.pattern_pos = 0x3F;
+        break;
+      default:
+
+        // is instrument ?
+        if (ins)
+          for(j=0;j<11;j++)
+            opl_write(hyb_adlib_registers[i*11+j], *((unsigned char *)&hyb.inst[ins-1] + 7 + j)); // +7 = skip name...
+
+        // is note ?
+        if (note)
+        {
+          hyb.channel[i].freq = hyb_notes[note];
+          hyb.channel[i].freq_slide = 0;
+        }
+
+        // is slide ?
+        if (slide)
+        {
+          hyb.channel[i].freq_slide = (((slide >> 3) * -1) * (slide & 7)) << 1;
+    
+          if (slide & 0x80)
+            slide = -(slide & 7);
+        }
+
+        // set frequency
+        if (!(hyb.channel[i].freq & 0x2000))
+        {
+          opl_write(0xA0+i, hyb.channel[i].freq & 0xFF);
+          opl_write(0xB0+i, hyb.channel[i].freq >> 8);
+
+          hyb.channel[i].freq |= 0x2000;
+
+          opl_write(0xA0+i, hyb.channel[i].freq & 0xFF);
+          opl_write(0xB0+i, hyb.channel[i].freq >> 8);
+        }
+
+        break;
+    }
+  }
+
+  hyb.pattern_pos++;
+
+  // end of pattern ?
+  if (hyb.pattern_pos >= 0x40)
+  {
+    hyb.pattern_pos = 0;
+
+    hyb.order_pos++;
+  }
+
+update_slides:
+#ifdef DEBUG
+   AdPlug_LogWrite("slides:\n");
+#endif
+  // update fine frequency slides
+  for(i=0;i<9;i++)
+    if (hyb.channel[i].freq_slide)
+    {
+      hyb.channel[i].freq = (((hyb.channel[i].freq & 0x1FFF) + hyb.channel[i].freq_slide) & 0x1FFF) | 0x2000;
+
+      opl_write(0xA0+i, hyb.channel[i].freq & 0xFF);
+      opl_write(0xB0+i, hyb.channel[i].freq >> 8);
+    }
+}
+
+float CxadhybridPlayer::xadplayer_getrefresh()
+{
+  return 50.0f;
+}
+
+std::string CxadhybridPlayer::xadplayer_gettype()
+{
+  return (std::string("xad: hybrid player"));
+}
+
+std::string CxadhybridPlayer::xadplayer_getinstrument(unsigned int i)
+{
+  return (std::string(hyb.inst[i].name,7));
+}
+
+unsigned int CxadhybridPlayer::xadplayer_getinstruments()
+{
+  return 26;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/hybrid.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,80 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * [xad] HYBRID player, by Riven the Mage <riven@ok.ru>
+ */
+
+#include "xad.h"
+
+class CxadhybridPlayer: public CxadPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+  CxadhybridPlayer(Copl *newopl): CxadPlayer(newopl)
+    { }
+
+protected:
+  struct hyb_instrument
+  {
+    char            name[7];
+    unsigned char   mod_wave;
+    unsigned char   mod_AD;
+    unsigned char   mod_SR;
+    unsigned char   mod_crtl;
+    unsigned char   mod_volume;
+    unsigned char   car_wave;
+    unsigned char   car_AD;
+    unsigned char   car_SR;
+    unsigned char   car_crtl;
+    unsigned char   car_volume;
+    unsigned char   connect;
+  };
+
+  struct
+  {
+    unsigned char   order_pos;
+    unsigned char   pattern_pos;
+
+    unsigned char   *order;
+
+    hyb_instrument  *inst;
+
+    struct
+    {
+      unsigned short  freq;
+      unsigned short  freq_slide;
+    } channel[9];
+
+    unsigned char   speed;
+    unsigned char   speed_counter;
+  } hyb;
+  //
+  bool            xadplayer_load();
+  void            xadplayer_rewind(int subsong);
+  void            xadplayer_update();
+  float           xadplayer_getrefresh();
+  std::string     xadplayer_gettype();
+  std::string     xadplayer_getinstrument(unsigned int i);
+  unsigned int    xadplayer_getinstruments();
+
+private:
+  static const unsigned char hyb_adlib_registers[99];
+  static const unsigned short hyb_notes[98];
+  static const unsigned char hyb_default_instrument[11];
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/hyp.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,125 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * [xad] HYP player, by Riven the Mage <riven@ok.ru>
+ */
+
+/*
+    - discovery -
+
+  file(s) : HT-EF2.COM, HT-EF3.COM
+     type : Eiserne Front BBStro
+     tune : by Shadowdancer [Hypnosis]
+   player : by (?)Hetero [LKCC/SAC]
+*/
+
+#include "hyp.h"
+#include "debug.h"
+
+const unsigned char CxadhypPlayer::hyp_adlib_registers[99] =
+{
+  0x20, 0x23, 0x40, 0x43, 0x60, 0x63, 0x80, 0x83, 0xA0, 0xB0, 0xC0,
+  0x21, 0x24, 0x41, 0x44, 0x61, 0x64, 0x81, 0x84, 0xA1, 0xB1, 0xC1,
+  0x22, 0x25, 0x42, 0x45, 0x62, 0x65, 0x82, 0x85, 0xA2, 0xB2, 0xC2,
+  0x28, 0x2B, 0x48, 0x4B, 0x68, 0x6B, 0x88, 0x8B, 0xA3, 0xB3, 0xC3,
+  0x29, 0x2C, 0x49, 0x4C, 0x69, 0x6C, 0x89, 0x8C, 0xA4, 0xB4, 0xC4,
+  0x2A, 0x2D, 0x4A, 0x4D, 0x6A, 0x6D, 0x8A, 0x8D, 0xA5, 0xB5, 0xC5,
+  0x30, 0x33, 0x50, 0x53, 0x70, 0x73, 0x90, 0x93, 0xA6, 0xB6, 0xC6,
+  0x31, 0x34, 0x51, 0x54, 0x71, 0x74, 0x91, 0x94, 0xA7, 0xB7, 0xC7,
+  0x32, 0x35, 0x52, 0x55, 0x72, 0x75, 0x92, 0x95, 0xA8, 0xB8, 0xC8
+};
+
+const unsigned short CxadhypPlayer::hyp_notes[73] =
+{
+  0x0000, // by riven
+  0x0956, 0x096B, 0x0980, 0x0998, 0x09B1, 0x09C9, 0x09E5, 0x0A03, 0x0A21,
+  0x0A41, 0x0A63, 0x0A86, 0x0D56, 0x0D6B, 0x0D80, 0x0D98, 0x0DB1, 0x0DC9,
+  0x0DE5, 0x0E03, 0x0E21, 0x0E41, 0x0E63, 0x0E86, 0x1156, 0x116B, 0x1180,
+  0x1198, 0x11B1, 0x11C9, 0x11E5, 0x1203, 0x1221, 0x1241, 0x1263, 0x1286,
+  0x1556, 0x156B, 0x1580, 0x1598, 0x15B1, 0x15C9, 0x15E5, 0x1603, 0x1621,
+  0x1641, 0x1663, 0x1686, 0x1956, 0x196B, 0x1980, 0x1998, 0x19B1, 0x19C9,
+  0x19E5, 0x1A03, 0x1A21, 0x1A41, 0x1A63, 0x1A86, 0x1D56, 0x1D6B, 0x1D80,
+  0x1D98, 0x1DB1, 0x1DC9, 0x1DE5, 0x1E03, 0x1E21, 0x1E41, 0x1E63, 0x1E86
+};
+
+CPlayer *CxadhypPlayer::factory(Copl *newopl)
+{
+  return new CxadhypPlayer(newopl);
+}
+
+void CxadhypPlayer::xadplayer_rewind(int subsong)
+{
+  int i;
+
+  plr.speed = tune[5];
+
+  opl_write(0xBD,0xC0);
+
+  for(i=0; i<9; i++)
+    adlib[0xB0+i] = 0;
+
+  // define instruments
+  for(i=0; i<99; i++)
+    opl_write(hyp_adlib_registers[i], tune[6+i]);
+
+  hyp.pointer = 0x69;
+}
+
+void CxadhypPlayer::xadplayer_update()
+{
+  for(int i=0; i<9; i++)
+  {
+    unsigned char event = tune[hyp.pointer++];
+
+    if (event)
+    {
+      unsigned short freq = hyp_notes[event & 0x3F];
+
+      unsigned char lofreq = (freq & 0xFF);
+      unsigned char hifreq = (freq >> 8);
+
+      opl_write(0xB0+i, adlib[0xB0+i]);
+
+      if (!(event & 0x40))
+      {
+        opl_write(0xA0+i, lofreq);
+        opl_write(0xB0+i, hifreq | 0x20);
+      }
+
+      adlib[0xB0+i] &= 0xDF;
+    }
+  }
+
+  hyp.pointer += 3;
+
+  if (hyp.pointer >= tune_size)
+  {
+    hyp.pointer = 0x69;
+    plr.looping = 1;
+  }
+}
+
+float CxadhypPlayer::xadplayer_getrefresh()
+{
+  return 60.0f;
+}
+
+std::string CxadhypPlayer::xadplayer_gettype()
+{
+  return std::string("xad: hypnosis player");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/hyp.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,53 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * [xad] HYP player, by Riven the Mage <riven@ok.ru>
+ */
+
+#include "xad.h"
+
+class CxadhypPlayer: public CxadPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+  CxadhypPlayer(Copl *newopl): CxadPlayer(newopl)
+    { }
+
+protected:
+  struct
+  {
+    unsigned short  pointer;
+  } hyp;
+  //
+  bool		    xadplayer_load()
+    {
+      if(xad.fmt == HYP)
+	return true;
+      else
+	return false;
+    }
+  void 		    xadplayer_rewind(int subsong);
+  void 		    xadplayer_update();
+  float 	    xadplayer_getrefresh();
+  std::string	    xadplayer_gettype();
+
+private:
+  static const unsigned char hyp_adlib_registers[99];
+  static const unsigned short hyp_notes[73];
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/imf.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,169 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * imf.cpp - IMF Player by Simon Peter <dn.tlp@gmx.net>
+ *
+ * FILE FORMAT:
+ * There seem to be 2 different flavors of IMF formats out there. One version
+ * contains just the raw IMF music data. In this case, the first word of the
+ * file is always 0 (because the music data starts this way). This is already
+ * the music data! So read in the entire file and play it.
+ *
+ * If this word is greater than 0, it specifies the size of the following
+ * song data in bytes. In this case, the file has a footer that contains
+ * arbitrary infos about it. Mostly, this is plain ASCII text with some words
+ * of the author. Read and play the specified amount of song data and display
+ * the remaining data as ASCII text.
+ *
+ * NOTES:
+ * This player handles the two above mentioned formats, as well as a third
+ * type, invented by Martin Fernandez <mfernan@cnba.uba.ar>, that's got a
+ * proper header to add title/game name information. After the header starts
+ * the normal IMF file in one of the two above mentioned formats.
+ */
+
+#include <string.h>
+
+#include "imf.h"
+#include "database.h"
+
+/*** public methods *************************************/
+
+CPlayer *CimfPlayer::factory(Copl *newopl)
+{
+  return new CimfPlayer(newopl);
+}
+
+bool CimfPlayer::load(const std::string &filename, const CFileProvider &fp)
+{
+  binistream *f = fp.open(filename); if(!f) return false;
+  unsigned long fsize, flsize, mfsize = 0;
+  unsigned int i;
+
+  // file validation section
+  {
+    char	header[5];
+    int		version;
+
+    f->readString(header, 5);
+    version = f->readInt(1);
+
+    if(strncmp(header, "ADLIB", 5) || version != 1) {
+      if(!fp.extension(filename, ".imf") && !fp.extension(filename, ".wlf")) {
+	// It's no IMF file at all
+	fp.close(f);
+	return false;
+      } else
+	f->seek(0);	// It's a normal IMF file
+    } else {
+      // It's a IMF file with header
+      track_name = f->readString('\0');
+      game_name = f->readString('\0');
+      f->ignore(1);
+      mfsize = f->pos() + 2;
+    }
+  }
+
+  // load section
+  if(mfsize)
+    fsize = f->readInt(4);
+  else
+    fsize = f->readInt(2);
+  flsize = fp.filesize(f);
+  if(!fsize) {		// footerless file (raw music data)
+    if(mfsize)
+      f->seek(-4, binio::Add);
+    else
+      f->seek(-2, binio::Add);
+    size = flsize / 4;
+  } else		// file has got a footer
+    size = fsize / 4;
+
+  data = new Sdata[size];
+  for(i = 0; i < size; i++) {
+    data[i].reg = f->readInt(1); data[i].val = f->readInt(1);
+    data[i].time = f->readInt(2);
+  }
+
+  // read footer, if any
+  if(fsize && (fsize < flsize - 2 - mfsize)) {
+    unsigned long footerlen = flsize - fsize - 2 - mfsize;
+
+    footer = new char[footerlen + 1];
+    f->readString(footer, footerlen);
+    footer[footerlen] = '\0';	// Make ASCIIZ string
+  }
+
+  rate = getrate(f);
+  fp.close(f);
+  rewind(0);
+  return true;
+}
+
+bool CimfPlayer::update()
+{
+	do {
+		opl->write(data[pos].reg,data[pos].val);
+		del = data[pos].time;
+		pos++;
+	} while(!del && pos < size);
+
+	if(pos >= size) {
+		pos = 0;
+		songend = true;
+	}
+	else timer = rate / (float)del;
+
+	return !songend;
+}
+
+void CimfPlayer::rewind(int subsong)
+{
+	pos = 0; del = 0; timer = rate; songend = false;
+	opl->init(); opl->write(1,32);	// go to OPL2 mode
+}
+
+std::string CimfPlayer::gettitle()
+{
+  std::string	title;
+
+  title = track_name;
+
+  if(!track_name.empty() && !game_name.empty())
+    title += " - ";
+
+  title += game_name;
+
+  return title;
+}
+
+/*** private methods *************************************/
+
+float CimfPlayer::getrate(binistream *f)
+{
+  if(!db) return 700.0f;	// Database offline
+
+  f->seek(0, binio::Set);
+
+  CClockRecord *record = (CClockRecord *)db->search(CAdPlugDatabase::CKey(*f));
+
+  if(!record || record->type != CAdPlugDatabase::CRecord::ClockSpeed)
+    return 700.0f;
+  else
+    return record->clock;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/imf.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,67 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * imf.h - IMF Player by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#ifndef H_ADPLUG_IMFPLAYER
+#define H_ADPLUG_IMFPLAYER
+
+#include "player.h"
+
+class CimfPlayer: public CPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	CimfPlayer(Copl *newopl)
+	  : CPlayer(newopl), footer(0), data(0)
+	{ }
+	~CimfPlayer()
+	{ if(data) delete [] data; if(footer) delete [] footer; };
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+	bool update();
+	void rewind(int subsong);
+	float getrefresh()
+	{ return timer; };
+
+	std::string gettype()
+	{ return std::string("IMF File Format"); }
+	std::string gettitle();
+	std::string getdesc()
+	{ if(footer) return std::string(footer); else return std::string(); }
+
+protected:
+	unsigned long	pos,size;
+	unsigned short	del;
+	bool		songend;
+	float		rate,timer;
+	char		*footer;
+	std::string	track_name, game_name;
+
+	struct Sdata {
+		unsigned char	reg, val;
+		unsigned short	time;
+	} *data;
+
+private:
+	float getrate(binistream *f);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/kemuopl.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,59 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * kemuopl.h - Emulated OPL using Ken Silverman's emulator, by Simon Peter
+ *             <dn.tlp@gmx.net>
+ */
+
+#ifndef H_ADPLUG_KEMUOPL
+#define H_ADPLUG_KEMUOPL
+
+#include "opl.h"
+extern "C" {
+#include "adlibemu.h"
+}
+
+class CKemuopl: public Copl
+{
+public:
+  CKemuopl(int rate, bool bit16, bool usestereo)
+    : use16bit(bit16), stereo(usestereo)
+    {
+      adlibinit(rate, usestereo ? 2 : 1, bit16 ? 2 : 1);
+    };
+
+  void update(short *buf, int samples)
+    {
+      if(use16bit) samples *= 2;
+      if(stereo) samples *= 2;
+      adlibgetsample(buf, samples);
+    }
+
+  // template methods
+  void write(int reg, int val)
+    {
+      adlib0(reg, val);
+    };
+
+  void init() {};
+
+private:
+  bool	use16bit,stereo;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/ksm.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,333 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * ksm.cpp - KSM Player for AdPlug by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include <string.h>
+
+#include "ksm.h"
+#include "debug.h"
+
+const unsigned int CksmPlayer::adlibfreq[63] = {
+	0,
+	2390,2411,2434,2456,2480,2506,2533,2562,2592,2625,2659,2695,
+	3414,3435,3458,3480,3504,3530,3557,3586,3616,3649,3683,3719,
+	4438,4459,4482,4504,4528,4554,4581,4610,4640,4673,4707,4743,
+	5462,5483,5506,5528,5552,5578,5605,5634,5664,5697,5731,5767,
+	6486,6507,6530,6552,6576,6602,6629,6658,6688,6721,6755,6791,
+	7510};
+
+/*** public methods **************************************/
+
+CPlayer *CksmPlayer::factory(Copl *newopl)
+{
+  return new CksmPlayer(newopl);
+}
+
+bool CksmPlayer::load(const std::string &filename, const CFileProvider &fp)
+{
+  binistream	*f;
+  int		i;
+  char		*fn = new char[filename.length() + 9];
+
+  // file validation section
+  if(!fp.extension(filename, ".ksm")) {
+    AdPlug_LogWrite("CksmPlayer::load(,\"%s\"): File doesn't have '.ksm' "
+		    "extension! Rejected!\n", filename.c_str());
+    return false;
+  }
+  AdPlug_LogWrite("*** CksmPlayer::load(,\"%s\") ***\n", filename.c_str());
+
+  // Load instruments from 'insts.dat'
+  strcpy(fn, filename.c_str());
+  for(i = strlen(fn) - 1; i >= 0; i--)
+    if(fn[i] == '/' || fn[i] == '\\')
+      break;
+  strcpy(fn + i + 1, "insts.dat");
+  AdPlug_LogWrite("Instruments file: \"%s\"\n", fn);
+  f = fp.open(fn);
+  delete [] fn;
+  if(!f) {
+    AdPlug_LogWrite("Couldn't open instruments file! Aborting!\n");
+    AdPlug_LogWrite("--- CksmPlayer::load ---\n");
+    return false;
+  }
+  loadinsts(f);
+  fp.close(f);
+
+  f = fp.open(filename); if(!f) return false;
+  for(i = 0; i < 16; i++) trinst[i] = f->readInt(1);
+  for(i = 0; i < 16; i++) trquant[i] = f->readInt(1);
+  for(i = 0; i < 16; i++) trchan[i] = f->readInt(1);
+  f->ignore(16);
+  for(i = 0; i < 16; i++) trvol[i] = f->readInt(1);
+  numnotes = f->readInt(2);
+  note = new unsigned long [numnotes];
+  for(i = 0; i < numnotes; i++) note[i] = f->readInt(4);
+  fp.close(f);
+
+  if(!trchan[11]) {
+    drumstat = 0;
+    numchans = 9;
+  } else {
+    drumstat = 32;
+    numchans = 6;
+  }
+
+  rewind(0);
+  AdPlug_LogWrite("--- CksmPlayer::load ---\n");
+  return true;
+}
+
+bool CksmPlayer::update()
+{
+	int quanter,chan,drumnum,freq,track,volevel,volval;
+	unsigned int i,j,bufnum;
+	unsigned long temp,templong;
+
+	count++;
+	if (count >= countstop)
+	{
+		bufnum = 0;
+		while (count >= countstop)
+		{
+			templong = note[nownote];
+			track = (int)((templong>>8)&15);
+			if ((templong&192) == 0)
+			{
+				i = 0;
+				while (((chanfreq[i] != (templong&63)) || (chantrack[i] != ((templong>>8)&15))) && (i < numchans))
+					i++;
+				if (i < numchans)
+				{
+					databuf[bufnum] = (char)0; bufnum++;
+					databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++;
+					databuf[bufnum] = (unsigned char)((adlibfreq[templong&63]>>8)&223); bufnum++;
+					chanfreq[i] = 0;
+					chanage[i] = 0;
+				}
+			}
+			else
+			{
+				volevel = trvol[track];
+				if ((templong&192) == 128)
+				{
+					volevel -= 4;
+					if (volevel < 0)
+						volevel = 0;
+				}
+				if ((templong&192) == 192)
+				{
+					volevel += 4;
+					if (volevel > 63)
+						volevel = 63;
+				}
+				if (track < 11)
+				{
+					temp = 0;
+					i = numchans;
+					for(j=0;j<numchans;j++)
+						if ((countstop - chanage[j] >= temp) && (chantrack[j] == track))
+						{
+							temp = countstop - chanage[j];
+							i = j;
+						}
+					if (i < numchans)
+					{
+						databuf[bufnum] = (char)0, bufnum++;
+						databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++;
+						databuf[bufnum] = (unsigned char)0; bufnum++;
+						volval = (inst[trinst[track]][1]&192)+(volevel^63);
+						databuf[bufnum] = (char)0, bufnum++;
+						databuf[bufnum] = (unsigned char)(0x40+op_table[i]+3); bufnum++;
+						databuf[bufnum] = (unsigned char)volval; bufnum++;
+						databuf[bufnum] = (char)0, bufnum++;
+						databuf[bufnum] = (unsigned char)(0xa0+i); bufnum++;
+						databuf[bufnum] = (unsigned char)(adlibfreq[templong&63]&255); bufnum++;
+						databuf[bufnum] = (char)0, bufnum++;
+						databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++;
+						databuf[bufnum] = (unsigned char)((adlibfreq[templong&63]>>8)|32); bufnum++;
+						chanfreq[i] = templong&63;
+						chanage[i] = countstop;
+					}
+				}
+				else if ((drumstat&32) > 0)
+				{
+					freq = adlibfreq[templong&63];
+					switch(track)
+					{
+						case 11: drumnum = 16; chan = 6; freq -= 2048; break;
+						case 12: drumnum = 8; chan = 7; freq -= 2048; break;
+						case 13: drumnum = 4; chan = 8; break;
+						case 14: drumnum = 2; chan = 8; break;
+						case 15: drumnum = 1; chan = 7; freq -= 2048; break;
+					}
+					databuf[bufnum] = (char)0, bufnum++;
+					databuf[bufnum] = (unsigned char)(0xa0+chan); bufnum++;
+					databuf[bufnum] = (unsigned char)(freq&255); bufnum++;
+					databuf[bufnum] = (char)0, bufnum++;
+					databuf[bufnum] = (unsigned char)(0xb0+chan); bufnum++;
+					databuf[bufnum] = (unsigned char)((freq>>8)&223); bufnum++;
+					databuf[bufnum] = (char)0, bufnum++;
+					databuf[bufnum] = (unsigned char)(0xbd); bufnum++;
+					databuf[bufnum] = (unsigned char)(drumstat&(255-drumnum)); bufnum++;
+					drumstat |= drumnum;
+					if ((track == 11) || (track == 12) || (track == 14))
+					{
+						volval = (inst[trinst[track]][1]&192)+(volevel^63);
+						databuf[bufnum] = (char)0, bufnum++;
+						databuf[bufnum] = (unsigned char)(0x40+op_table[chan]+3); bufnum++;
+						databuf[bufnum] = (unsigned char)(volval); bufnum++;
+					}
+					else
+					{
+						volval = (inst[trinst[track]][6]&192)+(volevel^63);
+						databuf[bufnum] = (char)0, bufnum++;
+						databuf[bufnum] = (unsigned char)(0x40+op_table[chan]); bufnum++;
+						databuf[bufnum] = (unsigned char)(volval); bufnum++;
+					}
+					databuf[bufnum] = (char)0, bufnum++;
+					databuf[bufnum] = (unsigned char)(0xbd); bufnum++;
+					databuf[bufnum] = (unsigned char)(drumstat); bufnum++;
+				}
+			}
+			nownote++;
+			if (nownote >= numnotes) {
+				nownote = 0;
+				songend = true;
+			}
+			templong = note[nownote];
+			if (nownote == 0)
+				count = (templong>>12)-1;
+			quanter = (240/trquant[(templong>>8)&15]);
+			countstop = (((templong>>12)+(quanter>>1)) / quanter) * quanter;
+		}
+		for(i=0;i<bufnum;i+=3)
+			opl->write(databuf[i+1],databuf[i+2]);
+	}
+	return !songend;
+}
+
+void CksmPlayer::rewind(int subsong)
+{
+	unsigned int i,j,k;
+	unsigned char instbuf[11];
+	unsigned long templong;
+
+	songend = false;
+	opl->init(); opl->write(1,32); opl->write(4,0); opl->write(8,0); opl->write(0xbd,drumstat);
+
+	if (trchan[11] == 1) {
+	  for(i=0;i<11;i++)
+	    instbuf[i] = inst[trinst[11]][i];
+	  instbuf[1] = ((instbuf[1]&192)|(trvol[11])^63);
+	  setinst(6,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]);
+	  for(i=0;i<5;i++)
+	    instbuf[i] = inst[trinst[12]][i];
+	  for(i=5;i<11;i++)
+	    instbuf[i] = inst[trinst[15]][i];
+	  instbuf[1] = ((instbuf[1]&192)|(trvol[12])^63);
+	  instbuf[6] = ((instbuf[6]&192)|(trvol[15])^63);
+	  setinst(7,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]);
+	  for(i=0;i<5;i++)
+	    instbuf[i] = inst[trinst[14]][i];
+	  for(i=5;i<11;i++)
+	    instbuf[i] = inst[trinst[13]][i];
+	  instbuf[1] = ((instbuf[1]&192)|(trvol[14])^63);
+	  instbuf[6] = ((instbuf[6]&192)|(trvol[13])^63);
+	  setinst(8,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]);
+	}
+
+	for(i=0;i<numchans;i++)
+	{
+		chantrack[i] = 0;
+		chanage[i] = 0;
+	}
+	j = 0;
+	for(i=0;i<16;i++)
+		if ((trchan[i] > 0) && (j < numchans))
+		{
+			k = trchan[i];
+			while ((j < numchans) && (k > 0))
+			{
+				chantrack[j] = i;
+				k--;
+				j++;
+			}
+		}
+	for(i=0;i<numchans;i++)
+	{
+		for(j=0;j<11;j++)
+			instbuf[j] = inst[trinst[chantrack[i]]][j];
+		instbuf[1] = ((instbuf[1]&192)|(63-trvol[chantrack[i]]));
+		setinst(i,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]);
+		chanfreq[i] = 0;
+	}
+	k = 0;
+	templong = *note;
+	count = (templong>>12)-1;
+	countstop = (templong>>12)-1;
+	nownote = 0;
+}
+
+std::string CksmPlayer::getinstrument(unsigned int n)
+{
+	if(trchan[n])
+		return std::string(instname[trinst[n]]);
+	else
+		return std::string();
+}
+
+/*** private methods *************************************/
+
+void CksmPlayer::loadinsts(binistream *f)
+{
+  int i, j;
+
+  for(i = 0; i < 256; i++) {
+    f->readString(instname[i], 20);
+    for(j = 0; j < 11; j++) inst[i][j] = f->readInt(1);
+    f->ignore(2);
+  }
+}
+
+void CksmPlayer::setinst(int chan,
+			 unsigned char v0,unsigned char v1,unsigned char v2,
+			 unsigned char v3,unsigned char v4,unsigned char v5,
+			 unsigned char v6,unsigned char v7,unsigned char v8,
+			 unsigned char v9,unsigned char v10)
+{
+	int offs;
+
+	opl->write(0xa0+chan,0);
+	opl->write(0xb0+chan,0);
+	opl->write(0xc0+chan,v10);
+	offs = op_table[chan];
+	opl->write(0x20+offs,v5);
+	opl->write(0x40+offs,v6);
+	opl->write(0x60+offs,v7);
+	opl->write(0x80+offs,v8);
+	opl->write(0xe0+offs,v9);
+	offs+=3;
+	opl->write(0x20+offs,v0);
+	opl->write(0x40+offs,v1);
+	opl->write(0x60+offs,v2);
+	opl->write(0x80+offs,v3);
+	opl->write(0xe0+offs,v4);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/ksm.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,62 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * ksm.h - KSM Player for AdPlug by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "player.h"
+
+class CksmPlayer: public CPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	CksmPlayer(Copl *newopl)
+		: CPlayer(newopl), note(0)
+	{ };
+	~CksmPlayer()
+	{ if(note) delete [] note; };
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+	bool update();
+	void rewind(int subsong);
+	float getrefresh()
+	{ return 240.0f; };
+
+	std::string gettype()
+	{ return std::string("Ken Silverman's Music Format"); };
+	unsigned int getinstruments()
+	{ return 16; };
+	std::string getinstrument(unsigned int n);
+
+private:
+	static const unsigned int adlibfreq[63];
+
+	unsigned long count,countstop,chanage[18],*note;
+	unsigned short numnotes;
+	unsigned int nownote,numchans,drumstat;
+	unsigned char trinst[16],trquant[16],trchan[16],trvol[16],inst[256][11],databuf[2048],chanfreq[18],chantrack[18];
+	char instname[256][20];
+
+	bool songend;
+
+	void loadinsts(binistream *f);
+	void setinst(int chan,unsigned char v0,unsigned char v1,unsigned char v2,unsigned char v3,
+				 unsigned char v4,unsigned char v5,unsigned char v6,unsigned char v7,
+				 unsigned char v8,unsigned char v9,unsigned char v10);
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/lds.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,676 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * lds.cpp - LOUDNESS Player by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include <string.h>
+
+#include "lds.h"
+#include "debug.h"
+
+// Note frequency table (16 notes / octave)
+const unsigned short CldsPlayer::frequency[] = {
+  343, 344, 345, 347, 348, 349, 350, 352, 353, 354, 356, 357, 358,
+  359, 361, 362, 363, 365, 366, 367, 369, 370, 371, 373, 374, 375,
+  377, 378, 379, 381, 382, 384, 385, 386, 388, 389, 391, 392, 393,
+  395, 396, 398, 399, 401, 402, 403, 405, 406, 408, 409, 411, 412,
+  414, 415, 417, 418, 420, 421, 423, 424, 426, 427, 429, 430, 432,
+  434, 435, 437, 438, 440, 442, 443, 445, 446, 448, 450, 451, 453,
+  454, 456, 458, 459, 461, 463, 464, 466, 468, 469, 471, 473, 475,
+  476, 478, 480, 481, 483, 485, 487, 488, 490, 492, 494, 496, 497,
+  499, 501, 503, 505, 506, 508, 510, 512, 514, 516, 518, 519, 521,
+  523, 525, 527, 529, 531, 533, 535, 537, 538, 540, 542, 544, 546,
+  548, 550, 552, 554, 556, 558, 560, 562, 564, 566, 568, 571, 573,
+  575, 577, 579, 581, 583, 585, 587, 589, 591, 594, 596, 598, 600,
+  602, 604, 607, 609, 611, 613, 615, 618, 620, 622, 624, 627, 629,
+  631, 633, 636, 638, 640, 643, 645, 647, 650, 652, 654, 657, 659,
+  662, 664, 666, 669, 671, 674, 676, 678, 681, 683
+};
+
+// Vibrato (sine) table
+const unsigned char CldsPlayer::vibtab[] = {
+  0, 13, 25, 37, 50, 62, 74, 86, 98, 109, 120, 131, 142, 152, 162,
+  171, 180, 189, 197, 205, 212, 219, 225, 231, 236, 240, 244, 247,
+  250, 252, 254, 255, 255, 255, 254, 252, 250, 247, 244, 240, 236,
+  231, 225, 219, 212, 205, 197, 189, 180, 171, 162, 152, 142, 131,
+  120, 109, 98, 86, 74, 62, 50, 37, 25, 13
+};
+
+// Tremolo (sine * sine) table
+const unsigned char CldsPlayer::tremtab[] = {
+  0, 0, 1, 1, 2, 4, 5, 7, 10, 12, 15, 18, 21, 25, 29, 33, 37, 42, 47,
+  52, 57, 62, 67, 73, 79, 85, 90, 97, 103, 109, 115, 121, 128, 134,
+  140, 146, 152, 158, 165, 170, 176, 182, 188, 193, 198, 203, 208,
+  213, 218, 222, 226, 230, 234, 237, 240, 243, 245, 248, 250, 251,
+  253, 254, 254, 255, 255, 255, 254, 254, 253, 251, 250, 248, 245,
+  243, 240, 237, 234, 230, 226, 222, 218, 213, 208, 203, 198, 193,
+  188, 182, 176, 170, 165, 158, 152, 146, 140, 134, 127, 121, 115,
+  109, 103, 97, 90, 85, 79, 73, 67, 62, 57, 52, 47, 42, 37, 33, 29,
+  25, 21, 18, 15, 12, 10, 7, 5, 4, 2, 1, 1, 0
+};
+
+// 'maxsound' is maximum number of patches (instruments)
+// 'maxpos' is maximum number of entries in position list (orderlist)
+const unsigned short CldsPlayer::maxsound = 0x3f, CldsPlayer::maxpos = 0xff;
+
+/*** public methods *************************************/
+
+CldsPlayer::CldsPlayer(Copl *newopl)
+  : CPlayer(newopl), soundbank(0), positions(0), patterns(0)
+{
+}
+
+CldsPlayer::~CldsPlayer()
+{
+  if(soundbank) delete [] soundbank;
+  if(positions) delete [] positions;
+  if(patterns) delete [] patterns;
+}
+
+bool CldsPlayer::load(const std::string &filename, const CFileProvider &fp)
+{
+  binistream	*f;
+  unsigned int	i, j;
+  SoundBank	*sb;
+
+  // file validation section (actually just an extension check)
+  if(!fp.extension(filename, ".lds")) return false;
+  f = fp.open(filename); if(!f) return false;
+
+  // file load section (header)
+  mode = f->readInt(1);
+  if(mode > 2) { fp.close(f); return false; }
+  speed = f->readInt(2);
+  tempo = f->readInt(1);
+  pattlen = f->readInt(1);
+  for(i = 0; i < 9; i++) chandelay[i] = f->readInt(1);
+  regbd = f->readInt(1);
+
+  // load patches
+  numpatch = f->readInt(2);
+  soundbank = new SoundBank[numpatch];
+  for(i = 0; i < numpatch; i++) {
+    sb = &soundbank[i];
+    sb->mod_misc = f->readInt(1); sb->mod_vol = f->readInt(1);
+    sb->mod_ad = f->readInt(1); sb->mod_sr = f->readInt(1);
+    sb->mod_wave = f->readInt(1); sb->car_misc = f->readInt(1);
+    sb->car_vol = f->readInt(1); sb->car_ad = f->readInt(1);
+    sb->car_sr = f->readInt(1); sb->car_wave = f->readInt(1);
+    sb->feedback = f->readInt(1); sb->keyoff = f->readInt(1);
+    sb->portamento = f->readInt(1); sb->glide = f->readInt(1);
+    sb->finetune = f->readInt(1); sb->vibrato = f->readInt(1);
+    sb->vibdelay = f->readInt(1); sb->mod_trem = f->readInt(1);
+    sb->car_trem = f->readInt(1); sb->tremwait = f->readInt(1);
+    sb->arpeggio = f->readInt(1);
+    for(j = 0; j < 12; j++) sb->arp_tab[j] = f->readInt(1);
+    sb->start = f->readInt(2); sb->size = f->readInt(2);
+    sb->fms = f->readInt(1); sb->transp = f->readInt(2);
+    sb->midinst = f->readInt(1); sb->midvelo = f->readInt(1);
+    sb->midkey = f->readInt(1); sb->midtrans = f->readInt(1);
+    sb->middum1 = f->readInt(1); sb->middum2 = f->readInt(1);
+  }
+
+  // load positions
+  numposi = f->readInt(2);
+  positions = new Position[9 * numposi];
+  for(i = 0; i < numposi; i++)
+    for(j = 0; j < 9; j++) {
+      /*
+       * patnum is a pointer inside the pattern space, but patterns are 16bit
+       * word fields anyway, so it ought to be an even number (hopefully) and
+       * we can just divide it by 2 to get our array index of 16bit words.
+       */
+      positions[i * 9 + j].patnum = f->readInt(2) / 2;
+      positions[i * 9 + j].transpose = f->readInt(1);
+    }
+
+  AdPlug_LogWrite("CldsPlayer::load(\"%s\",fp): loading LOUDNESS file: mode = "
+		  "%d, pattlen = %d, numpatch = %d, numposi = %d\n",
+		  filename.c_str(), mode, pattlen, numpatch, numposi);
+
+  // load patterns
+  f->ignore(2);		// ignore # of digital sounds (not played by this player)
+  patterns = new unsigned short[(fp.filesize(f) - f->pos()) / 2 + 1];
+  for(i = 0; !f->eof(); i++)
+    patterns[i] = f->readInt(2);
+
+  fp.close(f);
+  rewind(0);
+  return true;
+}
+
+bool CldsPlayer::update()
+{
+  unsigned short	comword, freq, octave, chan, tune, wibc, tremc, arpreg;
+  bool			vbreak;
+  unsigned char		level, regnum, comhi, comlo;
+  int			i;
+  Channel		*c;
+
+  if(!playing) return false;
+
+  // handle fading
+  if(fadeonoff)
+    if(fadeonoff <= 128) {
+      if(allvolume > fadeonoff || allvolume == 0)
+	allvolume -= fadeonoff;
+      else {
+	allvolume = 1;
+	fadeonoff = 0;
+	if(hardfade != 0) {
+	  playing = false;
+	  hardfade = 0;
+	  for(i = 0; i < 9; i++)
+	    channel[i].keycount = 1;
+	}
+      }
+    } else
+      if(((allvolume + (0x100 - fadeonoff)) & 0xff) <= mainvolume)
+	allvolume += 0x100 - fadeonoff;
+      else {
+	allvolume = mainvolume;
+	fadeonoff = 0;
+      }
+
+  // handle channel delay
+  for(chan = 0; chan < 9; chan++) {
+    c = &channel[chan];
+    if(c->chancheat.chandelay)
+      if(!(--c->chancheat.chandelay))
+	playsound(c->chancheat.sound, chan, c->chancheat.high);
+  }
+
+  // handle notes
+  if(!tempo_now) {
+    vbreak = false;
+    for(chan = 0; chan < 9; chan++) {
+      c = &channel[chan];
+      if(!c->packwait) {
+	unsigned short	patnum = positions[posplay * 9 + chan].patnum;
+	unsigned char	transpose = positions[posplay * 9 + chan].transpose;
+
+	comword = patterns[patnum + c->packpos];
+	comhi = comword >> 8; comlo = comword & 0xff;
+	if(comword)
+	  if(comhi == 0x80)
+	    c->packwait = comlo;
+	  else
+	    if(comhi >= 0x80) {
+	      switch(comhi) {
+	      case 0xff:
+		c->volcar = (((c->volcar & 0x3f) * comlo) >> 6) & 0x3f;
+		if(fmchip[0xc0 + chan] & 1)
+		  c->volmod = (((c->volmod & 0x3f) * comlo) >> 6) & 0x3f;
+		break;
+	      case 0xfe:
+		tempo = comword & 0x3f;
+		break;
+	      case 0xfd:
+		c->nextvol = comlo;
+		break;
+	      case 0xfc:
+		playing = false;
+		// in real player there's also full keyoff here, but we don't need it
+		break;
+	      case 0xfb:
+		c->keycount = 1;
+		break;
+	      case 0xfa:
+		vbreak = true;
+		jumppos = (posplay + 1) & maxpos;
+		break;
+	      case 0xf9:
+		vbreak = true;
+		jumppos = comlo & maxpos;
+		jumping = 1;
+		if(jumppos < posplay) songlooped = true;
+		break;
+	      case 0xf8:
+		c->lasttune = 0;
+		break;
+	      case 0xf7:
+		c->vibwait = 0;
+		// PASCAL: c->vibspeed = ((comlo >> 4) & 15) + 2;
+		c->vibspeed = (comlo >> 4) + 2;
+		c->vibrate = (comlo & 15) + 1;
+		break;
+	      case 0xf6:
+		c->glideto = comlo;
+		break;
+	      case 0xf5:
+		c->finetune = comlo;
+		break;
+	      case 0xf4:
+		if(!hardfade) {
+		  allvolume = mainvolume = comlo;
+		  fadeonoff = 0;
+		}
+		break;
+	      case 0xf3:
+		if(!hardfade) fadeonoff = comlo;
+		break;
+	      case 0xf2:
+		c->trmstay = comlo;
+		break;
+	      case 0xf1:	// panorama
+	      case 0xf0:	// progch
+		// MIDI commands (unhandled)
+		AdPlug_LogWrite("CldsPlayer(): not handling MIDI command 0x%x, "
+				"value = 0x%x\n", comhi);
+		break;
+	      default:
+		if(comhi < 0xa0)
+		  c->glideto = comhi & 0x1f;
+		else
+		  AdPlug_LogWrite("CldsPlayer(): unknown command 0x%x encountered!"
+				  " value = 0x%x\n", comhi, comlo);
+		break;
+	      }
+	    } else {
+	      unsigned char	sound;
+	      unsigned short	high;
+	      signed char	transp = transpose & 127;
+
+	      /*
+	       * Originally, in assembler code, the player first shifted
+	       * logically left the transpose byte by 1 and then shifted
+	       * arithmetically right the same byte to achieve the final,
+	       * signed transpose value. Since we can't do arithmetic shifts
+	       * in C, we just duplicate the 7th bit into the 8th one and
+	       * discard the 8th one completely.
+	       */
+
+	      if(transpose & 64) transp |= 128;
+
+	      if(transpose & 128) {
+		sound = (comlo + transp) & maxsound;
+		high = comhi << 4;
+	      } else {
+		sound = comlo & maxsound;
+		high = (comhi + transp) << 4;
+	      }
+
+	      /*
+		PASCAL:
+	      sound = comlo & maxsound;
+	      high = (comhi + (((transpose + 0x24) & 0xff) - 0x24)) << 4;
+	      */
+
+	      if(!chandelay[chan])
+		playsound(sound, chan, high);
+	      else {
+		c->chancheat.chandelay = chandelay[chan];
+		c->chancheat.sound = sound;
+		c->chancheat.high = high;
+	      }
+	    }
+
+	c->packpos++;
+      } else
+	c->packwait--;
+    }
+
+    tempo_now = tempo;
+    /*
+      The continue table is updated here, but this is only used in the
+      original player, which can be paused in the middle of a song and then
+      unpaused. Since AdPlug does all this for us automatically, we don't
+      have a continue table here. The continue table update code is noted
+      here for reference only.
+
+      if(!pattplay) {
+        conttab[speed & maxcont].position = posplay & 0xff;
+        conttab[speed & maxcont].tempo = tempo;
+      }
+    */
+    pattplay++;
+    if(vbreak) {
+      pattplay = 0;
+      for(i = 0; i < 9; i++) channel[i].packpos = channel[i].packwait = 0;
+      posplay = jumppos;
+    } else
+      if(pattplay >= pattlen) {
+	pattplay = 0;
+	for(i = 0; i < 9; i++) channel[i].packpos = channel[i].packwait = 0;
+	posplay = (posplay + 1) & maxpos;
+      }
+  } else
+    tempo_now--;
+
+  // make effects
+  for(chan = 0; chan < 9; chan++) {
+    c = &channel[chan];
+    regnum = op_table[chan];
+    if(c->keycount > 0) {
+      if(c->keycount == 1)
+	setregs_adv(0xb0 + chan, 0xdf, 0);
+      c->keycount--;
+    }
+
+    // arpeggio
+    if(c->arp_size == 0)
+      arpreg = 0;
+    else {
+      arpreg = c->arp_tab[c->arp_pos] << 4;
+      if(arpreg == 0x800) {
+	if(c->arp_pos > 0) c->arp_tab[0] = c->arp_tab[c->arp_pos - 1];
+	c->arp_size = 1; c->arp_pos = 0;
+	arpreg = c->arp_tab[0] << 4;
+      }
+
+      if(c->arp_count == c->arp_speed) {
+	c->arp_pos++;
+	if(c->arp_pos >= c->arp_size) c->arp_pos = 0;
+	c->arp_count = 0;
+      } else
+	c->arp_count++;
+    }
+
+    // glide & portamento
+    if(c->lasttune && (c->lasttune != c->gototune)) {
+      if(c->lasttune > c->gototune) {
+	if(c->lasttune - c->gototune < c->portspeed)
+	  c->lasttune = c->gototune;
+	else
+	  c->lasttune -= c->portspeed;
+      } else {
+	if(c->gototune - c->lasttune < c->portspeed)
+	  c->lasttune = c->gototune;
+	else
+	  c->lasttune += c->portspeed;
+      }
+
+      if(arpreg >= 0x800)
+	arpreg = c->lasttune - (arpreg ^ 0xff0) - 16;
+      else
+	arpreg += c->lasttune;
+
+      freq = frequency[arpreg % (12 * 16)];
+      octave = arpreg / (12 * 16) - 1;
+      setregs(0xa0 + chan, freq & 0xff);
+      setregs_adv(0xb0 + chan, 0x20, ((octave << 2) + (freq >> 8)) & 0xdf);
+    } else {
+      // vibrato
+      if(!c->vibwait) {
+	if(c->vibrate) {
+	  wibc = vibtab[c->vibcount & 0x3f] * c->vibrate;
+
+	  if((c->vibcount & 0x40) == 0)
+	    tune = c->lasttune + (wibc >> 8);
+	  else
+	    tune = c->lasttune - (wibc >> 8);
+
+	  if(arpreg >= 0x800)
+	    tune = tune - (arpreg ^ 0xff0) - 16;
+	  else
+	    tune += arpreg;
+
+	  freq = frequency[tune % (12 * 16)];
+	  octave = tune / (12 * 16) - 1;
+	  setregs(0xa0 + chan, freq & 0xff);
+	  setregs_adv(0xb0 + chan, 0x20, ((octave << 2) + (freq >> 8)) & 0xdf);
+	  c->vibcount += c->vibspeed;
+	} else
+	  if(c->arp_size != 0) {	// no vibrato, just arpeggio
+	    if(arpreg >= 0x800)
+	      tune = c->lasttune - (arpreg ^ 0xff0) - 16;
+	    else
+	      tune = c->lasttune + arpreg;
+
+	    freq = frequency[tune % (12 * 16)];
+	    octave = tune / (12 * 16) - 1;
+	    setregs(0xa0 + chan, freq & 0xff);
+	    setregs_adv(0xb0 + chan, 0x20, ((octave << 2) + (freq >> 8)) & 0xdf);
+	  }
+      } else {	// no vibrato, just arpeggio
+	c->vibwait--;
+
+	if(c->arp_size != 0) {
+	  if(arpreg >= 0x800)
+	    tune = c->lasttune - (arpreg ^ 0xff0) - 16;
+	  else
+	    tune = c->lasttune + arpreg;
+
+	  freq = frequency[tune % (12 * 16)];
+	  octave = tune / (12 * 16) - 1;
+	  setregs(0xa0 + chan, freq & 0xff);
+	  setregs_adv(0xb0 + chan, 0x20, ((octave << 2) + (freq >> 8)) & 0xdf);
+	}
+      }
+    }
+
+    // tremolo (modulator)
+    if(!c->trmwait) {
+      if(c->trmrate) {
+	tremc = tremtab[c->trmcount & 0x7f] * c->trmrate;
+	if((tremc >> 8) <= (c->volmod & 0x3f))
+	  level = (c->volmod & 0x3f) - (tremc >> 8);
+	else
+	  level = 0;
+
+	if(allvolume != 0 && (fmchip[0xc0 + chan] & 1))
+	  setregs_adv(0x40 + regnum, 0xc0, ((level * allvolume) >> 8) ^ 0x3f);
+	else
+	  setregs_adv(0x40 + regnum, 0xc0, level ^ 0x3f);
+
+	c->trmcount += c->trmspeed;
+      } else
+	if(allvolume != 0 && (fmchip[0xc0 + chan] & 1))
+	  setregs_adv(0x40 + regnum, 0xc0, ((((c->volmod & 0x3f) * allvolume) >> 8) ^ 0x3f) & 0x3f);
+	else
+	  setregs_adv(0x40 + regnum, 0xc0, (c->volmod ^ 0x3f) & 0x3f);
+    } else {
+      c->trmwait--;
+      if(allvolume != 0 && (fmchip[0xc0 + chan] & 1))
+	setregs_adv(0x40 + regnum, 0xc0, ((((c->volmod & 0x3f) * allvolume) >> 8) ^ 0x3f) & 0x3f);
+    }
+
+    // tremolo (carrier)
+    if(!c->trcwait) {
+      if(c->trcrate) {
+	tremc = tremtab[c->trccount & 0x7f] * c->trcrate;
+	if((tremc >> 8) <= (c->volcar & 0x3f))
+	  level = (c->volcar & 0x3f) - (tremc >> 8);
+	else
+	  level = 0;
+
+	if(allvolume != 0)
+	  setregs_adv(0x43 + regnum, 0xc0, ((level * allvolume) >> 8) ^ 0x3f);
+	else
+	  setregs_adv(0x43 + regnum, 0xc0, level ^ 0x3f);
+	c->trccount += c->trcspeed;
+      } else
+	if(allvolume != 0)
+	  setregs_adv(0x43 + regnum, 0xc0, ((((c->volcar & 0x3f) * allvolume) >> 8) ^ 0x3f) & 0x3f);
+	else
+	  setregs_adv(0x43 + regnum, 0xc0, (c->volcar ^ 0x3f) & 0x3f);
+    } else {
+      c->trcwait--;
+      if(allvolume != 0)
+	setregs_adv(0x43 + regnum, 0xc0, ((((c->volcar & 0x3f) * allvolume) >> 8) ^ 0x3f) & 0x3f);
+    }
+  }
+
+  return (!playing || songlooped) ? false : true;
+}
+
+void CldsPlayer::rewind(int subsong)
+{
+  int i;
+
+  // init all with 0
+  tempo_now = 3; playing = true; songlooped = false;
+  jumping = fadeonoff = allvolume = hardfade = pattplay = posplay = jumppos =
+    mainvolume = 0;
+  memset(channel, 0, sizeof(channel));
+  memset(fmchip, 0, sizeof(fmchip));
+
+  // OPL2 init
+  opl->init();				// Reset OPL chip
+  opl->write(1, 0x20);
+  opl->write(8, 0);
+  opl->write(0xbd, regbd);
+
+  for(i = 0; i < 9; i++) {
+    opl->write(0x20 + op_table[i], 0);
+    opl->write(0x23 + op_table[i], 0);
+    opl->write(0x40 + op_table[i], 0x3f);
+    opl->write(0x43 + op_table[i], 0x3f);
+    opl->write(0x60 + op_table[i], 0xff);
+    opl->write(0x63 + op_table[i], 0xff);
+    opl->write(0x80 + op_table[i], 0xff);
+    opl->write(0x83 + op_table[i], 0xff);
+    opl->write(0xe0 + op_table[i], 0);
+    opl->write(0xe3 + op_table[i], 0);
+    opl->write(0xa0 + i, 0);
+    opl->write(0xb0 + i, 0);
+    opl->write(0xc0 + i, 0);
+  }
+}
+
+/*** private methods *************************************/
+
+void CldsPlayer::playsound(int inst_number, int channel_number, int tunehigh)
+{
+  Channel		*c = &channel[channel_number];		// current channel
+  SoundBank		*i = &soundbank[inst_number];		// current instrument
+  unsigned int		regnum = op_table[channel_number];	// channel's OPL2 register
+  unsigned char		volcalc, octave;
+  unsigned short	freq;
+
+  // set fine tune
+  tunehigh += ((i->finetune + c->finetune + 0x80) & 0xff) - 0x80;
+
+  // arpeggio handling
+  if(!i->arpeggio) {
+    unsigned short	arpcalc = i->arp_tab[0] << 4;
+
+    if(arpcalc > 0x800)
+      tunehigh = tunehigh - (arpcalc ^ 0xff0) - 16;
+    else
+      tunehigh += arpcalc;
+  }
+
+  // glide handling
+  if(c->glideto != 0) {
+    c->gototune = tunehigh;
+    c->portspeed = c->glideto;
+    c->glideto = c->finetune = 0;
+    return;
+  }
+
+  // set modulator registers
+  setregs(0x20 + regnum, i->mod_misc);
+  volcalc = i->mod_vol;
+  if(!c->nextvol || !(i->feedback & 1))
+    c->volmod = volcalc;
+  else
+    c->volmod = (volcalc & 0xc0) | ((((volcalc & 0x3f) * c->nextvol) >> 6));
+
+  if((i->feedback & 1) == 1 && allvolume != 0)
+    setregs(0x40 + regnum, ((c->volmod & 0xc0) | (((c->volmod & 0x3f) * allvolume) >> 8)) ^ 0x3f);
+  else
+    setregs(0x40 + regnum, c->volmod ^ 0x3f);
+  setregs(0x60 + regnum, i->mod_ad);
+  setregs(0x80 + regnum, i->mod_sr);
+  setregs(0xe0 + regnum, i->mod_wave);
+
+  // Set carrier registers
+  setregs(0x23 + regnum, i->car_misc);
+  volcalc = i->car_vol;
+  if(!c->nextvol)
+    c->volcar = volcalc;
+  else
+    c->volcar = (volcalc & 0xc0) | ((((volcalc & 0x3f) * c->nextvol) >> 6));
+
+  if(allvolume)
+    setregs(0x43 + regnum, ((c->volcar & 0xc0) | (((c->volcar & 0x3f) * allvolume) >> 8)) ^ 0x3f);
+  else
+    setregs(0x43 + regnum, c->volcar ^ 0x3f);
+  setregs(0x63 + regnum, i->car_ad);
+  setregs(0x83 + regnum, i->car_sr);
+  setregs(0xe3 + regnum, i->car_wave);
+  setregs(0xc0 + channel_number, i->feedback);
+  setregs_adv(0xb0 + channel_number, 0xdf, 0);		// key off
+
+  freq = frequency[tunehigh % (12 * 16)];
+  octave = tunehigh / (12 * 16) - 1;
+  if(!i->glide) {
+    if(!i->portamento || !c->lasttune) {
+      setregs(0xa0 + channel_number, freq & 0xff);
+      setregs(0xb0 + channel_number, (octave << 2) + 0x20 + (freq >> 8));
+      c->lasttune = c->gototune = tunehigh;
+    } else {
+      c->gototune = tunehigh;
+      c->portspeed = i->portamento;
+      setregs_adv(0xb0 + channel_number, 0xdf, 0x20);	// key on
+    }
+  } else {
+    setregs(0xa0 + channel_number, freq & 0xff);
+    setregs(0xb0 + channel_number, (octave << 2) + 0x20 + (freq >> 8));
+    c->lasttune = tunehigh;
+    c->gototune = tunehigh + ((i->glide + 0x80) & 0xff) - 0x80;	// set destination
+    c->portspeed = i->portamento;
+  }
+
+  if(!i->vibrato)
+    c->vibwait = c->vibspeed = c->vibrate = 0;
+  else {
+    c->vibwait = i->vibdelay;
+    // PASCAL:    c->vibspeed = ((i->vibrato >> 4) & 15) + 1;
+    c->vibspeed = (i->vibrato >> 4) + 2;
+    c->vibrate = (i->vibrato & 15) + 1;
+  }
+
+  if(!(c->trmstay & 0xf0)) {
+    c->trmwait = (i->tremwait & 0xf0) >> 3;
+    // PASCAL:    c->trmspeed = (i->mod_trem >> 4) & 15;
+    c->trmspeed = i->mod_trem >> 4;
+    c->trmrate = i->mod_trem & 15;
+    c->trmcount = 0;
+  }
+
+  if(!(c->trmstay & 0x0f)) {
+    c->trcwait = (i->tremwait & 15) << 1;
+    // PASCAL:    c->trcspeed = (i->car_trem >> 4) & 15;
+    c->trcspeed = i->car_trem >> 4;
+    c->trcrate = i->car_trem & 15;
+    c->trccount = 0;
+  }
+
+  c->arp_size = i->arpeggio & 15;
+  c->arp_speed = i->arpeggio >> 4;
+  memcpy(c->arp_tab, i->arp_tab, 12);
+  c->keycount = i->keyoff;
+  c->nextvol = c->glideto = c->finetune = c->vibcount = c->arp_pos = c->arp_count = 0;
+}
+
+inline void CldsPlayer::setregs(unsigned char reg, unsigned char val)
+{
+  if(fmchip[reg] == val) return;
+
+  fmchip[reg] = val;
+  opl->write(reg, val);
+}
+
+inline void CldsPlayer::setregs_adv(unsigned char reg, unsigned char mask,
+				    unsigned char val)
+{
+  setregs(reg, (fmchip[reg] & mask) | val);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/lds.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,91 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * lds.h - LOUDNESS Player by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "player.h"
+
+class CldsPlayer: public CPlayer
+{
+ public:
+  static CPlayer *factory(Copl *newopl) { return new CldsPlayer(newopl); }
+
+  CldsPlayer(Copl *newopl);
+  virtual ~CldsPlayer();
+
+  bool load(const std::string &filename, const CFileProvider &fp);
+  virtual bool update();
+  virtual void rewind(int subsong = -1);
+  float getrefresh() { return 70.0f; }
+
+  std::string gettype() { return std::string("LOUDNESS Sound System"); }
+  unsigned int getorders() { return numposi; }
+  unsigned int getorder() { return posplay; }
+  unsigned int getrow() { return pattplay; }
+  unsigned int getspeed() { return speed; }
+  unsigned int getinstruments() { return numpatch; }
+
+ private:
+  typedef struct {
+    unsigned char	mod_misc, mod_vol, mod_ad, mod_sr, mod_wave,
+      car_misc, car_vol, car_ad, car_sr, car_wave, feedback, keyoff,
+      portamento, glide, finetune, vibrato, vibdelay, mod_trem, car_trem,
+      tremwait, arpeggio, arp_tab[12];
+    unsigned short	start, size;
+    unsigned char	fms;
+    unsigned short	transp;
+    unsigned char	midinst, midvelo, midkey, midtrans, middum1, middum2;
+  } SoundBank;
+
+  typedef struct {
+    unsigned short	gototune, lasttune, packpos;
+    unsigned char	finetune, glideto, portspeed, nextvol, volmod, volcar,
+      vibwait, vibspeed, vibrate, trmstay, trmwait, trmspeed, trmrate, trmcount,
+      trcwait, trcspeed, trcrate, trccount, arp_size, arp_speed, keycount,
+      vibcount, arp_pos, arp_count, packwait, arp_tab[12];
+
+    struct {
+      unsigned char	chandelay, sound;
+      unsigned short	high;
+    } chancheat;
+  } Channel;
+
+  typedef struct {
+    unsigned short	patnum;
+    unsigned char	transpose;
+  } Position;
+
+  static const unsigned short	frequency[];
+  static const unsigned char	vibtab[], tremtab[];
+  static const unsigned short	maxsound, maxpos;
+
+  SoundBank		*soundbank;
+  Channel		channel[9];
+  Position		*positions;
+  unsigned char		fmchip[0xff], jumping, fadeonoff, allvolume, hardfade,
+    tempo_now, pattplay, tempo, regbd, chandelay[9], mode, pattlen;
+  unsigned short	posplay, jumppos, *patterns, speed;
+  bool			playing, songlooped;
+  unsigned int		numpatch, numposi, patterns_size, mainvolume;
+
+  void		playsound(int inst_number, int channel_number, int tunehigh);
+  inline void	setregs(unsigned char reg, unsigned char val);
+  inline void	setregs_adv(unsigned char reg, unsigned char mask,
+			    unsigned char val);
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/mad.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,126 @@
+/*
+  Adplug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  mad.cpp - MAD loader by Riven the Mage <riven@ok.ru>
+*/
+
+#include "mad.h"
+
+/* -------- Public Methods -------------------------------- */
+
+CPlayer *CmadLoader::factory(Copl *newopl)
+{
+  return new CmadLoader(newopl);
+}
+
+bool CmadLoader::load(const std::string &filename, const CFileProvider &fp)
+{
+  binistream *f = fp.open(filename); if(!f) return false;
+  const unsigned char conv_inst[10] = { 2,1,10,9,4,3,6,5,8,7 };
+  unsigned int i, j, k, t = 0;
+
+  // 'MAD+' - signed ?
+  char id[4]; f->readString(id, 4);
+  if (strncmp(id,"MAD+",4)) { fp.close(f); return false; }
+
+  // load instruments
+  for(i = 0; i < 9; i++) {
+    f->readString(instruments[i].name, 8);
+    for(j = 0; j < 12; j++) instruments[i].data[j] = f->readInt(1);
+  }
+
+  f->ignore(1);
+
+  // data for Protracker
+  length = f->readInt(1); nop = f->readInt(1); timer = f->readInt(1);
+
+  // init CmodPlayer
+  realloc_instruments(9);
+  realloc_order(length);
+  realloc_patterns(nop,32,9);
+  init_trackord();
+
+  // load tracks
+  for(i = 0; i < nop; i++)
+    for(k = 0; k < 32; k++)
+      for(j = 0; j < 9; j++) {
+	t = i * 9 + j;
+
+	// read event
+	unsigned char event = f->readInt(1);
+
+	// convert event
+	if (event < 0x61)
+	  tracks[t][k].note = event;
+	if (event == 0xFF) // 0xFF: Release note
+	  tracks[t][k].command = 8;
+	if (event == 0xFE) // 0xFE: Pattern Break
+	  tracks[t][k].command = 13;
+      }
+
+  // load order
+  for(i = 0; i < length; i++) order[i] = f->readInt(1) - 1;
+
+  fp.close(f);
+
+  // convert instruments
+  for(i = 0; i < 9; i++)
+    for(j = 0; j < 10; j++)
+      inst[i].data[conv_inst[j]] = instruments[i].data[j];
+
+  // data for Protracker
+  restartpos = 0;
+  initspeed = 1;
+
+  rewind(0);
+  return true;
+}
+
+void CmadLoader::rewind(int subsong)
+{
+	CmodPlayer::rewind(subsong);
+
+	// default instruments
+	for (int i=0;i<9;i++)
+	{
+		channel[i].inst = i;
+
+		channel[i].vol1 = 63 - (inst[i].data[10] & 63);
+		channel[i].vol2 = 63 - (inst[i].data[9] & 63);
+	}
+}
+
+float CmadLoader::getrefresh()
+{
+	return (float)timer;
+}
+
+std::string CmadLoader::gettype()
+{
+	return std::string("Mlat Adlib Tracker");
+}
+
+std::string CmadLoader::getinstrument(unsigned int n)
+{
+	return std::string(instruments[n].name,8);
+}
+
+unsigned int CmadLoader::getinstruments()
+{
+	return 9;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/mad.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,48 @@
+/*
+  Adplug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  mad.h - MAD loader by Riven the Mage <riven@ok.ru>
+*/
+
+#include "protrack.h"
+
+class CmadLoader: public CmodPlayer
+{
+public:
+	static CPlayer *factory(Copl *newopl);
+
+	CmadLoader(Copl *newopl) : CmodPlayer(newopl) { };
+
+	bool	load(const std::string &filename, const CFileProvider &fp);
+	void	rewind(int subsong);
+	float	getrefresh();
+
+	std::string	gettype();
+	std::string	getinstrument(unsigned int n);
+	unsigned int	getinstruments();
+
+private:
+
+	struct mad_instrument
+	{
+	  char            name[8];
+	  unsigned char   data[12]; // last two unused
+	} instruments[9];
+
+	unsigned char   timer;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/mid.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,1050 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * MIDI & MIDI-like file player - Last Update: 8/16/2000
+ *                  by Phil Hassey - www.imitationpickles.org
+ *                                   philhassey@hotmail.com
+ *
+ * Can play the following
+ *      .LAA - a raw save of a Lucas Arts Adlib music
+ *             or
+ *             a raw save of a LucasFilm Adlib music
+ *      .MID - a "midi" save of a Lucas Arts Adlib music
+ *           - or general MIDI files
+ *      .CMF - Creative Music Format
+ *      .SCI - the sierra "midi" format.
+ *             Files must be in the form
+ *             xxxNAME.sci
+ *             So that the loader can load the right patch file:
+ *             xxxPATCH.003  (patch.003 must be saved from the
+ *                            sierra resource from each game.)
+ *
+ * 6/2/2000:  v1.0 relased by phil hassey
+ *      Status:  LAA is almost perfect
+ *                      - some volumes are a bit off (intrument too quiet)
+ *               MID is fine (who wants to listen to MIDI vid adlib anyway)
+ *               CMF is okay (still needs the adlib rythm mode implemented
+ *                            for real)
+ * 6/6/2000:
+ *      Status:  SCI:  there are two SCI formats, orginal and advanced.
+ *                    original:  (Found in SCI/EGA Sierra Adventures)
+ *                               played almost perfectly, I believe
+ *                               there is one mistake in the instrument
+ *                               loader that causes some sounds to
+ *                               not be quite right.  Most sounds are fine.
+ *                    advanced:  (Found in SCI/VGA Sierra Adventures)
+ *                               These are multi-track files.  (Thus the
+ *                               player had to be modified to work with
+ *                               them.)  This works fine.
+ *                               There are also multiple tunes in each file.
+ *                               I think some of them are supposed to be
+ *                               played at the same time, but I'm not sure
+ *                               when.
+ *  8/16/200:
+ *      Status:  LAA: now EGA and VGA lucas games work pretty well
+ *
+ * Other acknowledgements:
+ *  Allegro - for the midi instruments and the midi volume table
+ *  SCUMM Revisited - for getting the .LAA / .MIDs out of those
+ *                    LucasArts files.
+ *  FreeSCI - for some information on the sci music files
+ *  SD - the SCI Decoder (to get all .sci out of the Sierra files)
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include "mid.h"
+#include "mididata.h"
+
+/*#define TESTING*/
+#ifdef TESTING
+#define midiprintf printf
+#else
+void CmidPlayer::midiprintf(char *format, ...)
+    {
+    }
+#endif
+
+CPlayer *CmidPlayer::factory(Copl *newopl)
+{
+  return new CmidPlayer(newopl);
+}
+
+unsigned char CmidPlayer::datalook(long pos)
+{
+    if (pos<0 || pos >= flen) return(0);
+    return(data[pos]);
+}
+
+unsigned long CmidPlayer::getnexti(unsigned long num)
+{
+	unsigned long v=0;
+	unsigned long i;
+
+    for (i=0; i<num; i++)
+        {
+        v+=(datalook(pos)<<(8*i)); pos++;
+        }
+    return(v);
+}
+
+unsigned long CmidPlayer::getnext(unsigned long num)
+{
+	unsigned long v=0;
+	unsigned long i;
+
+    for (i=0; i<num; i++)
+        {
+        v<<=8;
+        v+=datalook(pos); pos++;
+        }
+    return(v);
+}
+
+unsigned long CmidPlayer::getval()
+{
+    int v=0;
+	unsigned char b;
+
+    b=(unsigned char)getnext(1);
+	v=b&0x7f;
+	while ((b&0x80) !=0)
+		{
+        b=(unsigned char)getnext(1);
+        v = (v << 7) + (b & 0x7F);
+		}
+	return(v);
+}
+
+#define LUCAS_STYLE   1
+#define CMF_STYLE     2
+#define MIDI_STYLE    4
+#define SIERRA_STYLE  8
+
+#define ADLIB_MELODIC	0
+#define ADLIB_RYTHM	1
+
+bool CmidPlayer::load_sierra_ins(const std::string &fname, const CFileProvider &fp)
+{
+    long i,j,k,l;
+    unsigned char ins[28];
+    char *pfilename;
+    binistream *f;
+
+    pfilename = (char *)malloc(fname.length()+9);
+    strcpy(pfilename,fname.c_str());
+    j=0;
+    for(i=strlen(pfilename)-1; i >= 0; i--)
+      if(pfilename[i] == '/' || pfilename[i] == '\\') {
+	j = i+1;
+	break;
+      }
+    sprintf(pfilename+j+3,"patch.003");
+
+    f = fp.open(pfilename);
+    free(pfilename);
+    if(!f) return false;
+
+    f->ignore(2);
+    stins = 0;
+    for (i=0; i<2; i++)
+        {
+        for (k=0; k<48; k++)
+            {
+            l=i*48+k;
+            midiprintf ("\n%2d: ",l);
+            for (j=0; j<28; j++)
+                ins[j] = f->readInt(1);
+
+            myinsbank[l][0]=
+                (ins[9]*0x80) + (ins[10]*0x40) +
+                (ins[5]*0x20) + (ins[11]*0x10) +
+                ins[1];   //1=ins5
+            myinsbank[l][1]=
+                (ins[22]*0x80) + (ins[23]*0x40) +
+                (ins[18]*0x20) + (ins[24]*0x10) +
+                ins[14];  //1=ins18
+
+            myinsbank[l][2]=(ins[0]<<6)+ins[8];
+            myinsbank[l][3]=(ins[13]<<6)+ins[21];
+
+            myinsbank[l][4]=(ins[3]<<4)+ins[6];
+            myinsbank[l][5]=(ins[16]<<4)+ins[19];
+            myinsbank[l][6]=(ins[4]<<4)+ins[7];
+            myinsbank[l][7]=(ins[17]<<4)+ins[20];
+
+            myinsbank[l][8]=ins[26];
+            myinsbank[l][9]=ins[27];
+
+            myinsbank[l][10]=((ins[2]<<1))+(1-(ins[12]&1));
+            //(ins[12] ? 0:1)+((ins[2]<<1));
+
+            for (j=0; j<11; j++)
+                midiprintf ("%02X ",myinsbank[l][j]);
+			stins++;
+            }
+		f->ignore(2);
+        }
+
+    fp.close(f);
+    memcpy(smyinsbank, myinsbank, 128 * 16);
+    return true;
+}
+
+void CmidPlayer::sierra_next_section()
+{
+    int i,j;
+
+    for (i=0; i<16; i++)
+        track[i].on=0;
+
+    midiprintf("\n\nnext adv sierra section:\n");
+
+    pos=sierra_pos;
+    i=0;j=0;
+    while (i!=0xff)
+       {
+       getnext(1);
+       curtrack=j; j++;
+       track[curtrack].on=1;
+	   track[curtrack].spos = getnext(1);
+	   track[curtrack].spos += (getnext(1) << 8) + 4;	//4 best usually +3? not 0,1,2 or 5
+//       track[curtrack].spos=getnext(1)+(getnext(1)<<8)+4;		// dynamite!: doesn't optimize correctly!!
+       track[curtrack].tend=flen; //0xFC will kill it
+       track[curtrack].iwait=0;
+       track[curtrack].pv=0;
+       midiprintf ("track %d starts at %lx\n",curtrack,track[curtrack].spos);
+
+       getnext(2);
+       i=getnext(1);
+       }
+    getnext(2);
+    deltas=0x20;
+    sierra_pos=pos;
+    //getch();
+
+    fwait=0;
+    doing=1;
+}
+
+#define FILE_LUCAS      1
+#define FILE_MIDI       2
+#define FILE_CMF        3
+#define FILE_SIERRA     4
+#define FILE_ADVSIERRA  5
+#define FILE_OLDLUCAS   6
+
+bool CmidPlayer::load(const std::string &filename, const CFileProvider &fp)
+{
+    binistream *f = fp.open(filename); if(!f) return false;
+    int good;
+    unsigned char s[6];
+
+    f->readString((char *)s, 6);
+    good=0;
+    subsongs=0;
+    switch(s[0])
+        {
+        case 'A':
+            if (s[1]=='D' && s[2]=='L') good=FILE_LUCAS;
+            break;
+        case 'M':
+            if (s[1]=='T' && s[2]=='h' && s[3]=='d') good=FILE_MIDI;
+            break;
+        case 'C':
+            if (s[1]=='T' && s[2]=='M' && s[3]=='F') good=FILE_CMF;
+            break;
+        case 0x84:
+            if (s[1]==0x00 && load_sierra_ins(filename, fp))
+                if (s[2]==0xf0)
+                    good=FILE_ADVSIERRA;
+                    else
+                    good=FILE_SIERRA;
+            break;
+        default:
+            if (s[4]=='A' && s[5]=='D') good=FILE_OLDLUCAS;
+            break;
+        }
+
+    if (good!=0)
+		subsongs=1;
+    else {
+      fp.close(f);
+      return false;
+    }
+
+    type=good;
+    f->seek(0);
+    flen = fp.filesize(f);
+    data = new unsigned char [flen];
+    f->readString((char *)data, flen);
+
+    fp.close(f);
+    rewind(0);
+    return true;
+}
+
+void CmidPlayer::midi_write_adlib(unsigned int r, unsigned char v)
+{
+	opl->write(r,v);
+    adlib_data[r]=v;
+}
+
+unsigned char adlib_opadd[] = {0x00  ,0x01 ,0x02  ,0x08  ,0x09  ,0x0A  ,0x10 ,0x11  ,0x12};
+int ops[] = {0x20,0x20,0x40,0x40,0x60,0x60,0x80,0x80,0xe0,0xe0,0xc0};
+
+void CmidPlayer::midi_fm_instrument(int voice, unsigned char *inst)
+{
+    if ((adlib_style&SIERRA_STYLE)!=0)
+        midi_write_adlib(0xbd,0);  //just gotta make sure this happens..
+                                      //'cause who knows when it'll be
+                                      //reset otherwise.
+
+
+    midi_write_adlib(0x20+adlib_opadd[voice],inst[0]);
+    midi_write_adlib(0x23+adlib_opadd[voice],inst[1]);
+
+    if ((adlib_style&LUCAS_STYLE)!=0)
+        {
+        midi_write_adlib(0x43+adlib_opadd[voice],0x3f);
+        if ((inst[10] & 1)==0)
+            midi_write_adlib(0x40+adlib_opadd[voice],inst[2]);
+            else
+            midi_write_adlib(0x40+adlib_opadd[voice],0x3f);
+        }
+        else
+        {
+        if ((adlib_style&SIERRA_STYLE)!=0)
+            {
+            midi_write_adlib(0x40+adlib_opadd[voice],inst[2]);
+            midi_write_adlib(0x43+adlib_opadd[voice],inst[3]);
+            }
+            else
+            {
+            midi_write_adlib(0x40+adlib_opadd[voice],inst[2]);
+            if ((inst[10] & 1)==0)
+                midi_write_adlib(0x43+adlib_opadd[voice],inst[3]);
+                else
+                midi_write_adlib(0x43+adlib_opadd[voice],0);
+            }
+        }
+
+    midi_write_adlib(0x60+adlib_opadd[voice],inst[4]);
+    midi_write_adlib(0x63+adlib_opadd[voice],inst[5]);
+    midi_write_adlib(0x80+adlib_opadd[voice],inst[6]);
+    midi_write_adlib(0x83+adlib_opadd[voice],inst[7]);
+    midi_write_adlib(0xe0+adlib_opadd[voice],inst[8]);
+    midi_write_adlib(0xe3+adlib_opadd[voice],inst[9]);
+
+    midi_write_adlib(0xc0+voice,inst[10]);
+}
+
+void CmidPlayer::midi_fm_volume(int voice, int volume)
+{
+    int vol;
+
+    if ((adlib_style&SIERRA_STYLE)==0)  //sierra likes it loud!
+    {
+    vol=volume>>2;
+
+    if ((adlib_style&LUCAS_STYLE)!=0)
+        {
+        if ((adlib_data[0xc0+voice]&1)==1)
+            midi_write_adlib(0x40+adlib_opadd[voice], (unsigned 
+char)((63-vol) |
+            (adlib_data[0x40+adlib_opadd[voice]]&0xc0)));
+        midi_write_adlib(0x43+adlib_opadd[voice], (unsigned char)((63-vol) |
+            (adlib_data[0x43+adlib_opadd[voice]]&0xc0)));
+        }
+        else
+        {
+        if ((adlib_data[0xc0+voice]&1)==1)
+            midi_write_adlib(0x40+adlib_opadd[voice], (unsigned 
+char)((63-vol) |
+            (adlib_data[0x40+adlib_opadd[voice]]&0xc0)));
+        midi_write_adlib(0x43+adlib_opadd[voice], (unsigned char)((63-vol) |
+           (adlib_data[0x43+adlib_opadd[voice]]&0xc0)));
+        }
+    }
+}
+
+
+int fnums[] = {
+0x16b,0x181,0x198,0x1b0,0x1ca,0x1e5,0x202,0x220,0x241,0x263,0x287,0x2ae
+		  };
+
+void CmidPlayer::midi_fm_playnote(int voice, int note, int volume)
+{
+    int freq=fnums[note%12];
+    int oct=note/12;
+	int c;
+
+    midi_fm_volume(voice,volume);
+    midi_write_adlib(0xa0+voice,(unsigned char)(freq&0xff));
+
+	c=((freq&0x300) >> 8)+(oct<<2) + (1<<5);
+    midi_write_adlib(0xb0+voice,(unsigned char)c);
+}
+
+void CmidPlayer::midi_fm_endnote(int voice)
+{
+    //midi_fm_volume(voice,0);
+    //midi_write_adlib(0xb0+voice,0);
+
+    midi_write_adlib(0xb0+voice,(unsigned char)(adlib_data[0xb0+voice]&(255-32)));
+}
+
+void CmidPlayer::midi_fm_reset()
+{
+    int i;
+    for (i=0; i<256; i++)
+        midi_write_adlib(i,0);
+
+    midi_write_adlib(0x01, 0x20);
+    midi_write_adlib(0xBD,0xc0);
+}
+
+bool CmidPlayer::update()
+{
+    long w,v,note,vel,ctrl,nv,x,l,lnum;
+    int i=0,j,c;
+    int on,onl;
+    unsigned char ins[11];
+    int ret;
+
+    if (doing == 1)
+        {
+        // just get the first wait and ignore it :>
+        for (curtrack=0; curtrack<16; curtrack++)
+            if (track[curtrack].on)
+                {
+                pos=track[curtrack].pos;
+                if (type != FILE_SIERRA && type !=FILE_ADVSIERRA)
+                    track[curtrack].iwait+=getval();
+                    else
+                    track[curtrack].iwait+=getnext(1);
+                track[curtrack].pos=pos;
+                }
+        doing=0;
+        }
+
+    iwait=0;
+    ret=1;
+
+    while (iwait==0 && ret==1)
+        {
+        for (curtrack=0; curtrack<16; curtrack++)
+        if (track[curtrack].on && track[curtrack].iwait==0 &&
+            track[curtrack].pos < track[curtrack].tend)
+        {
+        pos=track[curtrack].pos;
+
+		v=getnext(1);
+
+        //  This is to do implied MIDI events.
+        if (v<0x80) {v=track[curtrack].pv; pos--;}
+        track[curtrack].pv=(unsigned char)v;
+
+		c=v&0x0f;
+        midiprintf ("[%2X]",v);
+        switch(v&0xf0)
+            {
+			case 0x80: /*note off*/
+				note=getnext(1); vel=getnext(1);
+                for (i=0; i<9; i++)
+                    if (chp[i][0]==c && chp[i][1]==note)
+                        {
+                        midi_fm_endnote(i);
+                        chp[i][0]=-1;
+                        }
+                break;
+            case 0x90: /*note on*/
+              //  doing=0;
+                note=getnext(1); vel=getnext(1);
+
+                if (ch[c].on!=0)
+                {
+                for (i=0; i<9; i++)
+                    chp[i][2]++;
+
+                j=0;
+                on=-1;onl=0;
+                for (i=0; i<9; i++)
+                    if (chp[i][0]==-1 && chp[i][2]>onl)
+                        { onl=chp[i][2]; on=i; j=1; }
+
+                if (on==-1)
+                    {
+                    onl=0;
+                    for (i=0; i<9; i++)
+                        if (chp[i][2]>onl)
+                            { onl=chp[i][2]; on=i; }
+                    }
+
+                 if (j==0)
+                    midi_fm_endnote(on);
+
+                 if (vel!=0 && ch[c].inum>=0 && ch[c].inum<128)
+                    {
+                    if (adlib_mode == ADLIB_MELODIC || c < 12)
+                        midi_fm_instrument(on,ch[c].ins);
+                        else
+                        {
+                        //the following fails to be effective
+                        //at doing rythm sounds .. (cmf blah)
+                        ins[0]=ins[1]=ch[c].ins[0];
+                        ins[2]=ins[3]=ch[c].ins[2];
+                        ins[4]=ins[5]=ch[c].ins[4];
+                        ins[6]=ins[7]=ch[c].ins[6];
+                        ins[8]=ins[9]=ch[c].ins[8];
+                        ins[10]=ch[c].ins[10]|1;
+                        midi_fm_instrument(on,ins);
+                        }
+
+                    if ((adlib_style&MIDI_STYLE)!=0)
+                        {
+                        nv=((ch[c].vol*vel)/128);
+                        if ((adlib_style&LUCAS_STYLE)!=0)
+                            nv*=2;
+                        if (nv>127) nv=127;
+                        nv=my_midi_fm_vol_table[nv];
+                        if ((adlib_style&LUCAS_STYLE)!=0)
+                            nv=(int)((float)sqrt((float)nv)*11);
+                        }
+                        else
+                        {
+                        nv=vel;
+                        }
+
+                    midi_fm_playnote(on,note+ch[c].nshift,nv*2);
+                    chp[on][0]=c;
+                    chp[on][1]=note;
+                    chp[on][2]=0;
+                    }
+                    else
+                    {
+                    if (vel==0)  //same code as end note
+                        {
+                        for (i=0; i<9; i++)
+                            if (chp[i][0]==c && chp[i][1]==note)
+                                {
+                               // midi_fm_volume(i,0);  // really end the note
+                                midi_fm_endnote(i);
+                                chp[i][0]=-1;
+                                }
+                        }
+                        else
+                        {        // i forget what this is for.
+                        chp[on][0]=-1;
+                        chp[on][2]=0;
+                        }
+                    }
+                midiprintf(" [%d:%d:%d:%d]\n",c,ch[c].inum,note,vel);
+                }
+                else
+                midiprintf ("off");
+                break;
+            case 0xa0: /*key after touch */
+                note=getnext(1); vel=getnext(1);
+                /*  //this might all be good
+                for (i=0; i<9; i++)
+                    if (chp[i][0]==c & chp[i][1]==note)
+                        
+midi_fm_playnote(i,note+cnote[c],my_midi_fm_vol_table[(cvols[c]*vel)/128]*2);
+                */
+                break;
+            case 0xb0: /*control change .. pitch bend? */
+                ctrl=getnext(1); vel=getnext(1);
+
+                switch(ctrl)
+                    {
+                    case 0x07:
+                        midiprintf ("(pb:%d: %d %d)",c,ctrl,vel);
+                        ch[c].vol=vel;
+                        midiprintf("vol");
+                        break;
+                    case 0x67:
+                        midiprintf ("\n\nhere:%d\n\n",vel);
+                        if ((adlib_style&CMF_STYLE)!=0)
+                            adlib_mode=vel;  // this gets faked - no mode change
+                        break;
+                    }
+                break;
+            case 0xc0: /*patch change*/
+				x=getnext(1);
+                ch[c].inum=x;
+                for (j=0; j<11; j++)
+                    ch[c].ins[j]=myinsbank[ch[c].inum][j];
+                break;
+            case 0xd0: /*chanel touch*/
+                x=getnext(1);
+                break;
+            case 0xe0: /*pitch wheel*/
+                x=getnext(1);
+                x=getnext(1);
+                break;
+            case 0xf0:
+                switch(v)
+                    {
+                    case 0xf0:
+                    case 0xf7: /*sysex*/
+						l=getval();
+                        if (datalook(pos+l)==0xf7)
+							i=1;
+                        midiprintf("{%d}",l);
+                        midiprintf("\n");
+
+                        if (datalook(pos)==0x7d &&
+                            datalook(pos+1)==0x10 &&
+                            datalook(pos+2)<16)
+							{
+                            adlib_style=LUCAS_STYLE|MIDI_STYLE;
+							for (i=0; i<l; i++)
+								{
+                                midiprintf ("%x ",datalook(pos+i));
+                                if ((i-3)%10 == 0) midiprintf("\n");
+								}
+                            midiprintf ("\n");
+                            getnext(1);
+                            getnext(1);
+							c=getnext(1);
+							getnext(1);
+
+                          //  getnext(22); //temp
+                            ch[c].ins[0]=(unsigned char)((getnext(1)<<4)+getnext(1));
+                            ch[c].ins[2]=(unsigned char)(0xff-(((getnext(1)<<4)+getnext(1))&0x3f));
+                            ch[c].ins[4]=(unsigned char)(0xff-((getnext(1)<<4)+getnext(1)));
+                            ch[c].ins[6]=(unsigned char)(0xff-((getnext(1)<<4)+getnext(1)));
+                            ch[c].ins[8]=(unsigned char)((getnext(1)<<4)+getnext(1));
+
+                            ch[c].ins[1]=(unsigned char)((getnext(1)<<4)+getnext(1));
+                            ch[c].ins[3]=(unsigned char)(0xff-(((getnext(1)<<4)+getnext(1))&0x3f));
+                            ch[c].ins[5]=(unsigned char)(0xff-((getnext(1)<<4)+getnext(1)));
+                            ch[c].ins[7]=(unsigned char)(0xff-((getnext(1)<<4)+getnext(1)));
+                            ch[c].ins[9]=(unsigned char)((getnext(1)<<4)+getnext(1));
+
+                            i=(getnext(1)<<4)+getnext(1);
+                            ch[c].ins[10]=i;
+
+                            //if ((i&1)==1) ch[c].ins[10]=1;
+
+                            midiprintf ("\n%d: ",c);
+							for (i=0; i<11; i++)
+                                midiprintf ("%2X ",ch[c].ins[i]);
+                            getnext(l-26);
+							}
+                            else
+                            {
+                            midiprintf("\n");
+                            for (j=0; j<l; j++)
+                                midiprintf ("%2X ",getnext(1));
+                            }
+
+                        midiprintf("\n");
+						if(i==1)
+							getnext(1);
+                        break;
+                    case 0xf1:
+                        break;
+                    case 0xf2:
+                        getnext(2);
+                        break;
+                    case 0xf3:
+                        getnext(1);
+                        break;
+                    case 0xf4:
+                        break;
+                    case 0xf5:
+                        break;
+                    case 0xf6: /*something*/
+                    case 0xf8:
+                    case 0xfa:
+                    case 0xfb:
+                    case 0xfc:
+                        //this ends the track for sierra.
+                        if (type == FILE_SIERRA ||
+                            type == FILE_ADVSIERRA)
+                            {
+                            track[curtrack].tend=pos;
+                            midiprintf ("endmark: %ld -- %lx\n",pos,pos);
+                            }
+                        break;
+                    case 0xfe:
+                        break;
+                    case 0xfd:
+                        break;
+                    case 0xff:
+                        v=getnext(1);
+                        l=getval();
+                        midiprintf ("\n");
+                        midiprintf("{%X_%X}",v,l);
+                        if (v==0x51)
+                            {
+                            lnum=getnext(l);
+                            msqtr=lnum; /*set tempo*/
+                            midiprintf ("(qtr=%ld)",msqtr);
+                            }
+                            else
+                            {
+                            for (i=0; i<l; i++)
+                                midiprintf ("%2X ",getnext(1));
+                            }
+                        break;
+					}
+                break;
+            default: midiprintf("!",v); /* if we get down here, a error occurred */
+			break;
+            }
+
+        if (pos < track[curtrack].tend)
+            {
+            if (type != FILE_SIERRA && type !=FILE_ADVSIERRA)
+                w=getval();
+                else
+                w=getnext(1);
+            track[curtrack].iwait=w;
+            /*
+            if (w!=0)
+                {
+                midiprintf("\n<%d>",w);
+                f = 
+((float)w/(float)deltas)*((float)msqtr/(float)1000000);
+                if (doing==1) f=0; //not playing yet. don't wait yet
+                }
+                */
+            }
+            else
+            track[curtrack].iwait=0;
+
+        track[curtrack].pos=pos;
+        }
+
+
+        ret=0; //end of song.
+        iwait=0;
+        for (curtrack=0; curtrack<16; curtrack++)
+            if (track[curtrack].on == 1 &&
+                track[curtrack].pos < track[curtrack].tend)
+                ret=1;  //not yet..
+
+        if (ret==1)
+            {
+            iwait=0xffffff;  // bigger than any wait can be!
+            for (curtrack=0; curtrack<16; curtrack++)
+               if (track[curtrack].on == 1 &&
+                   track[curtrack].pos < track[curtrack].tend &&
+                   track[curtrack].iwait < iwait)
+                   iwait=track[curtrack].iwait;
+            }
+        }
+
+
+    if (iwait !=0 && ret==1)
+        {
+        for (curtrack=0; curtrack<16; curtrack++)
+            if (track[curtrack].on)
+                track[curtrack].iwait-=iwait;
+
+        
+fwait=1.0f/(((float)iwait/(float)deltas)*((float)msqtr/(float)1000000));
+        }
+        else
+        fwait=50;  // 1/50th of a second
+
+    midiprintf ("\n");
+    for (i=0; i<16; i++)
+        if (track[i].on)
+            if (track[i].pos < track[i].tend)
+                midiprintf ("<%d>",track[i].iwait);
+                else
+                midiprintf("stop");
+
+    /*
+    if (ret==0 && type==FILE_ADVSIERRA)
+        if (datalook(sierra_pos-2)!=0xff)
+            {
+            midiprintf ("next sectoin!");
+            sierra_next_section(p);
+            fwait=50;
+            ret=1;
+            }
+    */
+
+	if(ret)
+		return true;
+	else
+		return false;
+}
+
+float CmidPlayer::getrefresh()
+{
+    return (fwait > 0.01f ? fwait : 0.01f);
+}
+
+void CmidPlayer::rewind(int subsong)
+{
+    long i,j,n,m,l;
+    long o_sierra_pos;
+    unsigned char ins[16];
+
+    pos=0; tins=0;
+    adlib_style=MIDI_STYLE|CMF_STYLE;
+    adlib_mode=ADLIB_MELODIC;
+    for (i=0; i<128; i++)
+        for (j=0; j<16; j++)
+            myinsbank[i][j]=midi_fm_instruments[i][j];
+	for (i=0; i<16; i++)
+        {
+        ch[i].inum=0;
+        for (j=0; j<11; j++)
+            ch[i].ins[j]=myinsbank[ch[i].inum][j];
+        ch[i].vol=127;
+        ch[i].nshift=-25;
+        ch[i].on=1;
+        }
+
+    /* General init */
+    for (i=0; i<9; i++)
+        {
+        chp[i][0]=-1;
+        chp[i][2]=0;
+        }
+
+    deltas=250;  // just a number,  not a standard
+    msqtr=500000;
+    fwait=123; // gotta be a small thing.. sorta like nothing
+    iwait=0;
+
+    subsongs=1;
+
+    for (i=0; i<16; i++)
+        {
+        track[i].tend=0;
+        track[i].spos=0;
+        track[i].pos=0;
+        track[i].iwait=0;
+        track[i].on=0;
+        track[i].pv=0;
+        }
+    curtrack=0;
+
+    /* specific to file-type init */
+
+        pos=0;
+        i=getnext(1);
+        switch(type)
+            {
+            case FILE_LUCAS:
+                getnext(24);  //skip junk and get to the midi.
+                adlib_style=LUCAS_STYLE|MIDI_STYLE;
+                //note: no break, we go right into midi headers...
+            case FILE_MIDI:
+                if (type != FILE_LUCAS)
+                    tins=128;
+                getnext(11);  /*skip header*/
+                deltas=getnext(2);
+                midiprintf ("deltas:%ld\n",deltas);
+                getnext(4);
+
+                curtrack=0;
+                track[curtrack].on=1;
+                track[curtrack].tend=getnext(4);
+                track[curtrack].spos=pos;
+                midiprintf ("tracklen:%ld\n",track[curtrack].tend);
+                break;
+            case FILE_CMF:
+                getnext(3);  // ctmf
+                getnexti(2); //version
+                n=getnexti(2); // instrument offset
+                m=getnexti(2); // music offset
+                deltas=getnexti(2); //ticks/qtr note
+                msqtr=1000000/getnexti(2)*deltas;
+                   //the stuff in the cmf is click ticks per second..
+
+                i=getnexti(2);
+				if(i) title = (char *)data+i;
+                i=getnexti(2);
+				if(i) author = (char *)data+i;
+                i=getnexti(2);
+				if(i) remarks = (char *)data+i;
+
+                getnext(16); // channel in use table ..
+                i=getnexti(2); // num instr
+                if (i>128) i=128; // to ward of bad numbers...
+                getnexti(2); //basic tempo
+
+                midiprintf("\nioff:%d\nmoff%d\ndeltas:%ld\nmsqtr:%ld\nnumi:%d\n",
+                    n,m,deltas,msqtr,i);
+                pos=n;  // jump to instruments
+                tins=i;
+                for (j=0; j<i; j++)
+                    {
+                    midiprintf ("\n%d: ",j);
+                    for (l=0; l<16; l++)
+                        {
+                        myinsbank[j][l]=(unsigned char)getnext(1);
+                        midiprintf ("%2X ",myinsbank[j][l]);
+                        }
+                    }
+
+                for (i=0; i<16; i++)
+                    ch[i].nshift=-13;
+
+                adlib_style=CMF_STYLE;
+
+                curtrack=0;
+                track[curtrack].on=1;
+                track[curtrack].tend=flen;  // music until the end of the file
+                track[curtrack].spos=m;  //jump to midi music
+                break;
+            case FILE_OLDLUCAS:
+                msqtr=250000;
+                pos=9;
+                deltas=getnext(1);
+
+                i=8;
+                pos=0x19;  // jump to instruments
+                tins=i;
+                for (j=0; j<i; j++)
+                    {
+                    midiprintf ("\n%d: ",j);
+                    for (l=0; l<16; l++)
+                        ins[l]=(unsigned char)getnext(1);
+
+                    myinsbank[j][10]=ins[2];
+                    myinsbank[j][0]=ins[3];
+                    myinsbank[j][2]=ins[4];
+                    myinsbank[j][4]=ins[5];
+                    myinsbank[j][6]=ins[6];
+                    myinsbank[j][8]=ins[7];
+                    myinsbank[j][1]=ins[8];
+                    myinsbank[j][3]=ins[9];
+                    myinsbank[j][5]=ins[10];
+                    myinsbank[j][7]=ins[11];
+                    myinsbank[j][9]=ins[12];
+
+                    for (l=0; l<11; l++)
+                        midiprintf ("%2X ",myinsbank[j][l]);
+                    }
+
+                for (i=0; i<16; i++)
+                    {
+                    if (i<tins)
+                        {
+                        ch[i].inum=i;
+                        for (j=0; j<11; j++)
+                            ch[i].ins[j]=myinsbank[ch[i].inum][j];
+                        }
+                    }
+
+                adlib_style=LUCAS_STYLE|MIDI_STYLE;
+
+                curtrack=0;
+                track[curtrack].on=1;
+                track[curtrack].tend=flen;  // music until the end of the file
+                track[curtrack].spos=0x98;  //jump to midi music
+                break;
+            case FILE_ADVSIERRA:
+	      memcpy(myinsbank, smyinsbank, 128 * 16);
+	      tins = stins;
+                deltas=0x20;
+                getnext(11); //worthless empty space and "stuff" :)
+
+                o_sierra_pos=sierra_pos=pos;
+                sierra_next_section();
+                while (datalook(sierra_pos-2)!=0xff)
+                    {
+                    sierra_next_section();
+                    subsongs++;
+                    }
+
+                if (subsong < 0 || subsong >= subsongs) subsong=0;
+
+                sierra_pos=o_sierra_pos;
+                sierra_next_section();
+                i=0;
+                while (i != subsong)
+                    {
+                    sierra_next_section();
+                    i++;
+                    }
+
+                adlib_style=SIERRA_STYLE|MIDI_STYLE;  //advanced sierra tunes use volume
+                break;
+            case FILE_SIERRA:
+	      memcpy(myinsbank, smyinsbank, 128 * 16);
+	      tins = stins;
+                getnext(2);
+                deltas=0x20;
+
+                curtrack=0;
+                track[curtrack].on=1;
+                track[curtrack].tend=flen;  // music until the end of the file
+
+                for (i=0; i<16; i++)
+                    {
+                    ch[i].nshift=-13;
+                    ch[i].on=getnext(1);
+                    ch[i].inum=getnext(1);
+                    for (j=0; j<11; j++)
+                        ch[i].ins[j]=myinsbank[ch[i].inum][j];
+                    }
+
+                track[curtrack].spos=pos;
+                adlib_style=SIERRA_STYLE|MIDI_STYLE;
+                break;
+            }
+
+
+/*        sprintf(info,"%s\r\nTicks/Quarter Note: %ld\r\n",info,deltas);
+        sprintf(info,"%sms/Quarter Note: %ld",info,msqtr); */
+
+        for (i=0; i<16; i++)
+            if (track[i].on)
+                {
+                track[i].pos=track[i].spos;
+                track[i].pv=0;
+                track[i].iwait=0;
+                }
+
+    doing=1;
+	opl->init();
+}
+
+std::string CmidPlayer::gettype()
+{
+	switch(type) {
+	case FILE_LUCAS:
+		return std::string("LucasArts AdLib MIDI");
+	case FILE_MIDI:
+		return std::string("General MIDI");
+	case FILE_CMF:
+		return std::string("Creative Music Format (CMF MIDI)");
+	case FILE_OLDLUCAS:
+		return std::string("Lucasfilm Adlib MIDI");
+	case FILE_ADVSIERRA:
+		return std::string("Sierra On-Line VGA MIDI");
+	case FILE_SIERRA:
+		return std::string("Sierra On-Line EGA MIDI");
+	default:
+		return std::string("MIDI unknown");
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/mid.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,111 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * mid.h - LAA, SCI, MID & CMF Player by Philip Hassey <philhassey@hotmail.com>
+ */
+
+#include "player.h"
+
+class CmidPlayer: public CPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	CmidPlayer(Copl *newopl)
+		: CPlayer(newopl), author(&emptystr), title(&emptystr),
+	  remarks(&emptystr), emptystr('\0'), flen(0), data(0)
+	{ };
+	~CmidPlayer()
+	{ if(data) delete [] data; };
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+	bool update();
+	void rewind(int subsong);
+	float getrefresh();
+
+	std::string gettype();
+	std::string gettitle()
+	{ return std::string(title); };
+	std::string getauthor()
+	{ return std::string(author); };
+	std::string getdesc()
+	{ return std::string(remarks); };
+	unsigned int getinstruments()
+	{ return tins; };
+	unsigned int getsubsongs()
+	{ return subsongs; };
+
+protected:
+	struct midi_channel {
+		int inum;
+		unsigned char ins[11];
+		int vol;
+		int nshift;
+		int on;
+	};
+
+	struct midi_track {
+		unsigned long tend;
+		unsigned long spos;
+		unsigned long pos;
+		unsigned long iwait;
+		int on;
+		unsigned char pv;
+	};
+
+    char *author,*title,*remarks,emptystr;
+    long flen;
+    unsigned long pos;
+    unsigned long sierra_pos; //sierras gotta be special.. :>
+    int subsongs;
+    unsigned char *data;
+
+    unsigned char adlib_data[256];
+    int adlib_style;
+    int adlib_mode;
+    unsigned char myinsbank[128][16], smyinsbank[128][16];
+    midi_channel ch[16];
+    int chp[9][3];
+
+    long deltas;
+    long msqtr;
+
+    midi_track track[16];
+    unsigned int curtrack;
+
+    float fwait;
+    unsigned long iwait;
+    int doing;
+
+    int type,tins,stins;
+
+private:
+	bool load_sierra_ins(const std::string &fname, const CFileProvider &fp);
+	void midiprintf(char *format, ...);
+	unsigned char datalook(long pos);
+	unsigned long getnexti(unsigned long num);
+	unsigned long getnext(unsigned long num);
+	unsigned long getval();
+	void sierra_next_section();
+	void midi_write_adlib(unsigned int r, unsigned char v);
+	void midi_fm_instrument(int voice, unsigned char *inst);
+	void midi_fm_volume(int voice, int volume);
+	void midi_fm_playnote(int voice, int note, int volume);
+	void midi_fm_endnote(int voice);
+	void midi_fm_reset();
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/mididata.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,174 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999, 2000, 2001 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * FM instrument definitions below borrowed from the Allegro library by
+ * Phil Hassey, <philhassey@hotmail.com> - see "adplug/players/mid.cpp"
+ * for further acknowledgements.
+ */
+ 
+unsigned char midi_fm_instruments[128][14] =
+{
+
+   /* This set of GM instrument patches was provided by Jorrit Rouwe...
+    */
+
+   { 0x21, 0x21, 0x8f, 0x0c, 0xf2, 0xf2, 0x45, 0x76, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Acoustic Grand */
+   { 0x31, 0x21, 0x4b, 0x09, 0xf2, 0xf2, 0x54, 0x56, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Bright Acoustic */
+   { 0x31, 0x21, 0x49, 0x09, 0xf2, 0xf2, 0x55, 0x76, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Electric Grand */
+   { 0xb1, 0x61, 0x0e, 0x09, 0xf2, 0xf3, 0x3b, 0x0b, 0x00, 0x00, 0x06, 0, 0, 0 }, /* Honky-Tonk */
+   { 0x01, 0x21, 0x57, 0x09, 0xf1, 0xf1, 0x38, 0x28, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Electric Piano 1 */
+   { 0x01, 0x21, 0x93, 0x09, 0xf1, 0xf1, 0x38, 0x28, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Electric Piano 2 */
+   { 0x21, 0x36, 0x80, 0x17, 0xa2, 0xf1, 0x01, 0xd5, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Harpsichord */
+   { 0x01, 0x01, 0x92, 0x09, 0xc2, 0xc2, 0xa8, 0x58, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Clav */
+   { 0x0c, 0x81, 0x5c, 0x09, 0xf6, 0xf3, 0x54, 0xb5, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Celesta */
+   { 0x07, 0x11, 0x97, 0x89, 0xf6, 0xf5, 0x32, 0x11, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Glockenspiel */
+   { 0x17, 0x01, 0x21, 0x09, 0x56, 0xf6, 0x04, 0x04, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Music Box */
+   { 0x18, 0x81, 0x62, 0x09, 0xf3, 0xf2, 0xe6, 0xf6, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Vibraphone */
+   { 0x18, 0x21, 0x23, 0x09, 0xf7, 0xe5, 0x55, 0xd8, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Marimba */
+   { 0x15, 0x01, 0x91, 0x09, 0xf6, 0xf6, 0xa6, 0xe6, 0x00, 0x00, 0x04, 0, 0, 0 }, /* Xylophone */
+   { 0x45, 0x81, 0x59, 0x89, 0xd3, 0xa3, 0x82, 0xe3, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* Tubular Bells */
+   { 0x03, 0x81, 0x49, 0x89, 0x74, 0xb3, 0x55, 0x05, 0x01, 0x00, 0x04, 0, 0, 0 }, /* Dulcimer */
+   { 0x71, 0x31, 0x92, 0x09, 0xf6, 0xf1, 0x14, 0x07, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Drawbar Organ */
+   { 0x72, 0x30, 0x14, 0x09, 0xc7, 0xc7, 0x58, 0x08, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Percussive Organ */
+   { 0x70, 0xb1, 0x44, 0x09, 0xaa, 0x8a, 0x18, 0x08, 0x00, 0x00, 0x04, 0, 0, 0 }, /* Rock Organ */
+   { 0x23, 0xb1, 0x93, 0x09, 0x97, 0x55, 0x23, 0x14, 0x01, 0x00, 0x04, 0, 0, 0 }, /* Church Organ */
+   { 0x61, 0xb1, 0x13, 0x89, 0x97, 0x55, 0x04, 0x04, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Reed Organ */
+   { 0x24, 0xb1, 0x48, 0x09, 0x98, 0x46, 0x2a, 0x1a, 0x01, 0x00, 0x0c, 0, 0, 0 }, /* Accoridan */
+   { 0x61, 0x21, 0x13, 0x09, 0x91, 0x61, 0x06, 0x07, 0x01, 0x00, 0x0a, 0, 0, 0 }, /* Harmonica */
+   { 0x21, 0xa1, 0x13, 0x92, 0x71, 0x61, 0x06, 0x07, 0x00, 0x00, 0x06, 0, 0, 0 }, /* Tango Accordian */
+   { 0x02, 0x41, 0x9c, 0x89, 0xf3, 0xf3, 0x94, 0xc8, 0x01, 0x00, 0x0c, 0, 0, 0 }, /* Acoustic Guitar(nylon) */
+   { 0x03, 0x11, 0x54, 0x09, 0xf3, 0xf1, 0x9a, 0xe7, 0x01, 0x00, 0x0c, 0, 0, 0 }, /* Acoustic Guitar(steel) */
+   { 0x23, 0x21, 0x5f, 0x09, 0xf1, 0xf2, 0x3a, 0xf8, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Electric Guitar(jazz) */
+   { 0x03, 0x21, 0x87, 0x89, 0xf6, 0xf3, 0x22, 0xf8, 0x01, 0x00, 0x06, 0, 0, 0 }, /* Electric Guitar(clean) */
+   { 0x03, 0x21, 0x47, 0x09, 0xf9, 0xf6, 0x54, 0x3a, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Electric Guitar(muted) */
+   { 0x23, 0x21, 0x4a, 0x0e, 0x91, 0x84, 0x41, 0x19, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Overdriven Guitar */
+   { 0x23, 0x21, 0x4a, 0x09, 0x95, 0x94, 0x19, 0x19, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Distortion Guitar */
+   { 0x09, 0x84, 0xa1, 0x89, 0x20, 0xd1, 0x4f, 0xf8, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Guitar Harmonics */
+   { 0x21, 0xa2, 0x1e, 0x09, 0x94, 0xc3, 0x06, 0xa6, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Acoustic Bass */
+   { 0x31, 0x31, 0x12, 0x09, 0xf1, 0xf1, 0x28, 0x18, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Electric Bass(finger) */
+   { 0x31, 0x31, 0x8d, 0x09, 0xf1, 0xf1, 0xe8, 0x78, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Electric Bass(pick) */
+   { 0x31, 0x32, 0x5b, 0x09, 0x51, 0x71, 0x28, 0x48, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* Fretless Bass */
+   { 0x01, 0x21, 0x8b, 0x49, 0xa1, 0xf2, 0x9a, 0xdf, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Slap Bass 1 */
+   { 0x21, 0x21, 0x8b, 0x11, 0xa2, 0xa1, 0x16, 0xdf, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Slap Bass 2 */
+   { 0x31, 0x31, 0x8b, 0x09, 0xf4, 0xf1, 0xe8, 0x78, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Synth Bass 1 */
+   { 0x31, 0x31, 0x12, 0x09, 0xf1, 0xf1, 0x28, 0x18, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Synth Bass 2 */
+   { 0x31, 0x21, 0x15, 0x09, 0xdd, 0x56, 0x13, 0x26, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Violin */
+   { 0x31, 0x21, 0x16, 0x09, 0xdd, 0x66, 0x13, 0x06, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Viola */
+   { 0x71, 0x31, 0x49, 0x09, 0xd1, 0x61, 0x1c, 0x0c, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Cello */
+   { 0x21, 0x23, 0x4d, 0x89, 0x71, 0x72, 0x12, 0x06, 0x01, 0x00, 0x02, 0, 0, 0 }, /* Contrabass */
+   { 0xf1, 0xe1, 0x40, 0x09, 0xf1, 0x6f, 0x21, 0x16, 0x01, 0x00, 0x02, 0, 0, 0 }, /* Tremolo Strings */
+   { 0x02, 0x01, 0x1a, 0x89, 0xf5, 0x85, 0x75, 0x35, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Pizzicato Strings */
+   { 0x02, 0x01, 0x1d, 0x89, 0xf5, 0xf3, 0x75, 0xf4, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Orchestral Strings */
+   { 0x10, 0x11, 0x41, 0x09, 0xf5, 0xf2, 0x05, 0xc3, 0x01, 0x00, 0x02, 0, 0, 0 }, /* Timpani */
+   { 0x21, 0xa2, 0x9b, 0x0a, 0xb1, 0x72, 0x25, 0x08, 0x01, 0x00, 0x0e, 0, 0, 0 }, /* String Ensemble 1 */
+   { 0xa1, 0x21, 0x98, 0x09, 0x7f, 0x3f, 0x03, 0x07, 0x01, 0x01, 0x00, 0, 0, 0 }, /* String Ensemble 2 */
+   { 0xa1, 0x61, 0x93, 0x09, 0xc1, 0x4f, 0x12, 0x05, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* SynthStrings 1 */
+   { 0x21, 0x61, 0x18, 0x09, 0xc1, 0x4f, 0x22, 0x05, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* SynthStrings 2 */
+   { 0x31, 0x72, 0x5b, 0x8c, 0xf4, 0x8a, 0x15, 0x05, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Choir Aahs */
+   { 0xa1, 0x61, 0x90, 0x09, 0x74, 0x71, 0x39, 0x67, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Voice Oohs */
+   { 0x71, 0x72, 0x57, 0x09, 0x54, 0x7a, 0x05, 0x05, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* Synth Voice */
+   { 0x90, 0x41, 0x00, 0x09, 0x54, 0xa5, 0x63, 0x45, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Orchestra Hit */
+   { 0x21, 0x21, 0x92, 0x0a, 0x85, 0x8f, 0x17, 0x09, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* Trumpet */
+   { 0x21, 0x21, 0x94, 0x0e, 0x75, 0x8f, 0x17, 0x09, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* Trombone */
+   { 0x21, 0x61, 0x94, 0x09, 0x76, 0x82, 0x15, 0x37, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* Tuba */
+   { 0x31, 0x21, 0x43, 0x09, 0x9e, 0x62, 0x17, 0x2c, 0x01, 0x01, 0x02, 0, 0, 0 }, /* Muted Trumpet */
+   { 0x21, 0x21, 0x9b, 0x09, 0x61, 0x7f, 0x6a, 0x0a, 0x00, 0x00, 0x02, 0, 0, 0 }, /* French Horn */
+   { 0x61, 0x22, 0x8a, 0x0f, 0x75, 0x74, 0x1f, 0x0f, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Brass Section */
+   { 0xa1, 0x21, 0x86, 0x8c, 0x72, 0x71, 0x55, 0x18, 0x01, 0x00, 0x00, 0, 0, 0 }, /* SynthBrass 1 */
+   { 0x21, 0x21, 0x4d, 0x09, 0x54, 0xa6, 0x3c, 0x1c, 0x00, 0x00, 0x08, 0, 0, 0 }, /* SynthBrass 2 */
+   { 0x31, 0x61, 0x8f, 0x09, 0x93, 0x72, 0x02, 0x0b, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Soprano Sax */
+   { 0x31, 0x61, 0x8e, 0x09, 0x93, 0x72, 0x03, 0x09, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Alto Sax */
+   { 0x31, 0x61, 0x91, 0x09, 0x93, 0x82, 0x03, 0x09, 0x01, 0x00, 0x0a, 0, 0, 0 }, /* Tenor Sax */
+   { 0x31, 0x61, 0x8e, 0x09, 0x93, 0x72, 0x0f, 0x0f, 0x01, 0x00, 0x0a, 0, 0, 0 }, /* Baritone Sax */
+   { 0x21, 0x21, 0x4b, 0x09, 0xaa, 0x8f, 0x16, 0x0a, 0x01, 0x00, 0x08, 0, 0, 0 }, /* Oboe */
+   { 0x31, 0x21, 0x90, 0x09, 0x7e, 0x8b, 0x17, 0x0c, 0x01, 0x01, 0x06, 0, 0, 0 }, /* English Horn */
+   { 0x31, 0x32, 0x81, 0x09, 0x75, 0x61, 0x19, 0x19, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Bassoon */
+   { 0x32, 0x21, 0x90, 0x09, 0x9b, 0x72, 0x21, 0x17, 0x00, 0x00, 0x04, 0, 0, 0 }, /* Clarinet */
+   { 0xe1, 0xe1, 0x1f, 0x09, 0x85, 0x65, 0x5f, 0x1a, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Piccolo */
+   { 0xe1, 0xe1, 0x46, 0x09, 0x88, 0x65, 0x5f, 0x1a, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Flute */
+   { 0xa1, 0x21, 0x9c, 0x09, 0x75, 0x75, 0x1f, 0x0a, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Recorder */
+   { 0x31, 0x21, 0x8b, 0x09, 0x84, 0x65, 0x58, 0x1a, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Pan Flute */
+   { 0xe1, 0xa1, 0x4c, 0x09, 0x66, 0x65, 0x56, 0x26, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Blown Bottle */
+   { 0x62, 0xa1, 0xcb, 0x09, 0x76, 0x55, 0x46, 0x36, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Skakuhachi */
+   { 0x62, 0xa1, 0xa2, 0x09, 0x57, 0x56, 0x07, 0x07, 0x00, 0x00, 0x0b, 0, 0, 0 }, /* Whistle */
+   { 0x62, 0xa1, 0x9c, 0x09, 0x77, 0x76, 0x07, 0x07, 0x00, 0x00, 0x0b, 0, 0, 0 }, /* Ocarina */
+   { 0x22, 0x21, 0x59, 0x09, 0xff, 0xff, 0x03, 0x0f, 0x02, 0x00, 0x00, 0, 0, 0 }, /* Lead 1 (square) */
+   { 0x21, 0x21, 0x0e, 0x09, 0xff, 0xff, 0x0f, 0x0f, 0x01, 0x01, 0x00, 0, 0, 0 }, /* Lead 2 (sawtooth) */
+   { 0x22, 0x21, 0x46, 0x89, 0x86, 0x64, 0x55, 0x18, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Lead 3 (calliope) */
+   { 0x21, 0xa1, 0x45, 0x09, 0x66, 0x96, 0x12, 0x0a, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Lead 4 (chiff) */
+   { 0x21, 0x22, 0x8b, 0x09, 0x92, 0x91, 0x2a, 0x2a, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Lead 5 (charang) */
+   { 0xa2, 0x61, 0x9e, 0x49, 0xdf, 0x6f, 0x05, 0x07, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Lead 6 (voice) */
+   { 0x20, 0x60, 0x1a, 0x09, 0xef, 0x8f, 0x01, 0x06, 0x00, 0x02, 0x00, 0, 0, 0 }, /* Lead 7 (fifths) */
+   { 0x21, 0x21, 0x8f, 0x86, 0xf1, 0xf4, 0x29, 0x09, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Lead 8 (bass+lead) */
+   { 0x77, 0xa1, 0xa5, 0x09, 0x53, 0xa0, 0x94, 0x05, 0x00, 0x00, 0x02, 0, 0, 0 }, /* Pad 1 (new age) */
+   { 0x61, 0xb1, 0x1f, 0x89, 0xa8, 0x25, 0x11, 0x03, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Pad 2 (warm) */
+   { 0x61, 0x61, 0x17, 0x09, 0x91, 0x55, 0x34, 0x16, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* Pad 3 (polysynth) */
+   { 0x71, 0x72, 0x5d, 0x09, 0x54, 0x6a, 0x01, 0x03, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Pad 4 (choir) */
+   { 0x21, 0xa2, 0x97, 0x09, 0x21, 0x42, 0x43, 0x35, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Pad 5 (bowed) */
+   { 0xa1, 0x21, 0x1c, 0x09, 0xa1, 0x31, 0x77, 0x47, 0x01, 0x01, 0x00, 0, 0, 0 }, /* Pad 6 (metallic) */
+   { 0x21, 0x61, 0x89, 0x0c, 0x11, 0x42, 0x33, 0x25, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Pad 7 (halo) */
+   { 0xa1, 0x21, 0x15, 0x09, 0x11, 0xcf, 0x47, 0x07, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Pad 8 (sweep) */
+   { 0x3a, 0x51, 0xce, 0x09, 0xf8, 0x86, 0xf6, 0x02, 0x00, 0x00, 0x02, 0, 0, 0 }, /* FX 1 (rain) */
+   { 0x21, 0x21, 0x15, 0x09, 0x21, 0x41, 0x23, 0x13, 0x01, 0x00, 0x00, 0, 0, 0 }, /* FX 2 (soundtrack) */
+   { 0x06, 0x01, 0x5b, 0x09, 0x74, 0xa5, 0x95, 0x72, 0x00, 0x00, 0x00, 0, 0, 0 }, /* FX 3 (crystal) */
+   { 0x22, 0x61, 0x92, 0x8c, 0xb1, 0xf2, 0x81, 0x26, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* FX 4 (atmosphere) */
+   { 0x41, 0x42, 0x4d, 0x09, 0xf1, 0xf2, 0x51, 0xf5, 0x01, 0x00, 0x00, 0, 0, 0 }, /* FX 5 (brightness) */
+   { 0x61, 0xa3, 0x94, 0x89, 0x11, 0x11, 0x51, 0x13, 0x01, 0x00, 0x06, 0, 0, 0 }, /* FX 6 (goblins) */
+   { 0x61, 0xa1, 0x8c, 0x89, 0x11, 0x1d, 0x31, 0x03, 0x00, 0x00, 0x06, 0, 0, 0 }, /* FX 7 (echoes) */
+   { 0xa4, 0x61, 0x4c, 0x09, 0xf3, 0x81, 0x73, 0x23, 0x01, 0x00, 0x04, 0, 0, 0 }, /* FX 8 (sci-fi) */
+   { 0x02, 0x07, 0x85, 0x0c, 0xd2, 0xf2, 0x53, 0xf6, 0x00, 0x01, 0x00, 0, 0, 0 }, /* Sitar */
+   { 0x11, 0x13, 0x0c, 0x89, 0xa3, 0xa2, 0x11, 0xe5, 0x01, 0x00, 0x00, 0, 0, 0 }, /* Banjo */
+   { 0x11, 0x11, 0x06, 0x09, 0xf6, 0xf2, 0x41, 0xe6, 0x01, 0x02, 0x04, 0, 0, 0 }, /* Shamisen */
+   { 0x93, 0x91, 0x91, 0x09, 0xd4, 0xeb, 0x32, 0x11, 0x00, 0x01, 0x08, 0, 0, 0 }, /* Koto */
+   { 0x04, 0x01, 0x4f, 0x09, 0xfa, 0xc2, 0x56, 0x05, 0x00, 0x00, 0x0c, 0, 0, 0 }, /* Kalimba */
+   { 0x21, 0x22, 0x49, 0x09, 0x7c, 0x6f, 0x20, 0x0c, 0x00, 0x01, 0x06, 0, 0, 0 }, /* Bagpipe */
+   { 0x31, 0x21, 0x85, 0x09, 0xdd, 0x56, 0x33, 0x16, 0x01, 0x00, 0x0a, 0, 0, 0 }, /* Fiddle */
+   { 0x20, 0x21, 0x04, 0x8a, 0xda, 0x8f, 0x05, 0x0b, 0x02, 0x00, 0x06, 0, 0, 0 }, /* Shanai */
+   { 0x05, 0x03, 0x6a, 0x89, 0xf1, 0xc3, 0xe5, 0xe5, 0x00, 0x00, 0x06, 0, 0, 0 }, /* Tinkle Bell */
+   { 0x07, 0x02, 0x15, 0x09, 0xec, 0xf8, 0x26, 0x16, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Agogo */
+   { 0x05, 0x01, 0x9d, 0x09, 0x67, 0xdf, 0x35, 0x05, 0x00, 0x00, 0x08, 0, 0, 0 }, /* Steel Drums */
+   { 0x18, 0x12, 0x96, 0x09, 0xfa, 0xf8, 0x28, 0xe5, 0x00, 0x00, 0x0a, 0, 0, 0 }, /* Woodblock */
+   { 0x10, 0x00, 0x86, 0x0c, 0xa8, 0xfa, 0x07, 0x03, 0x00, 0x00, 0x06, 0, 0, 0 }, /* Taiko Drum */
+   { 0x11, 0x10, 0x41, 0x0c, 0xf8, 0xf3, 0x47, 0x03, 0x02, 0x00, 0x04, 0, 0, 0 }, /* Melodic Tom */
+   { 0x01, 0x10, 0x8e, 0x09, 0xf1, 0xf3, 0x06, 0x02, 0x02, 0x00, 0x0e, 0, 0, 0 }, /* Synth Drum */
+   { 0x0e, 0xc0, 0x00, 0x09, 0x1f, 0x1f, 0x00, 0xff, 0x00, 0x03, 0x0e, 0, 0, 0 }, /* Reverse Cymbal */
+   { 0x06, 0x03, 0x80, 0x91, 0xf8, 0x56, 0x24, 0x84, 0x00, 0x02, 0x0e, 0, 0, 0 }, /* Guitar Fret Noise */
+   { 0x0e, 0xd0, 0x00, 0x0e, 0xf8, 0x34, 0x00, 0x04, 0x00, 0x03, 0x0e, 0, 0, 0 }, /* Breath Noise */
+   { 0x0e, 0xc0, 0x00, 0x09, 0xf6, 0x1f, 0x00, 0x02, 0x00, 0x03, 0x0e, 0, 0, 0 }, /* Seashore */
+   { 0xd5, 0xda, 0x95, 0x49, 0x37, 0x56, 0xa3, 0x37, 0x00, 0x00, 0x00, 0, 0, 0 }, /* Bird Tweet */
+   { 0x35, 0x14, 0x5c, 0x11, 0xb2, 0xf4, 0x61, 0x15, 0x02, 0x00, 0x0a, 0, 0, 0 }, /* Telephone ring */
+   { 0x0e, 0xd0, 0x00, 0x09, 0xf6, 0x4f, 0x00, 0xf5, 0x00, 0x03, 0x0e, 0, 0, 0 }, /* Helicopter */
+   { 0x26, 0xe4, 0x00, 0x09, 0xff, 0x12, 0x01, 0x16, 0x00, 0x01, 0x0e, 0, 0, 0 }, /* Applause */
+   { 0x00, 0x00, 0x00, 0x09, 0xf3, 0xf6, 0xf0, 0xc9, 0x00, 0x02, 0x0e, 0, 0, 0 }  /* Gunshot */
+
+};
+
+/* logarithmic relationship between midi and FM volumes */
+static int my_midi_fm_vol_table[128] = {
+   0,  11, 16, 19, 22, 25, 27, 29, 32, 33, 35, 37, 39, 40, 42, 43,
+   45, 46, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+   64, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77,
+   78, 79, 80, 80, 81, 82, 83, 83, 84, 85, 86, 86, 87, 88, 89, 89,
+   90, 91, 91, 92, 93, 93, 94, 95, 96, 96, 97, 97, 98, 99, 99, 100,
+   101, 101, 102, 103, 103, 104, 104, 105, 106, 106, 107, 107, 108,
+   109, 109, 110, 110, 111, 112, 112, 113, 113, 114, 114, 115, 115,
+   116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122,
+   123, 123, 124, 124, 125, 125, 126, 126, 127
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/mkj.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,163 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * mkj.cpp - MKJamz Player, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include <assert.h>
+
+#include "mkj.h"
+#include "debug.h"
+
+CPlayer *CmkjPlayer::factory(Copl *newopl)
+{
+  return new CmkjPlayer(newopl);
+}
+
+bool CmkjPlayer::load(const std::string &filename, const CFileProvider &fp)
+{
+  binistream *f = fp.open(filename); if(!f) return false;
+  char	id[6];
+  float	ver;
+  int	i, j;
+  short	inst[8];
+
+  // file validation
+  f->readString(id, 6);
+  if(strncmp(id,"MKJamz",6)) { fp.close(f); return false; }
+  ver = f->readFloat(binio::Single);
+  if(ver > 1.12) { fp.close(f); return false; }
+
+  // load
+  maxchannel = f->readInt(2);
+  opl->init(); opl->write(1, 32);
+  for(i = 0; i < maxchannel; i++) {
+    for(j = 0; j < 8; j++) inst[j] = f->readInt(2);
+    opl->write(0x20+op_table[i],inst[4]);
+    opl->write(0x23+op_table[i],inst[0]);
+    opl->write(0x40+op_table[i],inst[5]);
+    opl->write(0x43+op_table[i],inst[1]);
+    opl->write(0x60+op_table[i],inst[6]);
+    opl->write(0x63+op_table[i],inst[2]);
+    opl->write(0x80+op_table[i],inst[7]);
+    opl->write(0x83+op_table[i],inst[3]);
+  }
+  maxnotes = f->readInt(2);
+  songbuf = new short [(maxchannel+1)*maxnotes];
+  for(i = 0; i < maxchannel; i++) channel[i].defined = f->readInt(2);
+  for(i = 0; i < (maxchannel + 1) * maxnotes; i++)
+    songbuf[i] = f->readInt(2);
+
+  AdPlug_LogWrite("CmkjPlayer::load(\"%s\"): loaded file ver %.2f, %d channels,"
+		  " %d notes/channel.\n", filename.c_str(), ver, maxchannel,
+		  maxnotes);
+  fp.close(f);
+  rewind(0);
+  return true;
+}
+
+bool CmkjPlayer::update()
+{
+  int c, i;
+  short note;
+
+  for(c = 0; c < maxchannel; c++) {
+    if(!channel[c].defined)	// skip if channel is disabled
+      continue;
+
+    if(channel[c].pstat) {
+      channel[c].pstat--;
+      continue;
+    }
+
+    opl->write(0xb0 + c, 0);	// key off
+    do {
+      assert(channel[c].songptr < (maxchannel + 1) * maxnotes);
+      note = songbuf[channel[c].songptr];
+      if(channel[c].songptr - c > maxchannel)
+	if(note && note < 250)
+	  channel[c].pstat = channel[c].speed;
+      switch(note) {
+	// normal notes
+      case 68: opl->write(0xa0 + c,0x81); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break;
+      case 69: opl->write(0xa0 + c,0xb0); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break;
+      case 70: opl->write(0xa0 + c,0xca); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break;
+      case 71: opl->write(0xa0 + c,0x2); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break;
+      case 65: opl->write(0xa0 + c,0x41); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break;
+      case 66: opl->write(0xa0 + c,0x87); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break;
+      case 67: opl->write(0xa0 + c,0xae); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break;
+      case 17: opl->write(0xa0 + c,0x6b); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break;
+      case 18: opl->write(0xa0 + c,0x98); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break;
+      case 20: opl->write(0xa0 + c,0xe5); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break;
+      case 21: opl->write(0xa0 + c,0x20); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break;
+      case 15: opl->write(0xa0 + c,0x63); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break;
+      case 255:	// delay
+	channel[c].songptr += maxchannel;
+	channel[c].pstat = songbuf[channel[c].songptr];
+	break;
+      case 254:	// set octave
+	channel[c].songptr += maxchannel;
+	channel[c].octave = songbuf[channel[c].songptr];
+	break;
+      case 253:	// set speed
+	channel[c].songptr += maxchannel;
+	channel[c].speed = songbuf[channel[c].songptr];
+	break;
+      case 252:	// set waveform
+	channel[c].songptr += maxchannel;
+	channel[c].waveform = songbuf[channel[c].songptr] - 300;
+	if(c > 2)
+	  opl->write(0xe0 + c + (c+6),channel[c].waveform);
+	else
+	  opl->write(0xe0 + c,channel[c].waveform);
+	break;
+      case 251:	// song end
+	for(i = 0; i < maxchannel; i++) channel[i].songptr = i;
+	songend = true;
+	return false;
+      }
+
+      if(channel[c].songptr - c < maxnotes)
+	channel[c].songptr += maxchannel;
+      else
+	channel[c].songptr = c;
+    } while(!channel[c].pstat);
+  }
+
+  return !songend;
+}
+
+void CmkjPlayer::rewind(int subsong)
+{
+  int i;
+
+  for(i = 0; i < maxchannel; i++) {
+    channel[i].pstat = 0;
+    channel[i].speed = 0;
+    channel[i].waveform = 0;
+    channel[i].songptr = i;
+    channel[i].octave = 4;
+  }
+
+  songend = false;
+}
+
+float CmkjPlayer::getrefresh()
+{
+  return 100.0f;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/mkj.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,50 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * mkj.h - MKJamz Player, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "player.h"
+
+class CmkjPlayer: public CPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	CmkjPlayer(Copl *newopl)
+		: CPlayer(newopl), songbuf(0)
+	{ }
+	~CmkjPlayer()
+	{ if(songbuf) delete [] songbuf; }
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+	bool update();
+	void rewind(int subsong);
+	float getrefresh();
+
+	std::string gettype()
+	{ return std::string("MKJamz Audio File"); }
+
+private:
+	short maxchannel,maxnotes,*songbuf;
+	bool songend;
+
+	struct {
+		short defined,songptr,octave,waveform,pstat,speed,delay;
+	} channel[9];
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/mtk.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,109 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * mtk.cpp - MPU-401 Trakker Loader by Simon Peter (dn.tlp@gmx.net)
+ */
+
+#include "mtk.h"
+
+/*** public methods **************************************/
+
+CPlayer *CmtkLoader::factory(Copl *newopl)
+{
+  return new CmtkLoader(newopl);
+}
+
+bool CmtkLoader::load(const std::string &filename, const CFileProvider &fp)
+{
+        binistream *f = fp.open(filename); if(!f) return false;
+	struct {
+		char id[18];
+		unsigned short crc,size;
+	} header;
+	struct mtkdata {
+		char songname[34],composername[34],instname[0x80][34];
+		unsigned char insts[0x80][12],order[0x80],dummy,patterns[0x32][0x40][9];
+	} *data;
+	unsigned char *cmp,*org;
+	unsigned int i;
+	unsigned long cmpsize,cmpptr=0,orgptr=0;
+	unsigned short ctrlbits=0,ctrlmask=0,cmd,cnt,offs;
+
+	// read header
+	f->readString(header.id, 18);
+	header.crc = f->readInt(2);
+	header.size = f->readInt(2);
+
+	// file validation section
+	if(strncmp(header.id,"mpu401tr\x92kk\xeer@data",18))
+	  { fp.close(f); return false; }
+
+	// load section
+	cmpsize = fp.filesize(f) - 22;
+	cmp = new unsigned char[cmpsize];
+	org = new unsigned char[header.size];
+	for(i = 0; i < cmpsize; i++) cmp[i] = f->readInt(1);
+	fp.close(f);
+
+	while(cmpptr < cmpsize) {	// decompress
+		ctrlmask >>= 1;
+		if(!ctrlmask) {
+		        ctrlbits = cmp[cmpptr] + (cmp[cmpptr + 1] << 8);
+			cmpptr += 2;
+			ctrlmask = 0x8000;
+		}
+		if(!(ctrlbits & ctrlmask)) {	// uncompressed data
+			org[orgptr] = cmp[cmpptr];
+			orgptr++; cmpptr++;
+			continue;
+		}
+
+		// compressed data
+		cmd = (cmp[cmpptr] >> 4) & 0x0f;
+		cnt = cmp[cmpptr] & 0x0f;
+		cmpptr++;
+		switch(cmd) {
+		case 0: cnt += 3; memset(&org[orgptr],cmp[cmpptr],cnt); cmpptr++; orgptr += cnt; break;
+		case 1: cnt += (cmp[cmpptr] << 4) + 19; memset(&org[orgptr],cmp[++cmpptr],cnt); cmpptr++; orgptr += cnt; break;
+		case 2: offs = (cnt+3) + (cmp[cmpptr] << 4); cnt = cmp[++cmpptr] + 16; cmpptr++;
+				memcpy(&org[orgptr],&org[orgptr - offs],cnt); orgptr += cnt; break;
+		default: offs = (cnt+3) + (cmp[cmpptr++] << 4); memcpy(&org[orgptr],&org[orgptr-offs],cmd); orgptr += cmd; break;
+		}
+	}
+	delete [] cmp;
+	data = (struct mtkdata *) org;
+
+	// convert to HSC replay data
+	memset(title,0,34); strncpy(title,data->songname+1,33);
+	memset(composer,0,34); strncpy(composer,data->composername+1,33);
+	memset(instname,0,0x80*34);
+	for(i=0;i<0x80;i++)
+		strncpy(instname[i],data->instname[i]+1,33);
+	memcpy(instr,data->insts,0x80 * 12);
+	memcpy(song,data->order,0x80);
+	memcpy(patterns,data->patterns,header.size-6084);
+	for (i=0;i<128;i++) {				// correct instruments
+		instr[i][2] ^= (instr[i][2] & 0x40) << 1;
+		instr[i][3] ^= (instr[i][3] & 0x40) << 1;
+		instr[i][11] >>= 4;		// make unsigned
+	}
+
+	delete [] org;
+	rewind(0);
+	return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/mtk.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,50 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * mtk.h - MPU-401 Trakker Loader by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "hsc.h"
+
+class CmtkLoader: public ChscPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	CmtkLoader(Copl *newopl)
+		: ChscPlayer(newopl)
+	{
+		mtkmode = 1;
+	};
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+
+	std::string gettype()
+	{ return std::string("MPU-401 Trakker"); };
+	std::string gettitle()
+	{ return std::string(title); };
+	std::string getauthor()
+	{ return std::string(composer); };
+	unsigned int getinstruments()
+	{ return 128; };
+	std::string getinstrument(unsigned int n)
+	{ return std::string(instname[n]); };
+
+private:
+	char title[34],composer[34],instname[0x80][34];
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/opl.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,34 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * opl.h - OPL base class declaration, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#ifndef H_ADPLUG_OPL
+#define H_ADPLUG_OPL
+
+class Copl
+{
+public:
+	virtual void write(int reg, int val) = 0;		// combined register select + data write
+	virtual void init(void) = 0;				// reinitialize OPL chip
+
+	virtual void update(short *buf, int samples) {};	// Emulation only: fill buffer
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/player.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,70 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * player.cpp - Replayer base class, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "player.h"
+#include "adplug.h"
+#include "silentopl.h"
+
+/***** CPlayer *****/
+
+const unsigned short CPlayer::note_table[12] =
+  {363, 385, 408, 432, 458, 485, 514, 544, 577, 611, 647, 686};
+
+const unsigned char CPlayer::op_table[9] =
+  {0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12};
+
+CPlayer::CPlayer(Copl *newopl)
+  : opl(newopl), db(CAdPlug::database)
+{
+}
+
+CPlayer::~CPlayer()
+{
+}
+
+unsigned long CPlayer::songlength(int subsong)
+{
+  CSilentopl	tempopl;
+  Copl		*saveopl = opl;
+  float		slength = 0.0f;
+
+  // save original OPL from being overwritten
+  opl = &tempopl;
+
+  // get song length
+  rewind(subsong);
+  while(update() && slength < 600000)	// song length limit: 10 minutes
+    slength += 1000.0f / getrefresh();
+  rewind(subsong);
+
+  // restore original OPL and return
+  opl = saveopl;
+  return (unsigned long)slength;
+}
+
+void CPlayer::seek(unsigned long ms)
+{
+  float pos = 0.0f;
+
+  rewind();
+  while(pos < ms && update())		// seek to new position
+    pos += 1000/getrefresh();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/player.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,83 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * player.h - Replayer base class, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#ifndef H_ADPLUG_PLAYER
+#define H_ADPLUG_PLAYER
+
+#include <string>
+
+#include "fprovide.h"
+#include "opl.h"
+#include "database.h"
+
+class CPlayer
+{
+public:
+        CPlayer(Copl *newopl);
+	virtual ~CPlayer();
+
+/***** Operational methods *****/
+	void seek(unsigned long ms);
+
+	virtual bool load(const std::string &filename,	// loads file
+			  const CFileProvider &fp = CProvider_Filesystem()) = 0;
+	virtual bool update() = 0;			// executes replay code for 1 tick
+	virtual void rewind(int subsong = -1) = 0;	// rewinds to specified subsong
+	virtual float getrefresh() = 0;			// returns needed timer refresh rate
+
+/***** Informational methods *****/
+	unsigned long songlength(int subsong = -1);
+
+	virtual std::string gettype() = 0;	// returns file type
+	virtual std::string gettitle()		// returns song title
+	{ return std::string(); }
+	virtual std::string getauthor()		// returns song author name
+	{ return std::string(); }
+	virtual std::string getdesc()		// returns song description
+	{ return std::string(); }
+	virtual unsigned int getpatterns()	// returns number of patterns
+	{ return 0; }
+	virtual unsigned int getpattern()	// returns currently playing pattern
+	{ return 0; }
+	virtual unsigned int getorders()	// returns size of orderlist
+	{ return 0; }
+	virtual unsigned int getorder()		// returns currently playing song position
+	{ return 0; }
+	virtual unsigned int getrow()		// returns currently playing row
+	{ return 0; }
+	virtual unsigned int getspeed()		// returns current song speed
+	{ return 0; }
+	virtual unsigned int getsubsongs()	// returns number of subsongs
+	{ return 1; }
+	virtual unsigned int getinstruments()	// returns number of instruments
+	{ return 0; }
+	virtual std::string getinstrument(unsigned int n)	// returns n-th instrument name
+	{ return std::string(); }
+
+protected:
+	Copl		*opl;	// our OPL chip
+	CAdPlugDatabase	*db;	// AdPlug Database
+
+	static const unsigned short	note_table[12];	// standard adlib note table
+	static const unsigned char	op_table[9];	// the 9 operators as expected by the OPL2
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/players.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,105 @@
+/*
+ * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * players.h - Players enumeration, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "players.h"
+
+/***** CPlayerDesc *****/
+
+CPlayerDesc::CPlayerDesc()
+  : factory(0), extensions(0), extlength(0)
+{
+}
+
+CPlayerDesc::CPlayerDesc(const CPlayerDesc &pd)
+  : factory(pd.factory), filetype(pd.filetype), extlength(pd.extlength)
+{
+  if(pd.extensions) {
+    extensions = (char *)malloc(extlength);
+    memcpy(extensions, pd.extensions, extlength);
+  } else
+    extensions = 0;
+}
+
+CPlayerDesc::CPlayerDesc(Factory f, const std::string &type, const char *ext)
+  : factory(f), filetype(type), extensions(0)
+{
+  const char *i = ext;
+
+  // Determine length of passed extensions list
+  while(*i) i += strlen(i) + 1;
+  extlength = i - ext + 1;	// length = difference between last and first char + 1
+
+  extensions = (char *)malloc(extlength);
+  memcpy(extensions, ext, extlength);
+}
+
+CPlayerDesc::~CPlayerDesc()
+{
+  if(extensions) free(extensions);
+}
+
+void CPlayerDesc::add_extension(const char *ext)
+{
+  unsigned long newlength = extlength + strlen(ext) + 1;
+
+  extensions = (char *)realloc(extensions, newlength);
+  strcpy(extensions + extlength - 1, ext);
+  extensions[newlength - 1] = '\0';
+  extlength = newlength;
+}
+
+const char *CPlayerDesc::get_extension(unsigned int n) const
+{
+  const char	*i = extensions;
+  unsigned int	j;
+
+  for(j = 0; j < n && (*i); j++, i += strlen(i) + 1) ;
+  return (*i != '\0' ? i : 0);
+}
+
+/***** CPlayers *****/
+
+const CPlayerDesc *CPlayers::lookup_filetype(const std::string &ftype) const
+{
+  const_iterator	i;
+
+  for(i = begin(); i != end(); i++)
+    if((*i)->filetype == ftype)
+      return *i;
+
+  return 0;
+}
+
+const CPlayerDesc *CPlayers::lookup_extension(const std::string &extension) const
+{
+  const_iterator	i;
+  unsigned int		j;
+
+  for(i = begin(); i != end(); i++)
+    for(j = 0; (*i)->get_extension(j); j++)
+      if(!stricmp(extension.c_str(), (*i)->get_extension(j)))
+	return *i;
+
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/players.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,60 @@
+/*
+ * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * players.h - Players enumeration, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#ifndef H_ADPLUG_PLAYERS
+#define H_ADPLUG_PLAYERS
+
+#include <string>
+#include <list>
+
+#include "opl.h"
+#include "player.h"
+
+class CPlayerDesc
+{
+public:
+  typedef CPlayer *(*Factory)(Copl *);
+
+  Factory	factory;
+  std::string	filetype;
+
+  CPlayerDesc();
+  CPlayerDesc(const CPlayerDesc &pd);
+  CPlayerDesc(Factory f, const std::string &type, const char *ext);
+
+  ~CPlayerDesc();
+
+  void add_extension(const char *ext);
+  const char *get_extension(unsigned int n) const;
+
+private:
+  char		*extensions;
+  unsigned long	extlength;
+};
+
+class CPlayers: public std::list<const CPlayerDesc *>
+{
+public:
+  const CPlayerDesc *lookup_filetype(const std::string &ftype) const;
+  const CPlayerDesc *lookup_extension(const std::string &extension) const;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/protrack.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,722 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2002 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * protrack.cpp - Generic Protracker Player
+ * Copyright (C) 2000 - 2002 Simon Peter <dn.tlp@gmx.net>
+ *
+ * NOTES:
+ * This is a generic Protracker-based formats player. It offers all Protracker
+ * features, plus a good set of extensions to be compatible to other Protracker
+ * derivatives. It is derived from the original SA2 player by me. If you got a
+ * Protracker-like format, this is most certainly the player you want to use.
+ *
+ * USAGE:
+ * Read the file 'Protracker.txt' in the 'doc' subdirectory.
+ */
+
+#include "protrack.h"
+#include "debug.h"
+
+#define SPECIALARPLEN	256	// Standard length of special arpeggio lists
+#define JUMPMARKER	0x80	// Orderlist jump marker
+
+// SA2 compatible adlib note table
+const unsigned short CmodPlayer::sa2_notetable[12] =
+{340,363,385,408,432,458,485,514,544,577,611,647};
+
+// SA2 compatible vibrato rate table
+const unsigned char CmodPlayer::vibratotab[32] =
+{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1};
+
+/*** public methods *************************************/
+
+CmodPlayer::CmodPlayer(Copl *newopl)
+  : CPlayer(newopl), inst(0), order(0), arplist(0), arpcmd(0), initspeed(6),
+    activechan(0xffff), flags(Standard), nop(0), nrows(0), npats(0), nchans(0)
+{
+  realloc_order(128);
+  realloc_patterns(64, 64, 9);
+  realloc_instruments(250);
+  init_notetable(sa2_notetable);
+}
+
+CmodPlayer::~CmodPlayer()
+{
+  dealloc();
+}
+
+bool CmodPlayer::update()
+{
+	unsigned char pattbreak=0,donote;		// remember vars
+	unsigned char pattnr,chan,info1,info2,info;	// cache vars
+	unsigned short track;
+	unsigned long row;
+
+	if(!speed)		// song full stop
+		return !songend;
+
+	// effect handling (timer dependant)
+	for(chan=0;chan<nchans;chan++) {
+		if(arplist && arpcmd && inst[channel[chan].inst].arpstart)	// special arpeggio
+			if(channel[chan].arpspdcnt)
+				channel[chan].arpspdcnt--;
+			else
+				if(arpcmd[channel[chan].arppos] != 255) {
+					switch(arpcmd[channel[chan].arppos]) {
+					case 252: channel[chan].vol1 = arplist[channel[chan].arppos];	// set volume
+							if(channel[chan].vol1 > 63)	// ?????
+								channel[chan].vol1 = 63;
+							channel[chan].vol2 = channel[chan].vol1;
+							setvolume(chan);
+							break;
+					case 253: channel[chan].key = 0; setfreq(chan); break;	// release sustaining note
+					case 254: channel[chan].arppos = arplist[channel[chan].arppos]; break; // arpeggio loop
+					default: if(arpcmd[channel[chan].arppos]) {
+								if(arpcmd[channel[chan].arppos] / 10)
+									opl->write(0xe3 + op_table[chan], arpcmd[channel[chan].arppos] / 10 - 1);
+								if(arpcmd[channel[chan].arppos] % 10)
+									opl->write(0xe0 + op_table[chan], (arpcmd[channel[chan].arppos] % 10) - 1);
+								if(arpcmd[channel[chan].arppos] < 10)	// ?????
+									opl->write(0xe0 + op_table[chan], arpcmd[channel[chan].arppos] - 1);
+							 }
+					}
+					if(arpcmd[channel[chan].arppos] != 252) {
+						if(arplist[channel[chan].arppos] <= 96)
+							setnote(chan,channel[chan].note + arplist[channel[chan].arppos]);
+						if(arplist[channel[chan].arppos] >= 100)
+							setnote(chan,arplist[channel[chan].arppos] - 100);
+					} else
+						setnote(chan,channel[chan].note);
+					setfreq(chan);
+					if(arpcmd[channel[chan].arppos] != 255)
+						channel[chan].arppos++;
+					channel[chan].arpspdcnt = inst[channel[chan].inst].arpspeed - 1;
+				}
+
+		info1 = channel[chan].info1;
+		info2 = channel[chan].info2;
+		if(flags & Decimal)
+			info = channel[chan].info1 * 10 + channel[chan].info2;
+		else
+			info = (channel[chan].info1 << 4) + channel[chan].info2;
+		switch(channel[chan].fx) {
+		case 0:	if(info) {									// arpeggio
+					if(channel[chan].trigger < 2)
+						channel[chan].trigger++;
+					else
+						channel[chan].trigger = 0;
+					switch(channel[chan].trigger) {
+					case 0: setnote(chan,channel[chan].note); break;
+					case 1: setnote(chan,channel[chan].note + info1); break;
+					case 2: setnote(chan,channel[chan].note + info2);
+					}
+					setfreq(chan);
+				}
+				break;
+		case 1: slide_up(chan,info); setfreq(chan); break;	// slide up
+		case 2: slide_down(chan,info); setfreq(chan); break;	// slide down
+		case 3: tone_portamento(chan,channel[chan].portainfo); break;	// tone portamento
+		case 4: vibrato(chan,channel[chan].vibinfo1,channel[chan].vibinfo2); break;	// vibrato
+		case 5:												// tone portamento & volume slide
+		case 6: if(channel[chan].fx == 5)				// vibrato & volume slide
+					tone_portamento(chan,channel[chan].portainfo);
+				else
+					vibrato(chan,channel[chan].vibinfo1,channel[chan].vibinfo2);
+		case 10: if(del % 4)	// SA2 volume slide
+					break;
+				 if(info1)
+					 vol_up(chan,info1);
+				 else
+					 vol_down(chan,info2);
+				 setvolume(chan);
+				 break;
+		case 14: if(info1 == 3)							// retrig note
+					if(!(del % (info2+1)))
+						playnote(chan);
+				 break;
+		case 16: if(del % 4)	// AMD volume slide
+					break;
+				 if(info1)
+					 vol_up_alt(chan,info1);
+				 else
+					 vol_down_alt(chan,info2);
+				 setvolume(chan);
+				 break;
+		case 20:				// RAD volume slide
+			if(info < 50)
+				vol_down_alt(chan,info);
+			else
+				vol_up_alt(chan,info - 50);
+			setvolume(chan);
+			break;
+		case 26: // volume slide
+			if(info1)
+				vol_up(chan,info1);
+			else
+				vol_down(chan,info2);
+			setvolume(chan);
+			break;
+		case 28:
+			if (info1) {
+				slide_up(chan,1); channel[chan].info1--;
+			}
+			if (info2) {
+				slide_down(chan,1); channel[chan].info2--;
+			}
+			setfreq(chan);
+			break;
+		}
+	}
+
+	if(del) {		// speed compensation
+		del--;
+		return !songend;
+	}
+
+	// arrangement handling
+	if(ord >= length) {
+		songend = 1;				// set end-flag
+		ord = restartpos;
+	}
+	pattnr = order[ord];
+
+        if(!rw) AdPlug_LogWrite("\nCmodPlayer::update(): Pattern: %d, Order: %d\n", pattnr, ord);
+        AdPlug_LogWrite("CmodPlayer::update():%3d|", rw);
+
+	// play row
+	row = rw;
+	for(chan=0;chan<nchans;chan++) {
+		if(!(activechan >> (15 - chan)) & 1) {	// channel active?
+                  AdPlug_LogWrite("N/A|");
+		  continue;
+		}
+		if(!(track = trackord[pattnr][chan])) {	// resolve track
+                  AdPlug_LogWrite("------------|");
+		  continue;
+		} else
+			track--;
+
+                AdPlug_LogWrite("%3d%3d%2X%2X%2X|", tracks[track][row].note,
+			 tracks[track][row].inst, tracks[track][row].command,
+			 tracks[track][row].param1, tracks[track][row].param2);
+
+		donote = 0;
+		if(tracks[track][row].inst) {
+		  channel[chan].inst = tracks[track][row].inst - 1;
+		  if (!(flags & Faust)) {
+		    channel[chan].vol1 = 63 - (inst[channel[chan].inst].data[10] & 63);
+		    channel[chan].vol2 = 63 - (inst[channel[chan].inst].data[9] & 63);
+		    setvolume(chan);
+		  }
+		}
+
+		if(tracks[track][row].note && tracks[track][row].command != 3) {	// no tone portamento
+			channel[chan].note = tracks[track][row].note;
+			setnote(chan,tracks[track][row].note);
+			channel[chan].nextfreq = channel[chan].freq;
+			channel[chan].nextoct = channel[chan].oct;
+			channel[chan].arppos = inst[channel[chan].inst].arpstart;
+			channel[chan].arpspdcnt = 0;
+			if(tracks[track][row].note != 127)	// handle key off
+				donote = 1;
+		}
+		channel[chan].fx = tracks[track][row].command;
+		channel[chan].info1 = tracks[track][row].param1;
+		channel[chan].info2 = tracks[track][row].param2;
+
+		if(donote)
+			playnote(chan);
+
+		// command handling (row dependant)
+		info1 = channel[chan].info1;
+		info2 = channel[chan].info2;
+		if(flags & Decimal)
+			info = channel[chan].info1 * 10 + channel[chan].info2;
+		else
+			info = (channel[chan].info1 << 4) + channel[chan].info2;
+		switch(channel[chan].fx) {
+		case 3:	if(tracks[track][row].note) {					// tone portamento
+					if(tracks[track][row].note < 13)
+						channel[chan].nextfreq = notetable[tracks[track][row].note - 1];
+					else
+						if(tracks[track][row].note % 12 > 0)
+							channel[chan].nextfreq = notetable[(tracks[track][row].note % 12) - 1];
+						else
+							channel[chan].nextfreq = notetable[11];
+					channel[chan].nextoct = (tracks[track][row].note - 1) / 12;
+					if(tracks[track][row].note == 127) {	// handle key off
+						channel[chan].nextfreq = channel[chan].freq;
+						channel[chan].nextoct = channel[chan].oct;
+					}
+				}
+				if(info)		// remember vars
+					channel[chan].portainfo = info;
+				break;
+		case 4: if(info) {										// vibrato (remember vars)
+					channel[chan].vibinfo1 = info1;
+					channel[chan].vibinfo2 = info2;
+				}
+				break;
+		case 7: tempo = info; break;							// set tempo
+		case 8: channel[chan].key = 0; setfreq(chan); break;	// release sustaining note
+		case 9: // set carrier/modulator volume
+				if(info1)
+					channel[chan].vol1 = info1 * 7;
+				else
+					channel[chan].vol2 = info2 * 7;
+				setvolume(chan);
+				break;
+		case 11: pattbreak = 1; rw = 0; if(info < ord) songend = 1; ord = info; break; // position jump
+		case 12: // set volume
+				channel[chan].vol1 = info;
+				channel[chan].vol2 = info;
+				if(channel[chan].vol1 > 63)
+					channel[chan].vol1 = 63;
+				if(channel[chan].vol2 > 63)
+					channel[chan].vol2 = 63;
+				setvolume(chan);
+				break;
+		case 13: if(!pattbreak) { pattbreak = 1; rw = info; ord++; } break;	// pattern break
+		case 14: // extended command
+				switch(info1) {
+				case 0: if(info2)								// define cell-tremolo
+							regbd |= 128;
+						else
+							regbd &= 127;
+						opl->write(0xbd,regbd);
+						break;
+				case 1: if(info2)								// define cell-vibrato
+							regbd |= 64;
+						else
+							regbd &= 191;
+						opl->write(0xbd,regbd);
+						break;
+				case 4: vol_up_alt(chan,info2);					// increase volume fine
+						setvolume(chan);
+						break;
+				case 5: vol_down_alt(chan,info2);				// decrease volume fine
+						setvolume(chan);
+						break;
+				case 6: slide_up(chan,info2);					// manual slide up
+						setfreq(chan);
+						break;
+				case 7: slide_down(chan,info2);					// manual slide down
+						setfreq(chan);
+						break;
+				}
+				break;
+		case 15: // SA2 set speed
+			if(info <= 0x1f)
+				speed = info;
+			if(info >= 0x32)
+				tempo = info;
+			if(!info)
+				songend = 1;
+			break;
+		case 17: // alternate set volume
+			channel[chan].vol1 = info;
+			if(channel[chan].vol1 > 63)
+				channel[chan].vol1 = 63;
+			if(inst[channel[chan].inst].data[0] & 1) {
+				channel[chan].vol2 = info;
+	 			if(channel[chan].vol2 > 63)
+					channel[chan].vol2 = 63;
+			}
+			setvolume(chan);
+			break;
+		case 18: // AMD set speed
+			if(info <= 31 && info > 0)
+				speed = info;
+			if(info > 31 || !info)
+				tempo = info;
+			break;
+		case 19: // RAD/A2M set speed
+			speed = (info ? info : info + 1);
+			break;
+		case 21: // set modulator volume
+			if(info <= 63)
+				channel[chan].vol2 = info;
+			else
+				channel[chan].vol2 = 63;
+			setvolume(chan);
+			break;
+		case 22: // set carrier volume
+			if(info <= 63)
+				channel[chan].vol1 = info;
+			else
+				channel[chan].vol1 = 63;
+			setvolume(chan);
+			break;
+		case 23: // fine frequency slide up
+			slide_up(chan,info);
+			setfreq(chan);
+			break;
+		case 24: // fine frequency slide down
+			slide_down(chan,info);
+			setfreq(chan);
+			break;
+		case 25: // set carrier/modulator waveform
+			if(info1 != 0x0f)
+				opl->write(0xe3 + op_table[chan],info1);
+			if(info2 != 0x0f)
+				opl->write(0xe0 + op_table[chan],info2);
+			break;
+		case 27: // set chip tremolo/vibrato
+			if (info1)
+				regbd |= 128;
+			else
+				regbd &= 127;
+			if (info2)
+				regbd |= 64;
+			else
+				regbd &= 191;
+			opl->write(0xbd,regbd);
+			break;
+		}
+	}
+
+	del = speed - 1;	// speed compensation
+	if(!pattbreak) {	// next row (only if no manual advance)
+		rw++;
+		if(rw >= nrows) {
+			rw = 0;
+			ord++;
+		}
+	}
+	if(ord < length) {
+	  if(order[ord] >= JUMPMARKER) {	// jump to order
+	    ord = order[ord] - JUMPMARKER;
+	    songend = 1;
+	  }
+	} else
+	  songend = 1;
+
+        AdPlug_LogWrite("\n");
+	return !songend;
+}
+
+void CmodPlayer::rewind(int subsong)
+{
+  unsigned long i;
+
+  // Reset playing variables
+  songend = del = ord = rw = regbd = 0;
+  tempo = bpm; speed = initspeed;
+
+  // Reset channel data
+  memset(channel,0,sizeof(Channel)*nchans);
+
+  // Compute number of patterns, if needed
+  if(!nop)
+    for(i=0;i<length;i++)
+      nop = (order[i] > nop ? order[i] : nop);
+
+  opl->init();				// Reset OPL chip
+  opl->write(1,32);			// Go to ym3812 mode
+}
+
+float CmodPlayer::getrefresh()
+{
+	return (float) (tempo / 2.5);
+}
+
+void CmodPlayer::init_trackord()
+{
+  unsigned long i;
+
+  for(i=0;i<npats*nchans;i++)
+    trackord[i / nchans][i % nchans] = i + 1;
+}
+
+bool CmodPlayer::init_specialarp()
+{
+  arplist = new unsigned char[SPECIALARPLEN];
+  arpcmd = new unsigned char[SPECIALARPLEN];
+
+  return true;
+}
+
+void CmodPlayer::init_notetable(const unsigned short *newnotetable)
+{
+  memcpy(notetable, newnotetable, 12 * 2);
+}
+
+bool CmodPlayer::realloc_order(unsigned long len)
+{
+  if(order) delete [] order;
+  order = new unsigned char[len];
+  return true;
+}
+
+bool CmodPlayer::realloc_patterns(unsigned long pats, unsigned long rows, unsigned long chans)
+{
+  unsigned long i;
+
+  dealloc_patterns();
+
+  // set new number of tracks, rows and channels
+  npats = pats; nrows = rows; nchans = chans;
+
+  // alloc new patterns
+  tracks = new Tracks *[pats * chans];
+  for(i=0;i<pats*chans;i++) tracks[i] = new Tracks[rows];
+  trackord = new unsigned short *[pats];
+  for(i=0;i<pats;i++) trackord[i] = new unsigned short[chans];
+  channel = new Channel[chans];
+
+  // initialize new patterns
+  for(i=0;i<pats*chans;i++) memset(tracks[i],0,sizeof(Tracks)*rows);
+  for(i=0;i<pats;i++) memset(trackord[i],0,chans*2);
+
+  return true;
+}
+
+void CmodPlayer::dealloc_patterns()
+{
+  unsigned long i;
+
+  // dealloc everything previously allocated
+  if(npats && nrows && nchans) {
+    for(i=0;i<npats*nchans;i++) delete [] tracks[i];
+    delete [] tracks;
+    for(i=0;i<npats;i++) delete [] trackord[i];
+    delete [] trackord;
+    delete [] channel;
+  }
+}
+
+bool CmodPlayer::realloc_instruments(unsigned long len)
+{
+  // dealloc previous instance, if any
+  if(inst) delete [] inst;
+
+  inst = new Instrument[len];
+  memset(inst,0,sizeof(Instrument)*len);	// reset instruments
+  return true;
+}
+
+void CmodPlayer::dealloc()
+{
+  if(inst) delete [] inst;
+  if(order) delete [] order;
+  if(arplist) delete [] arplist;
+  if(arpcmd) delete [] arpcmd;
+  dealloc_patterns();
+}
+
+/*** private methods *************************************/
+
+void CmodPlayer::setvolume(unsigned char chan)
+{
+	if (flags & Faust)
+        	setvolume_alt(chan);
+	else {
+		opl->write(0x40 + op_table[chan], 63-channel[chan].vol2 + (inst[channel[chan].inst].data[9] & 192));
+		opl->write(0x43 + op_table[chan], 63-channel[chan].vol1 + (inst[channel[chan].inst].data[10] & 192));
+	}
+}
+
+void CmodPlayer::setvolume_alt(unsigned char chan)
+{
+    unsigned char ivol2 = inst[channel[chan].inst].data[9] & 63;
+    unsigned char ivol1 = inst[channel[chan].inst].data[10] & 63;
+
+    opl->write(0x40 + op_table[chan], (((63 - channel[chan].vol2 & 63) + ivol2) >> 1) + (inst[channel[chan].inst].data[9] & 192));
+    opl->write(0x43 + op_table[chan], (((63 - channel[chan].vol1 & 63) + ivol1) >> 1) + (inst[channel[chan].inst].data[10] & 192));
+}
+
+void CmodPlayer::setfreq(unsigned char chan)
+{
+	opl->write(0xa0 + chan, channel[chan].freq & 255);
+	if(channel[chan].key)
+		opl->write(0xb0 + chan, ((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2) | 32);
+	else
+		opl->write(0xb0 + chan, ((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2));
+}
+
+void CmodPlayer::playnote(unsigned char chan)
+{
+	unsigned char op = op_table[chan], insnr = channel[chan].inst;
+
+	if(!(flags & NoKeyOn))
+	  opl->write(0xb0 + chan, 0);	// stop old note
+
+	// set instrument data
+	opl->write(0x20 + op, inst[insnr].data[1]);
+	opl->write(0x23 + op, inst[insnr].data[2]);
+	opl->write(0x60 + op, inst[insnr].data[3]);
+	opl->write(0x63 + op, inst[insnr].data[4]);
+	opl->write(0x80 + op, inst[insnr].data[5]);
+	opl->write(0x83 + op, inst[insnr].data[6]);
+	opl->write(0xe0 + op, inst[insnr].data[7]);
+	opl->write(0xe3 + op, inst[insnr].data[8]);
+	opl->write(0xc0 + chan, inst[insnr].data[0]);
+	opl->write(0xbd, inst[insnr].misc);	// set misc. register
+
+	// set frequency, volume & play
+	channel[chan].key = 1;
+	setfreq(chan);
+
+	if (flags & Faust) {
+		channel[chan].vol2 = 63;
+		channel[chan].vol1 = 63;
+	}
+	setvolume(chan);
+}
+
+void CmodPlayer::setnote(unsigned char chan, int note)
+{
+	if(note > 96)
+		if(note == 127) {	// key off
+			channel[chan].key = 0;
+			setfreq(chan);
+			return;
+		} else
+			note = 96;
+
+	if(note < 13)
+		channel[chan].freq = notetable[note - 1];
+	else
+		if(note % 12 > 0)
+			channel[chan].freq = notetable[(note % 12) - 1];
+		else
+			channel[chan].freq = notetable[11];
+	channel[chan].oct = (note - 1) / 12;
+	channel[chan].freq += inst[channel[chan].inst].slide;	// apply pre-slide
+}
+
+void CmodPlayer::slide_down(unsigned char chan, int amount)
+{
+	channel[chan].freq -= amount;
+	if(channel[chan].freq <= 342)
+		if(channel[chan].oct) {
+			channel[chan].oct--;
+			channel[chan].freq <<= 1;
+		} else
+			channel[chan].freq = 342;
+}
+
+void CmodPlayer::slide_up(unsigned char chan, int amount)
+{
+	channel[chan].freq += amount;
+	if(channel[chan].freq >= 686)
+		if(channel[chan].oct < 7) {
+			channel[chan].oct++;
+			channel[chan].freq >>= 1;
+		} else
+			channel[chan].freq = 686;
+}
+
+void CmodPlayer::tone_portamento(unsigned char chan, unsigned char info)
+{
+	if(channel[chan].freq + (channel[chan].oct << 10) < channel[chan].nextfreq +
+		(channel[chan].nextoct << 10)) {
+		slide_up(chan,info);
+		if(channel[chan].freq + (channel[chan].oct << 10) > channel[chan].nextfreq +
+		(channel[chan].nextoct << 10)) {
+			channel[chan].freq = channel[chan].nextfreq;
+			channel[chan].oct = channel[chan].nextoct;
+		}
+	}
+	if(channel[chan].freq + (channel[chan].oct << 10) > channel[chan].nextfreq +
+		(channel[chan].nextoct << 10)) {
+		slide_down(chan,info);
+		if(channel[chan].freq + (channel[chan].oct << 10) < channel[chan].nextfreq +
+		(channel[chan].nextoct << 10)) {
+			channel[chan].freq = channel[chan].nextfreq;
+			channel[chan].oct = channel[chan].nextoct;
+		}
+	}
+	setfreq(chan);
+}
+
+void CmodPlayer::vibrato(unsigned char chan, unsigned char speed, unsigned char depth)
+{
+	int i;
+
+	if(!speed || !depth)
+		return;
+
+	if(depth > 14)
+		depth = 14;
+
+	for(i=0;i<speed;i++) {
+		channel[chan].trigger++;
+		while(channel[chan].trigger >= 64)
+			channel[chan].trigger -= 64;
+		if(channel[chan].trigger >= 16 && channel[chan].trigger < 48)
+			slide_down(chan,vibratotab[channel[chan].trigger - 16] / (16-depth));
+		if(channel[chan].trigger < 16)
+			slide_up(chan,vibratotab[channel[chan].trigger + 16] / (16-depth));
+		if(channel[chan].trigger >= 48)
+			slide_up(chan,vibratotab[channel[chan].trigger - 48] / (16-depth));
+	}
+	setfreq(chan);
+}
+
+void CmodPlayer::vol_up(unsigned char chan, int amount)
+{
+	if(channel[chan].vol1 + amount < 63)
+		channel[chan].vol1 += amount;
+	else
+		channel[chan].vol1 = 63;
+
+	if(channel[chan].vol2 + amount < 63)
+		channel[chan].vol2 += amount;
+	else
+		channel[chan].vol2 = 63;
+}
+
+void CmodPlayer::vol_down(unsigned char chan, int amount)
+{
+	if(channel[chan].vol1 - amount > 0)
+		channel[chan].vol1 -= amount;
+	else
+		channel[chan].vol1 = 0;
+
+	if(channel[chan].vol2 - amount > 0)
+		channel[chan].vol2 -= amount;
+	else
+		channel[chan].vol2 = 0;
+}
+
+void CmodPlayer::vol_up_alt(unsigned char chan, int amount)
+{
+	if(channel[chan].vol1 + amount < 63)
+		channel[chan].vol1 += amount;
+	else
+		channel[chan].vol1 = 63;
+	if(inst[channel[chan].inst].data[0] & 1)
+		if(channel[chan].vol2 + amount < 63)
+			channel[chan].vol2 += amount;
+		else
+			channel[chan].vol2 = 63;
+}
+
+void CmodPlayer::vol_down_alt(unsigned char chan, int amount)
+{
+	if(channel[chan].vol1 - amount > 0)
+		channel[chan].vol1 -= amount;
+	else
+		channel[chan].vol1 = 0;
+	if(inst[channel[chan].inst].data[0] & 1)
+		if(channel[chan].vol2 - amount > 0)
+			channel[chan].vol2 -= amount;
+		else
+			channel[chan].vol2 = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/protrack.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,107 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2002 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * protrack.h - Generic Protracker Player by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#ifndef H_PROTRACK
+#define H_PROTRACK
+
+#include "player.h"
+
+class CmodPlayer: public CPlayer
+{
+public:
+	CmodPlayer(Copl *newopl);
+	virtual ~CmodPlayer();
+
+	bool update();
+	void rewind(int subsong);
+	float getrefresh();
+
+	unsigned int getpatterns()
+	{ return nop; };
+	unsigned int getpattern()
+	{ return order[ord]; };
+	unsigned int getorders()
+	{ return length; };
+	unsigned int getorder()
+	{ return ord; };
+	unsigned int getrow()
+	{ return rw; };
+	unsigned int getspeed()
+	{ return speed; };
+
+protected:
+	enum Flags {Standard = 0, Decimal = 1, Faust = 2, NoKeyOn = 4};
+
+	struct Instrument {
+		unsigned char data[11],arpstart,arpspeed,arppos,arpspdcnt,misc;
+		signed char slide;
+	} *inst;
+
+	struct Tracks {
+		unsigned char note,command,inst,param2,param1;
+	} **tracks;
+
+	unsigned char *order, *arplist, *arpcmd, initspeed;
+	unsigned short tempo, activechan, **trackord, bpm, flags, nop;
+	unsigned long length, restartpos;
+
+	struct Channel {
+	  unsigned short freq,nextfreq;
+	  unsigned char oct,vol1,vol2,inst,fx,info1,info2,key,nextoct,
+	    note,portainfo,vibinfo1,vibinfo2,arppos,arpspdcnt;
+	  signed char trigger;
+	} *channel;
+
+	void init_trackord();
+	bool init_specialarp();
+	void init_notetable(const unsigned short *newnotetable);
+	bool realloc_order(unsigned long len);
+	bool realloc_patterns(unsigned long pats, unsigned long rows, unsigned long chans);
+	bool realloc_instruments(unsigned long len);
+
+	void dealloc();
+
+private:
+	static const unsigned short sa2_notetable[12];
+	static const unsigned char vibratotab[32];
+
+	unsigned char speed, del, songend, regbd;
+	unsigned short rows, notetable[12];
+	unsigned long rw, ord, nrows, npats, nchans;
+
+	void setvolume(unsigned char chan);
+	void setvolume_alt(unsigned char chan);
+	void setfreq(unsigned char chan);
+	void playnote(unsigned char chan);
+	void setnote(unsigned char chan, int note);
+	void slide_down(unsigned char chan, int amount);
+	void slide_up(unsigned char chan, int amount);
+	void tone_portamento(unsigned char chan, unsigned char info);
+	void vibrato(unsigned char chan, unsigned char speed, unsigned char depth);
+	void vol_up(unsigned char chan, int amount);
+	void vol_down(unsigned char chan, int amount);
+	void vol_up_alt(unsigned char chan, int amount);
+	void vol_down_alt(unsigned char chan, int amount);
+
+	void dealloc_patterns();
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/psi.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,169 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * [xad] PSI player, by Riven the Mage <riven@ok.ru>
+ */
+
+/*
+    - discovery -
+
+  file(s) : 4BIDDEN.COM, PGRID.EXE
+     type : Forbidden Dreams BBStro
+            Power Grid BBStro
+     tune : by Friar Tuck [Shadow Faction/ICE]
+   player : by Psi [Future Crew]
+  comment : seems to me what 4bidden tune & player was ripped from pgrid
+
+  file(s) : MYSTRUNE.COM
+     type : Mystical Runes BBStro
+     tune : by ?
+   player : by Psi [Future Crew]
+*/
+
+#include "psi.h"
+#include "debug.h"
+
+const unsigned char CxadpsiPlayer::psi_adlib_registers[99] =
+{
+  0x20, 0x23, 0x40, 0x43, 0x60, 0x63, 0x80, 0x83, 0xE0, 0xE3, 0xC0,
+  0x21, 0x24, 0x41, 0x44, 0x61, 0x64, 0x81, 0x84, 0xE1, 0xE4, 0xC1,
+  0x22, 0x25, 0x42, 0x45, 0x62, 0x65, 0x82, 0x85, 0xE2, 0xE5, 0xC2,
+  0x28, 0x2B, 0x48, 0x4B, 0x68, 0x6B, 0x88, 0x8B, 0xE8, 0xEB, 0xC3,
+  0x29, 0x2C, 0x49, 0x4C, 0x69, 0x6C, 0x89, 0x8C, 0xE9, 0xEC, 0xC4,
+  0x2A, 0x2D, 0x4A, 0x4D, 0x6A, 0x6D, 0x8A, 0x8D, 0xEA, 0xED, 0xC5,
+  0x30, 0x33, 0x50, 0x53, 0x70, 0x73, 0x90, 0x93, 0xF0, 0xF3, 0xC6,
+  0x31, 0x34, 0x51, 0x54, 0x71, 0x74, 0x91, 0x94, 0xF1, 0xF4, 0xC7,
+  0x32, 0x35, 0x52, 0x55, 0x72, 0x75, 0x92, 0x95, 0xF2, 0xF5, 0xC8
+};
+
+const unsigned short CxadpsiPlayer::psi_notes[16] =
+{
+  0x216B, 0x2181, 0x2198, 0x21B0, 0x21CA, 0x21E5, 0x2202, 0x2220,
+  0x2241, 0x2263, 0x2287, 0x2364,
+  0x0000, 0x0000, 0x0000, 0x0000 // by riven
+};
+
+CPlayer *CxadpsiPlayer::factory(Copl *newopl)
+{
+  return new CxadpsiPlayer(newopl);
+}
+
+void CxadpsiPlayer::xadplayer_rewind(int subsong)
+{
+  opl_write(0x01, 0x20);
+  opl_write(0x08, 0x00);
+  opl_write(0xBD, 0x00);
+
+  // define instruments
+  psi.instr_table = (unsigned short *)&tune[((psi_header *)&tune[0])->instr_ptr];
+
+  for(int i=0; i<8; i++)
+  {
+    for(int j=0; j<11; j++)
+      opl_write(psi_adlib_registers[i*11 + j],tune[psi.instr_table[i] + j]);
+
+    opl_write(0xA0+i, 0x00);
+    opl_write(0xB0+i, 0x00);
+
+    psi.note_delay[i] = 1;
+    psi.note_curdelay[i] = 1;
+    psi.looping[i] = 0;
+  }
+
+  // calculate sequence pointer
+  psi.seq_table = (unsigned short *)&tune[((psi_header *)&tune[0])->seq_ptr];
+}
+
+void CxadpsiPlayer::xadplayer_update()
+{
+  unsigned short ptr;
+
+  for(int i=0; i<8; i++)
+  {
+    ptr = psi.seq_table[i<<1];
+
+    psi.note_curdelay[i]--;
+
+    if (!psi.note_curdelay[i])
+    {
+      opl_write(0xA0+i, 0x00);
+      opl_write(0xB0+i, 0x00);
+
+      unsigned char event = tune[ptr++];
+#ifdef DEBUG
+  AdPlug_LogWrite("channel %02X, event %02X:\n",i+1,event);
+#endif
+
+      // end of sequence ?
+      if (!event)
+      {
+        ptr = psi.seq_table[(i<<1) + 1];
+
+        event = tune[ptr++];
+#ifdef DEBUG
+  AdPlug_LogWrite(" channel %02X, event %02X:\n",i+1,event);
+#endif
+
+        // set sequence loop flag
+        psi.looping[i] = 1;
+
+        // module loop ?
+        plr.looping = 1;
+        for(int j=0; j<8; j++)
+          plr.looping &= psi.looping[j];
+      }
+
+      // new note delay ?
+      if (event & 0x80)
+      {
+        psi.note_delay[i] = (event & 0x7F);
+
+        event = tune[ptr++];
+#ifdef DEBUG
+  AdPlug_LogWrite("  channel %02X, event %02X:\n",i+1,event);
+#endif
+      }
+
+      psi.note_curdelay[i] = psi.note_delay[i];
+
+      // play note
+      unsigned short note = psi_notes[event & 0x0F];
+
+      opl_write(0xA0+i, note & 0xFF);
+      opl_write(0xB0+i, (note >> 8) + ((event >> 2) & 0xFC));
+
+      // save position
+      psi.seq_table[i<<1] = ptr;
+    }
+  }
+}
+
+float CxadpsiPlayer::xadplayer_getrefresh()
+{
+  return 70.0f;
+}
+
+std::string CxadpsiPlayer::xadplayer_gettype()
+{
+  return std::string("xad: psi player");
+}
+
+unsigned int CxadpsiPlayer::xadplayer_getinstruments()
+{
+  return 8;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/psi.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,64 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * [xad] PSI player, by Riven the Mage <riven@ok.ru>
+ */
+
+#include "xad.h"
+
+class CxadpsiPlayer: public CxadPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+  CxadpsiPlayer(Copl *newopl): CxadPlayer(newopl)
+    { }
+
+protected:
+  struct psi_header
+  {
+    unsigned short  instr_ptr;
+    unsigned short  seq_ptr;
+  };
+
+  struct
+  {
+    unsigned short  *instr_table;
+    unsigned short  *seq_table;
+    unsigned char   note_delay[9];
+    unsigned char   note_curdelay[9];
+    unsigned char   looping[9];
+  } psi;
+  //
+  bool		  xadplayer_load()
+    {
+      if(xad.fmt == PSI)
+	return true;
+      else
+	return false;
+    }
+  void            xadplayer_rewind(int subsong);
+  void            xadplayer_update();
+  float           xadplayer_getrefresh();
+  std::string     xadplayer_gettype();
+  unsigned int    xadplayer_getinstruments();
+
+private:
+  static const unsigned char psi_adlib_registers[99];
+  static const unsigned short psi_notes[16];
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/rad.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,124 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * rad.cpp - RAD Loader by Simon Peter <dn.tlp@gmx.net>
+ *
+ * BUGS:
+ * some volumes are dropped out
+ */
+
+#include "rad.h"
+
+CPlayer *CradLoader::factory(Copl *newopl)
+{
+  return new CradLoader(newopl);
+}
+
+bool CradLoader::load(const std::string &filename, const CFileProvider &fp)
+{
+        binistream *f = fp.open(filename); if(!f) return false;
+	char id[16];
+	unsigned char buf,ch,c,b,inp;
+	char bufstr[2] = "\0";
+	unsigned int i,j;
+	unsigned short patofs[32];
+	const unsigned char convfx[16] = {255,1,2,3,255,5,255,255,255,255,20,255,17,0xd,255,19};
+
+	// file validation section
+	f->readString(id, 16); version = f->readInt(1);
+	if(strncmp(id,"RAD by REALiTY!!",16) || version != 0x10)
+	  { fp.close(f); return false; }
+
+	// load section
+	radflags = f->readInt(1);
+	if(radflags & 128) {	// description
+		memset(desc,0,80*22);
+		while((buf = f->readInt(1)))
+			if(buf == 1)
+				strcat(desc,"\n");
+			else
+				if(buf >= 2 && buf <= 0x1f)
+					for(i=0;i<buf;i++)
+						strcat(desc," ");
+				else {
+					*bufstr = buf;
+					strcat(desc,bufstr);
+				}
+	}
+	while((buf = f->readInt(1))) {	// instruments
+		buf--;
+		inst[buf].data[2] = f->readInt(1); inst[buf].data[1] = f->readInt(1);
+		inst[buf].data[10] = f->readInt(1); inst[buf].data[9] = f->readInt(1);
+		inst[buf].data[4] = f->readInt(1); inst[buf].data[3] = f->readInt(1);
+		inst[buf].data[6] = f->readInt(1); inst[buf].data[5] = f->readInt(1);
+		inst[buf].data[0] = f->readInt(1);
+		inst[buf].data[8] = f->readInt(1); inst[buf].data[7] = f->readInt(1);
+	}
+	length = f->readInt(1);
+	for(i = 0; i < length; i++) order[i] = f->readInt(1);	// orderlist
+	for(i = 0; i < 32; i++) patofs[i] = f->readInt(2);	// pattern offset table
+	init_trackord();		// patterns
+	for(i=0;i<32;i++)
+		if(patofs[i]) {
+			f->seek(patofs[i]);
+			do {
+				buf = f->readInt(1); b = buf & 127;
+				do {
+					ch = f->readInt(1); c = ch & 127;
+					inp = f->readInt(1);
+					tracks[i*9+c][b].note = inp & 127;
+					tracks[i*9+c][b].inst = (inp & 128) >> 3;
+					inp = f->readInt(1);
+					tracks[i*9+c][b].inst += inp >> 4;
+					tracks[i*9+c][b].command = inp & 15;
+					if(inp & 15) {
+						inp = f->readInt(1);
+						tracks[i*9+c][b].param1 = inp / 10;
+						tracks[i*9+c][b].param2 = inp % 10;
+					}
+				} while(!(ch & 128));
+			} while(!(buf & 128));
+		} else
+			memset(trackord[i],0,9*2);
+	fp.close(f);
+
+	// convert replay data
+	for(i=0;i<32*9;i++)	// convert patterns
+		for(j=0;j<64;j++) {
+			if(tracks[i][j].note == 15)
+				tracks[i][j].note = 127;
+			if(tracks[i][j].note > 16 && tracks[i][j].note < 127)
+				tracks[i][j].note -= 4 * (tracks[i][j].note >> 4);
+			if(tracks[i][j].note && tracks[i][j].note < 126)
+				tracks[i][j].note++;
+			tracks[i][j].command = convfx[tracks[i][j].command];
+		}
+	restartpos = 0; activechan = 0xffff; initspeed = radflags & 31;
+	bpm = radflags & 64 ? 0 : 50; flags = Decimal;
+
+	rewind(0);
+	return true;
+}
+
+float CradLoader::getrefresh()
+{
+	if(tempo)
+		return (float) (tempo);
+	else
+		return 18.2f;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/rad.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,44 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * rad.h - RAD Loader by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "protrack.h"
+
+class CradLoader: public CmodPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	CradLoader(Copl *newopl)
+		: CmodPlayer(newopl)
+	{ *desc = '\0'; };
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+	float getrefresh();
+
+	std::string gettype()
+	{ return std::string("Reality ADlib Tracker"); };
+	std::string getdesc()
+	{ return std::string(desc); };
+
+private:
+	unsigned char version,radflags;
+	char desc[80*22];
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/rat.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,290 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * [xad] RAT player, by Riven the Mage <riven@ok.ru>
+ */
+
+/*
+    - discovery -
+
+  file(s) : PINA.EXE
+     type : Experimental Connection BBStro tune
+     tune : by (?)Ratt/GRIF
+   player : by (?)Ratt/GRIF
+  comment : there are bug in original replayer's adlib_init(): wrong frequency registers.
+*/
+
+#include "rat.h"
+#include "debug.h"
+
+const unsigned char CxadratPlayer::rat_adlib_bases[18] =
+{
+  0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12,
+  0x03, 0x04, 0x05, 0x0B, 0x0C, 0x0D, 0x13, 0x14, 0x15
+};
+
+const unsigned short CxadratPlayer::rat_notes[16] =
+{
+  0x157, 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287,
+  0x000, 0x000, 0x000, 0x000 // by riven
+};
+
+CPlayer *CxadratPlayer::factory(Copl *newopl)
+{
+  return new CxadratPlayer(newopl);
+}
+
+bool CxadratPlayer::xadplayer_load()
+{
+  if(xad.fmt != RAT)
+    return false;
+
+  // load header
+  memcpy(&rat.hdr, &tune[0], sizeof(rat_header));
+
+  // is 'RAT'-signed ?
+  if (strncmp(rat.hdr.id,"RAT",3))
+    return false;
+
+  // is version 1.0 ?
+  if (rat.hdr.version != 0x10)
+    return false;
+
+  // load order
+  rat.order = &tune[0x40];
+
+  // load instruments
+  rat.inst = (rat_instrument *)&tune[0x140];
+
+  // load pattern data
+  unsigned char *event_ptr = &tune[rat.hdr.patseg << 4];
+
+  for(int i=0;i<rat.hdr.numpat;i++)
+    for(int j=0;j<64;j++)
+      for(int k=0;k<rat.hdr.numchan;k++)
+      {
+        memcpy(&rat.tracks[i][j][k], event_ptr, sizeof(rat_event));
+
+        event_ptr += sizeof(rat_event);
+      }
+
+  return true;
+}
+
+void CxadratPlayer::xadplayer_rewind(int subsong)
+{
+  int i;
+
+  rat.order_pos = rat.hdr.order_start;
+  rat.pattern_pos = 0;
+  rat.volume = rat.hdr.volume;
+
+  plr.speed = rat.hdr.speed;
+
+  // clear channel data
+  memset(&rat.channel, 0, sizeof(rat.channel[0])*9);
+
+  // init OPL
+  opl_write(0x01, 0x20);
+  opl_write(0x08, 0x00);
+  opl_write(0xBD, 0x00);
+
+  // set default frequencies
+  for(i=0;i<9;i++)
+  {
+    opl_write(0xA0+i, 0x00);
+    opl_write(0xA3+i, 0x00);
+    opl_write(0xB0+i, 0x00);
+    opl_write(0xB3+i, 0x00);
+  }
+
+  // set default volumes
+  for(i=0;i<0x1F;i++)
+    opl_write(0x40+i, 0x3F);
+}
+
+void CxadratPlayer::xadplayer_update()
+{
+  int i;
+
+  rat_event event;
+
+  // process events
+  for(i=0;i<rat.hdr.numchan;i++)
+  {
+    memcpy(&event,&rat.tracks[rat.order[rat.order_pos]][rat.pattern_pos][i],sizeof(rat_event));
+#ifdef DEBUG
+   AdPlug_LogWrite("order %02X, pattern %02X, row %02X, channel %02X, event %02X %02X %02X %02X %02X:\n",
+	         rat.order_pos, rat.order[rat.order_pos], rat.pattern_pos, i, event.note, event.instrument, event.volume, event.fx, event.fxp
+           );
+#endif
+
+    // is instrument ?
+    if (event.instrument != 0xFF)
+    {
+      rat.channel[i].instrument = event.instrument - 1;
+      rat.channel[i].volume = rat.inst[event.instrument - 1].volume;
+    }
+
+    // is volume ?
+    if (event.volume != 0xFF)
+      rat.channel[i].volume = event.volume;
+
+    // is note ?
+    if (event.note != 0xFF)
+    {
+      // mute channel
+      opl_write(0xB0+i, 0x00);
+      opl_write(0xA0+i, 0x00);
+
+      // if note != 0xFE then play
+      if (event.note != 0xFE)
+      {
+        unsigned char ins = rat.channel[i].instrument;
+
+        // synthesis/feedback
+        opl_write(0xC0+i, rat.inst[ins].connect);
+
+        // controls
+		opl_write(0x20+rat_adlib_bases[i], rat.inst[ins].mod_ctrl);
+        opl_write(0x20+rat_adlib_bases[i+9], rat.inst[ins].car_ctrl);
+
+        // volumes
+		opl_write(0x40+rat_adlib_bases[i], __rat_calc_volume(rat.inst[ins].mod_volume,rat.channel[i].volume,rat.volume));
+        opl_write(0x40+rat_adlib_bases[i+9], __rat_calc_volume(rat.inst[ins].car_volume,rat.channel[i].volume,rat.volume));
+
+        // attack/decay
+		opl_write(0x60+rat_adlib_bases[i], rat.inst[ins].mod_AD);
+        opl_write(0x60+rat_adlib_bases[i+9], rat.inst[ins].car_AD);
+
+        // sustain/release
+		opl_write(0x80+rat_adlib_bases[i], rat.inst[ins].mod_SR);
+        opl_write(0x80+rat_adlib_bases[i+9], rat.inst[ins].car_SR);
+
+        // waveforms
+		opl_write(0xE0+rat_adlib_bases[i], rat.inst[ins].mod_wave);
+        opl_write(0xE0+rat_adlib_bases[i+9], rat.inst[ins].car_wave);
+
+        // octave/frequency
+        unsigned short freq = rat.inst[ins].freq * rat_notes[event.note & 0x0F] / 0x20AB;
+
+        opl_write(0xA0+i, freq & 0xFF);
+        opl_write(0xB0+i, (freq >> 8) | ((event.note & 0xF0) >> 2) | 0x20);
+      }
+    }
+
+    // is effect ?
+    if (event.fx != 0xFF)
+    {
+      rat.channel[i].fx = event.fx;
+      rat.channel[i].fxp = event.fxp;
+    }
+  }
+
+  // next row
+  rat.pattern_pos++;
+
+  // process effects
+  for(i=0;i<rat.hdr.numchan;i++)
+  {
+    unsigned char old_order_pos = rat.order_pos;
+
+    switch (rat.channel[i].fx)
+    {
+      case 0x01: // 0x01: Set Speed
+        plr.speed = rat.channel[i].fxp;
+        break;
+      case 0x02: // 0x02: Position Jump
+        if (rat.channel[i].fxp < rat.hdr.order_end)
+          rat.order_pos = rat.channel[i].fxp;
+        else
+          rat.order_pos = 0;
+
+        // jumpback ?
+        if (rat.order_pos <= old_order_pos)
+          plr.looping = 1;
+
+        rat.pattern_pos = 0;
+        break;
+      case 0x03: // 0x03: Pattern Break (?)
+        rat.pattern_pos = 0x40;
+        break;
+    }
+
+    rat.channel[i].fx = 0;
+  }
+
+  // end of pattern ?
+  if (rat.pattern_pos >= 0x40)
+  {
+    rat.pattern_pos = 0;
+
+    rat.order_pos++;
+
+    // end of module ?
+    if (rat.order_pos == rat.hdr.order_end)
+    {
+      rat.order_pos = rat.hdr.order_loop;
+
+      plr.looping = 1;
+    }
+  }
+}
+
+float CxadratPlayer::xadplayer_getrefresh()
+{
+  return 60.0f;
+}
+
+std::string CxadratPlayer::xadplayer_gettype()
+{
+  return (std::string("xad: rat player"));
+}
+
+std::string CxadratPlayer::xadplayer_gettitle()
+{
+  return (std::string(rat.hdr.title,32));
+}
+
+unsigned int CxadratPlayer::xadplayer_getinstruments()
+{
+  return rat.hdr.numinst;
+}
+
+/* -------- Internal Functions ---------------------------- */
+
+unsigned char CxadratPlayer::__rat_calc_volume(unsigned char ivol, unsigned char cvol, unsigned char gvol)
+{
+#ifdef DEBUG
+   AdPlug_LogWrite("volumes: instrument %02X, channel %02X, global %02X:\n", ivol, cvol, gvol);
+#endif
+  unsigned short vol;
+
+  vol   =  ivol;
+  vol  &=  0x3F;
+  vol  ^=  0x3F;
+  vol  *=  cvol;
+  vol >>=  6;
+  vol  *=  gvol;
+  vol >>=  6;
+  vol  ^=  0x3F;
+
+  vol  |=  ivol & 0xC0;
+
+  return vol;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/rat.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,121 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * [xad] RAT player, by Riven the Mage <riven@ok.ru>
+ */
+
+#include "xad.h"
+
+class CxadratPlayer: public CxadPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+  CxadratPlayer(Copl *newopl): CxadPlayer(newopl)
+    { }
+
+protected:
+  struct rat_header
+  {
+    char            id[3];
+    unsigned char   version;
+    char            title[32];
+    unsigned char   numchan;
+    unsigned char   reserved_25;
+    unsigned char   order_end;
+    unsigned char   reserved_27;
+    unsigned char   numinst;              // ?: Number of Instruments
+    unsigned char   reserved_29;
+    unsigned char   numpat;               // ?: Number of Patterns
+    unsigned char   reserved_2B;
+    unsigned char   order_start;
+    unsigned char   reserved_2D;
+    unsigned char   order_loop;
+    unsigned char   reserved_2F;
+    unsigned char   volume;
+    unsigned char   speed;
+    unsigned char   reserved_32[12];
+    unsigned short  patseg;
+  };
+
+  struct rat_event
+  {
+    unsigned char   note;
+    unsigned char   instrument;
+    unsigned char   volume;
+    unsigned char   fx;
+    unsigned char   fxp;
+  };
+
+  struct rat_instrument
+  {
+    unsigned short  freq;
+    unsigned char   reserved_2[2];
+    unsigned char   mod_ctrl;
+    unsigned char   car_ctrl;
+    unsigned char   mod_volume;   
+    unsigned char   car_volume;   
+    unsigned char   mod_AD;       
+    unsigned char   car_AD;       
+    unsigned char   mod_SR;       
+    unsigned char   car_SR;       
+    unsigned char   mod_wave;
+    unsigned char   car_wave;
+    unsigned char   connect;
+    unsigned char   reserved_F;
+    unsigned char   volume;
+    unsigned char   reserved_11[3];
+  };
+
+  struct
+  {
+    rat_header      hdr;
+
+    unsigned char   volume;
+    unsigned char   order_pos;
+    unsigned char   pattern_pos;
+
+    unsigned char   *order;
+
+    rat_instrument  *inst;
+
+    rat_event       tracks[256][64][9];
+
+    struct
+    {
+      unsigned char   instrument;
+      unsigned char   volume;
+      unsigned char   fx;
+      unsigned char   fxp;
+    } channel[9];
+  } rat;
+  //
+  bool            xadplayer_load();
+  void            xadplayer_rewind(int subsong);
+  void            xadplayer_update();
+  float           xadplayer_getrefresh();
+  std::string	    xadplayer_gettype();
+  std::string     xadplayer_gettitle();
+  unsigned int    xadplayer_getinstruments();
+  //
+private:
+  static const unsigned char rat_adlib_bases[18];
+  static const unsigned short rat_notes[16];
+
+  unsigned char   __rat_calc_volume(unsigned char ivol, unsigned char cvol, unsigned char gvol);
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/raw.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,107 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * raw.c - RAW Player by Simon Peter <dn.tlp@gmx.net>
+ *
+ * NOTES:
+ * OPL3 register writes are ignored (not possible with AdLib).
+ */
+
+#include "raw.h"
+
+/*** public methods *************************************/
+
+CPlayer *CrawPlayer::factory(Copl *newopl)
+{
+  return new CrawPlayer(newopl);
+}
+
+bool CrawPlayer::load(const std::string &filename, const CFileProvider &fp)
+{
+  binistream *f = fp.open(filename); if(!f) return false;
+  char id[8];
+  unsigned long i;
+
+  // file validation section
+  f->readString(id, 8);
+  if(strncmp(id,"RAWADATA",8)) { fp.close (f); return false; }
+
+  // load section
+  clock = f->readInt(2);	// clock speed
+  length = (fp.filesize(f) - 10) / 2;
+  data = new Tdata [length];
+  for(i = 0; i < length; i++) {
+    data[i].param = f->readInt(1);
+    data[i].command = f->readInt(1);
+  }
+
+  fp.close(f);
+  rewind(0);
+  return true;
+}
+
+bool CrawPlayer::update()
+{
+  bool	setspeed;
+
+  if(pos >= length) return false;
+
+  if(del) {
+    del--;
+    return !songend;
+  }
+
+  do {
+    setspeed = false;
+    switch(data[pos].command) {
+    case 0: del = data[pos].param - 1; break;
+    case 2:
+      if(!data[pos].param) {
+	pos++;
+	speed = data[pos].param + (data[pos].command << 8);
+	setspeed = true;
+      } else
+	opl3 = data[pos].param - 1;
+      break;
+    case 0xff:
+      if(data[pos].param == 0xff) {
+	rewind(0);		// auto-rewind song
+	songend = true;
+	return !songend;
+      }
+      break;
+    default:
+      if(!opl3)
+	opl->write(data[pos].command,data[pos].param);
+      break;
+    }
+  } while(data[pos++].command || setspeed);
+
+  return !songend;
+}
+
+void CrawPlayer::rewind(int subsong)
+{
+  pos = del = opl3 = 0; speed = clock; songend = false;
+  opl->init(); opl->write(1,32);	// go to OPL2 mode
+}
+
+float CrawPlayer::getrefresh()
+{
+  return 1193180.0 / (speed ? speed : 0xffff);	// timer oscillator speed / wait register = clock frequency
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/raw.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,52 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * raw.h - RAW Player by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "player.h"
+
+class CrawPlayer: public CPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	CrawPlayer(Copl *newopl)
+		: CPlayer(newopl), data(0)
+	{ };
+	~CrawPlayer()
+	{ if(data) delete [] data; };
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+	bool update();
+	void rewind(int subsong);
+	float getrefresh();
+
+	std::string gettype()
+	{ return std::string("RdosPlay RAW"); };
+
+protected:
+	struct Tdata {
+		unsigned char param,command;
+	} *data;
+
+	unsigned long pos,length;
+	unsigned short clock,speed;
+	unsigned char del,opl3;
+	bool songend;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/realopl.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,158 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999, 2000, 2001 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * realopl.cpp - Real hardware OPL, by Simon Peter (dn.tlp@gmx.net)
+ */
+
+#include <conio.h>
+#include "realopl.h"
+
+#ifdef _MSC_VER
+	#define INP		_inp
+	#define OUTP	_outp
+#elif defined(__WATCOMC__)
+	#define INP		inp
+	#define OUTP	outp
+#endif
+
+/* 
+ * chris: TODO: This isn't quite right.  According to Jeff Lee's doc:
+ *
+ *    "After writing to the register port, you must wait twelve cycles before
+ *   sending the data; after writing the data, eighty-four cycles must elapse
+ *   before any other sound card operation may be performed.
+ *
+ * | The AdLib manual gives the wait times in microseconds: three point three
+ * | (3.3) microseconds for the address, and twenty-three (23) microseconds
+ * | for the data.
+ * |
+ * | The most accurate method of producing the delay is to read the register
+ * | port six times after writing to the register port, and read the register
+ * | port thirty-five times after writing to the data port."
+ *
+ *
+ * In other words, the delay constants represented by {SHORT|LONG}DELAY below 
+ * aren't given in microseconds, but rather direct reads (INB) from the Adlib 
+ * I/O ports.
+ *
+ * Translation: SHORTDELAY should be 6, and LONGDELAY is just fine.  :-)
+ */
+
+#define SHORTDELAY		6					// short delay in I/O port-reads after OPL hardware output
+#define LONGDELAY		35					// long delay in I/O port-reads after OPL hardware output
+
+// the 9 operators as expected by the OPL2
+static const unsigned char op_table[9] = {0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12};
+
+CRealopl::CRealopl(unsigned short initport): adlport(initport), hardvol(0), bequiet(false), nowrite(false)
+{
+	for(int i=0;i<22;i++) {
+		hardvols[i][0] = 0;
+		hardvols[i][1] = 0;
+	}
+}
+
+bool CRealopl::detect()
+{
+	unsigned char stat1,stat2,i;
+
+	hardwrite(4,0x60); hardwrite(4,0x80);
+	stat1 = INP(adlport);
+	hardwrite(2,0xff); hardwrite(4,0x21);
+	for(i=0;i<80;i++)			// wait for adlib
+		INP(adlport);
+	stat2 = INP(adlport);
+	hardwrite(4,0x60); hardwrite(4,0x80);
+
+	if(((stat1 & 0xe0) == 0) && ((stat2 & 0xe0) == 0xc0))
+		return true;
+	else
+		return false;
+}
+
+void CRealopl::setvolume(int volume)
+{
+	int i;
+
+	hardvol = volume;
+	for(i=0;i<9;i++) {
+		hardwrite(0x43+op_table[i],((hardvols[op_table[i]+3][0] & 63) + volume) > 63 ? 63 : hardvols[op_table[i]+3][0] + volume);
+		if(hardvols[i][1] & 1)	// modulator too?
+			hardwrite(0x40+op_table[i],((hardvols[op_table[i]][0] & 63) + volume) > 63 ? 63 : hardvols[op_table[i]][0] + volume);
+	}
+}
+
+void CRealopl::setquiet(bool quiet)
+{
+	bequiet = quiet;
+
+	if(quiet) {
+		oldvol = hardvol;
+		setvolume(63);
+	} else
+		setvolume(oldvol);
+}
+
+void CRealopl::hardwrite(int reg, int val)
+{
+	int i;
+
+	OUTP(adlport,reg);							// set register
+	for(i=0;i<SHORTDELAY;i++)					// wait for adlib
+		INP(adlport);
+	OUTP(adlport+1,val);						// set value
+	for(i=0;i<LONGDELAY;i++)					// wait for adlib
+		INP(adlport);
+}
+
+void CRealopl::write(int reg, int val)
+{
+	int i;
+
+	if(nowrite)
+		return;
+
+	if(bequiet && (reg >= 0xb0 && reg <= 0xb8))	// filter all key-on commands
+		val &= ~32;
+	if(reg >= 0x40 && reg <= 0x55)				// cache volumes
+		hardvols[reg-0x40][0] = val;
+	if(reg >= 0xc0 && reg <= 0xc8)
+		hardvols[reg-0xc0][1] = val;
+	if(hardvol)									// reduce volume
+		for(i=0;i<9;i++) {
+			if(reg == 0x43 + op_table[i])
+				val = ((val & 63) + hardvol) > 63 ? 63 : val + hardvol;
+			else
+				if((reg == 0x40 + op_table[i]) && (hardvols[i][1] & 1))
+					val = ((val & 63) + hardvol) > 63 ? 63 : val + hardvol;
+		}
+
+	hardwrite(reg,val);
+}
+
+void CRealopl::init()
+{
+	int i;
+
+	for (i=0;i<9;i++) {				// stop instruments
+		hardwrite(0xb0 + i,0);				// key off
+		hardwrite(0x80 + op_table[i],0xff);	// fastest release
+	}
+	hardwrite(0xbd,0);	// clear misc. register
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/realopl.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,54 @@
+/*
+ * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2002 Simon Peter <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * realopl.h - Real hardware OPL, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "opl.h"
+
+#define DFL_ADLIBPORT	0x388		// default adlib baseport
+
+class CRealopl: public Copl
+{
+public:	
+	CRealopl(unsigned short initport = DFL_ADLIBPORT);	// initport = OPL2 hardware baseport
+
+	bool detect();					// returns true if adlib compatible board is found, else false
+	void setvolume(int volume);			// set adlib master volume (0 - 63) 0 = loudest, 63 = softest
+	void setquiet(bool quiet = true);	// sets the OPL2 quiet, while still writing to the registers
+	void setport(unsigned short port)	// set new OPL2 hardware baseport
+	{ adlport = port; };
+	void setnowrite(bool nw = true)		// set hardware write status
+	{ nowrite = nw; };
+
+	int getvolume()						// get adlib master volume
+	{ return hardvol; };
+
+	// template methods
+	void write(int reg, int val);
+	void init();
+
+private:
+	void hardwrite(int reg, int val);	// write to OPL2 hardware registers
+
+	unsigned short	adlport;			// adlib hardware baseport
+	int				hardvol,oldvol;		// hardware master volume
+	bool			bequiet;			// quiet status cache
+	char			hardvols[22][2];	// volume cache
+	bool			nowrite;			// don't write to hardware, if true
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/rol.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,723 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * rol.h - ROL Player by OPLx <oplx@yahoo.com>
+ *
+ * Visit:  http://tenacity.hispeed.com/aomit/oplx/
+ */
+#include <algorithm>
+
+#include "rol.h"
+#include "debug.h"
+
+int   const CrolPlayer::kSizeofDataRecord    =  30;
+int   const CrolPlayer::kMaxTickBeat         =  60;
+int   const CrolPlayer::kSilenceNote         = -12;
+int   const CrolPlayer::kNumMelodicVoices    =  9;
+int   const CrolPlayer::kNumPercussiveVoices = 11;
+int   const CrolPlayer::kBassDrumChannel     =  6;
+int   const CrolPlayer::kSnareDrumChannel    =  7;
+int   const CrolPlayer::kTomtomChannel       =  8;
+int   const CrolPlayer::kTomtomFreq          =  2;//4;
+int   const CrolPlayer::kSnareDrumFreq       =  2;//kTomtomFreq + 7;
+float const CrolPlayer::kDefaultUpdateTme    = 18.2f;
+float const CrolPlayer::kPitchFactor         = 400.0f;
+
+static const unsigned char drum_table[4] = {0x14, 0x12, 0x15, 0x11};
+
+CrolPlayer::uint16 const CrolPlayer::kNoteTable[12] = 
+{ 
+    340, // C
+    363, // C#
+    385, // D
+    408, // D#
+    432, // E
+    458, // F
+    485, // F#
+    514, // G
+    544, // G#
+    577, // A
+    611, // A#
+    647  // B
+};
+
+/*** public methods **************************************/
+
+CPlayer *CrolPlayer::factory(Copl *newopl)
+{
+  return new CrolPlayer(newopl);
+}
+//---------------------------------------------------------
+CrolPlayer::CrolPlayer(Copl *newopl)
+:  CPlayer         ( newopl )
+  ,rol_header      ( NULL )
+  ,mNextTempoEvent ( 0 )
+  ,mCurrTick       ( 0 )
+  ,mTimeOfLastNote ( 0 )
+  ,mRefresh        ( kDefaultUpdateTme )
+  ,bdRegister      ( 0 )
+{
+    int n;
+
+    memset(bxRegister,  0, sizeof(bxRegister) );
+    memset(volumeCache, 0, sizeof(volumeCache) );
+    memset(freqCache,   0, sizeof(freqCache) );
+
+    for(n=0; n<11; n++)
+      pitchCache[n]=1.0f;    
+}
+//---------------------------------------------------------
+CrolPlayer::~CrolPlayer()
+{
+    if( rol_header != NULL )
+    {
+        delete rol_header;
+        rol_header=NULL;
+    }
+}
+//---------------------------------------------------------
+bool CrolPlayer::load(const std::string &filename, const CFileProvider &fp)
+{
+    binistream *f = fp.open(filename); if(!f) return false;
+
+    char *fn = new char[filename.length()+9];
+    int i;
+    std::string bnk_filename;
+
+    AdPlug_LogWrite("*** CrolPlayer::load(f, \"%s\") ***\n", filename.c_str());
+    strcpy(fn,filename.data());
+    for (i=strlen(fn)-1; i>=0; i--)
+      if (fn[i] == '/' || fn[i] == '\\')
+	break;
+    strcpy(fn+i+1,"standard.bnk");
+    bnk_filename = fn;
+    delete [] fn;
+    AdPlug_LogWrite("bnk_filename = \"%s\"\n",bnk_filename.c_str());
+
+    rol_header = new SRolHeader;
+    memset( rol_header, 0, sizeof(SRolHeader) );
+
+    rol_header->version_major = f->readInt( 2 );
+    rol_header->version_minor = f->readInt( 2 );
+
+    // Version check
+    if(rol_header->version_major != 0 || rol_header->version_minor != 4) {
+      AdPlug_LogWrite("Unsupported file version %d.%d or not a ROL file!\n",
+	       rol_header->version_major, rol_header->version_minor);
+      AdPlug_LogWrite("--- CrolPlayer::load ---\n");
+      fp.close(f);
+      return false;
+    }
+
+    f->seek( 40, binio::Add );
+
+    rol_header->ticks_per_beat    = f->readInt( 2 );
+    rol_header->beats_per_measure = f->readInt( 2 );
+    rol_header->edit_scale_y      = f->readInt( 2 );
+    rol_header->edit_scale_x      = f->readInt( 2 );
+
+    f->seek( 1, binio::Add );
+
+    rol_header->mode = f->readInt(1);
+
+    f->seek( 90+38+15, binio::Add );
+
+    rol_header->basic_tempo = f->readFloat( binio::Single );
+
+    load_tempo_events( f );
+
+    mTimeOfLastNote = 0;
+
+    if( load_voice_data( f, bnk_filename, fp ) != true )
+    {
+      AdPlug_LogWrite("CrolPlayer::load_voice_data(f) failed!\n");
+      AdPlug_LogWrite("--- CrolPlayer::load ---\n");
+
+      fp.close( f );
+      return false;
+    }
+
+    fp.close( f );
+
+    rewind( 0 );
+    AdPlug_LogWrite("--- CrolPlayer::load ---\n");
+    return true;
+}
+//---------------------------------------------------------
+bool CrolPlayer::update()
+{
+    if( mNextTempoEvent < mTempoEvents.size() &&
+        mTempoEvents[mNextTempoEvent].time == mCurrTick )
+    {
+        SetRefresh( mTempoEvents[mNextTempoEvent].multiplier );
+        ++mNextTempoEvent;
+    }
+
+    TVoiceData::iterator curr = voice_data.begin();
+    TVoiceData::iterator end  = voice_data.end();
+    int voice                 = 0;
+
+    while( curr != end )
+    {
+        UpdateVoice( voice, *curr );
+        ++curr;
+        ++voice;
+    }
+
+    ++mCurrTick;
+
+    if( mCurrTick > mTimeOfLastNote )
+    {
+        return false;
+    }
+
+    return true;
+    //return ( mCurrTick > mTimeOfLastNote ) ? false : true;
+}
+//---------------------------------------------------------
+void CrolPlayer::rewind( int subsong )
+{
+    TVoiceData::iterator curr = voice_data.begin();
+    TVoiceData::iterator end  = voice_data.end();
+
+    while( curr != end )
+    {
+        CVoiceData &voice = *curr;
+
+        voice.Reset();
+        ++curr;
+    }
+
+    memset(bxRegister,  0, sizeof(bxRegister) );
+    memset(volumeCache, 0, sizeof(volumeCache) );
+
+    bdRegister = 0;
+
+    opl->init();        // initialize to melodic by default
+    opl->write(1,0x20); // Enable waveform select (bit 5)
+
+    if( rol_header->mode == 0 )
+    {
+        opl->write( 0xbd, 0x20 ); // select rhythm mode (bit 5)
+        bdRegister = 0x20;
+
+        SetFreq( kTomtomChannel,    24 );
+        SetFreq( kSnareDrumChannel, 31 );
+    }
+
+    mNextTempoEvent = 0;
+    mCurrTick       = 0;
+
+    SetRefresh(1.0f);
+}
+//---------------------------------------------------------
+inline float fmin( int const a, int const b )
+{
+    return static_cast<float>( a < b ? a : b );
+}
+//---------------------------------------------------------
+void CrolPlayer::SetRefresh( float const multiplier )
+{
+    float const tickBeat = fmin(kMaxTickBeat, rol_header->ticks_per_beat);
+
+    mRefresh =  (tickBeat*rol_header->basic_tempo*multiplier) / 60.0f;
+}
+//---------------------------------------------------------
+float CrolPlayer::getrefresh()
+{
+    return mRefresh;
+}
+//---------------------------------------------------------
+void CrolPlayer::UpdateVoice( int const voice, CVoiceData &voiceData )
+{
+    TNoteEvents const &nEvents = voiceData.note_events;
+
+    if( nEvents.empty() || voiceData.mEventStatus & CVoiceData::kES_NoteEnd )
+    {
+        return; // no note data to process, don't bother doing anything.
+    }
+
+    TInstrumentEvents  &iEvents = voiceData.instrument_events;
+    TVolumeEvents      &vEvents = voiceData.volume_events;
+    TPitchEvents       &pEvents = voiceData.pitch_events;
+
+    if( !(voiceData.mEventStatus & CVoiceData::kES_InstrEnd ) &&
+        iEvents[voiceData.next_instrument_event].time == mCurrTick )
+    {
+        if( voiceData.next_instrument_event < iEvents.size() )
+        {
+            send_ins_data_to_chip( voice, iEvents[voiceData.next_instrument_event].ins_index );
+            ++voiceData.next_instrument_event;
+        }
+        else
+        {
+            voiceData.mEventStatus |= CVoiceData::kES_InstrEnd;
+        }
+    }
+
+    if( !(voiceData.mEventStatus & CVoiceData::kES_VolumeEnd ) &&
+        vEvents[voiceData.next_volume_event].time == mCurrTick )
+    {
+      SVolumeEvent const &volumeEvent = vEvents[voiceData.next_volume_event];
+
+        if(  voiceData.next_volume_event < vEvents.size() )
+        {
+            int const volume = (int)(63.0f*(1.0f - volumeEvent.multiplier));
+
+            SetVolume( voice, volume );
+
+            ++voiceData.next_volume_event; // move to next volume event
+        }
+        else
+        {
+            voiceData.mEventStatus |= CVoiceData::kES_VolumeEnd;
+        }        
+    }
+
+    if( voiceData.mForceNote || voiceData.current_note_duration > voiceData.mNoteDuration-1 )
+    {
+        if( mCurrTick != 0 )
+        {
+            ++voiceData.current_note;
+        }
+
+        if( voiceData.current_note < nEvents.size() )
+        {
+            SNoteEvent const &noteEvent = nEvents[voiceData.current_note];
+
+            SetNote( voice, noteEvent.number );
+            voiceData.current_note_duration = 0;
+            voiceData.mNoteDuration         = noteEvent.duration;
+            voiceData.mForceNote            = false;
+        }
+        else
+        {
+            SetNote( voice, kSilenceNote );
+            voiceData.mEventStatus |= CVoiceData::kES_NoteEnd;
+            return;
+        }
+    }
+
+    if( !(voiceData.mEventStatus & CVoiceData::kES_PitchEnd ) &&
+        pEvents[voiceData.next_pitch_event].time == mCurrTick )
+    {
+        if( voiceData.next_pitch_event < pEvents.size() )
+        {
+            SetPitch(voice,pEvents[voiceData.next_pitch_event].variation);
+            ++voiceData.next_pitch_event;
+        }
+        else
+        {
+            voiceData.mEventStatus |= CVoiceData::kES_PitchEnd;
+        }
+    }
+
+    ++voiceData.current_note_duration;
+}
+//---------------------------------------------------------
+void CrolPlayer::SetNote( int const voice, int const note )
+{
+    if( voice < kBassDrumChannel || rol_header->mode )
+    {
+        SetNoteMelodic( voice, note );
+    }
+    else
+    {
+        SetNotePercussive( voice, note );
+    }
+}
+//---------------------------------------------------------
+void CrolPlayer::SetNotePercussive( int const voice, int const note )
+{
+    int const bit_pos = 4-voice+kBassDrumChannel;
+
+    bdRegister &= ~( 1<<bit_pos );
+    opl->write( 0xbd, bdRegister );
+
+    if( note != kSilenceNote )
+    {
+        switch( voice )
+        {
+            case kTomtomChannel:
+                SetFreq( kSnareDrumChannel, note+7 );
+            case kBassDrumChannel:
+                SetFreq( voice, note );
+                break;
+        }
+
+        bdRegister |= 1<<bit_pos;
+        opl->write( 0xbd, bdRegister );
+    }
+}
+//---------------------------------------------------------
+void CrolPlayer::SetNoteMelodic( int const voice, int const note )
+{
+    opl->write( 0xb0+voice, bxRegister[voice] & ~0x20 );
+
+    if( note != kSilenceNote )
+    {
+        SetFreq( voice, note, true );
+    }
+}
+//---------------------------------------------------------
+void CrolPlayer::SetPitch(int const voice, real32 const variation)
+{
+  pitchCache[voice] = variation;
+  freqCache[voice] += (uint16)((((float)freqCache[voice])*(variation-1.0f)) / kPitchFactor);
+
+  opl->write(0xa0+voice,freqCache[voice] & 0xff);
+}
+//---------------------------------------------------------
+void CrolPlayer::SetFreq( int const voice, int const note, bool const keyOn )
+{
+    uint16 freq = kNoteTable[note%12] + ((note/12) << 10);
+    freq += (uint16)((((float)freq)*(pitchCache[voice]-1.0f))/kPitchFactor);
+
+    freqCache[voice] = freq;
+    bxRegister[voice] = ((freq >> 8) & 0x1f);
+
+    opl->write( 0xa0+voice, freq & 0xff );
+    opl->write( 0xb0+voice, bxRegister[voice] | (keyOn ? 0x20 : 0x0) );
+}
+//---------------------------------------------------------
+void CrolPlayer::SetVolume( int const voice, int const volume )
+{
+    volumeCache[voice] = (volumeCache[voice] &0xc0) | volume;
+
+    int const op_offset = ( voice < kSnareDrumChannel || rol_header->mode ) ? 
+                          op_table[voice]+3 : drum_table[voice-kSnareDrumChannel];
+
+    opl->write( 0x40+op_offset, volumeCache[voice] );
+}
+//---------------------------------------------------------
+void CrolPlayer::send_ins_data_to_chip( int const voice, int const ins_index )
+{
+    SRolInstrument &instrument = ins_list[ins_index].instrument;
+
+    send_operator( voice, instrument.modulator, instrument.carrier );
+}
+//---------------------------------------------------------
+void CrolPlayer::send_operator( int const voice, SOPL2Op const &modulator,  SOPL2Op const &carrier )
+{
+    if( voice < kSnareDrumChannel || rol_header->mode )
+    {
+        int const op_offset = op_table[voice];
+
+        opl->write( 0x20+op_offset, modulator.ammulti  );
+        opl->write( 0x40+op_offset, modulator.ksltl    );
+        opl->write( 0x60+op_offset, modulator.ardr     );
+        opl->write( 0x80+op_offset, modulator.slrr     );
+        opl->write( 0xc0+voice    , modulator.fbc      );
+        opl->write( 0xe0+op_offset, modulator.waveform );
+
+        volumeCache[voice] = (carrier.ksltl & 0xc0) | volumeCache[voice] & 0x3f;
+
+        opl->write( 0x23+op_offset, carrier.ammulti  );
+        opl->write( 0x43+op_offset, volumeCache[voice]    );
+        opl->write( 0x63+op_offset, carrier.ardr     );
+        opl->write( 0x83+op_offset, carrier.slrr     );
+//        opl->write( 0xc3+voice    , carrier.fbc      ); <- don't bother writing this.
+        opl->write( 0xe3+op_offset, carrier.waveform );
+    }
+    else
+    {
+        int const op_offset = drum_table[voice-kSnareDrumChannel];
+
+        volumeCache[voice] = (modulator.ksltl & 0xc0) | volumeCache[voice] & 0x3f;
+
+        opl->write( 0x20+op_offset, modulator.ammulti  );
+        opl->write( 0x40+op_offset, volumeCache[voice]      );
+        opl->write( 0x60+op_offset, modulator.ardr     );
+        opl->write( 0x80+op_offset, modulator.slrr     );
+        opl->write( 0xc0+voice    , modulator.fbc      );
+        opl->write( 0xe0+op_offset, modulator.waveform );
+    }
+}
+//---------------------------------------------------------
+void CrolPlayer::load_tempo_events( binistream *f )
+{
+    int16 const num_tempo_events = f->readInt( 2 );
+
+    mTempoEvents.reserve( num_tempo_events );
+
+    for(int i=0; i<num_tempo_events; ++i)
+    {
+        STempoEvent event;
+
+        event.time       = f->readInt( 2 );
+        event.multiplier = f->readFloat( binio::Single );
+        mTempoEvents.push_back( event );
+    }
+}
+//---------------------------------------------------------
+bool CrolPlayer::load_voice_data( binistream *f, std::string const &bnk_filename, const CFileProvider &fp )
+{
+    SBnkHeader bnk_header;
+    binistream *bnk_file = fp.open( bnk_filename.c_str() );
+
+    if( bnk_file )
+    {
+        load_bnk_info( bnk_file, bnk_header );
+
+        int const numVoices = rol_header->mode ? kNumMelodicVoices : kNumPercussiveVoices;
+
+        voice_data.reserve( numVoices );
+        for(int i=0; i<numVoices; ++i)
+        {
+            CVoiceData voice;
+
+            load_note_events( f, voice );
+            load_instrument_events( f, voice, bnk_file, bnk_header );
+            load_volume_events( f, voice );
+            load_pitch_events( f, voice );
+
+            voice_data.push_back( voice );
+        }
+
+        fp.close(bnk_file);
+
+        return true;
+    }
+
+    return false;
+}
+//---------------------------------------------------------
+void CrolPlayer::load_note_events( binistream *f, CVoiceData &voice )
+{
+    f->seek( 15, binio::Add );
+
+    int16 const time_of_last_note = f->readInt( 2 );
+
+    if( time_of_last_note != 0 )
+    {
+        TNoteEvents &note_events = voice.note_events;
+        int16 total_duration     = 0;
+
+        do
+        {
+            SNoteEvent event;
+
+            event.number   = f->readInt( 2 );
+            event.duration = f->readInt( 2 );
+
+            event.number += kSilenceNote; // adding -12
+
+            note_events.push_back( event );
+
+            total_duration += event.duration;
+        } while( total_duration < time_of_last_note );
+
+        if( time_of_last_note > mTimeOfLastNote )
+        {
+            mTimeOfLastNote = time_of_last_note;
+        }
+    }
+
+    f->seek( 15, binio::Add );
+}
+//---------------------------------------------------------
+void CrolPlayer::load_instrument_events( binistream *f, CVoiceData &voice,
+                                         binistream *bnk_file, SBnkHeader const &bnk_header )
+{
+    int16 const number_of_instrument_events = f->readInt( 2 );
+
+    TInstrumentEvents &instrument_events = voice.instrument_events;
+
+    instrument_events.reserve( number_of_instrument_events );
+
+    for(int i=0; i<number_of_instrument_events; ++i)
+    {
+        SInstrumentEvent event;
+        event.time = f->readInt( 2 );
+        f->readString( event.name, 9 );
+
+	    std::string event_name = event.name;
+        event.ins_index = load_rol_instrument( bnk_file, bnk_header, event_name );
+
+        instrument_events.push_back( event );
+
+        f->seek( 1+2, binio::Add );
+    }
+
+    f->seek( 15, binio::Add );
+}
+//---------------------------------------------------------
+void CrolPlayer::load_volume_events( binistream *f, CVoiceData &voice )
+{
+    int16 const number_of_volume_events = f->readInt( 2 );
+
+    TVolumeEvents &volume_events = voice.volume_events;
+
+    volume_events.reserve( number_of_volume_events );
+
+    for(int i=0; i<number_of_volume_events; ++i)
+    {
+        SVolumeEvent event;
+        event.time       = f->readInt( 2 );
+        event.multiplier = f->readFloat( binio::Single );
+
+        volume_events.push_back( event );
+    }
+
+    f->seek( 15, binio::Add );
+}
+//---------------------------------------------------------
+void CrolPlayer::load_pitch_events( binistream *f, CVoiceData &voice )
+{
+    int16 const number_of_pitch_events = f->readInt( 2 );
+
+    TPitchEvents &pitch_events = voice.pitch_events;
+
+    pitch_events.reserve( number_of_pitch_events );
+
+    for(int i=0; i<number_of_pitch_events; ++i)
+    {
+        SPitchEvent event;
+        event.time      = f->readInt( 2 );
+        event.variation = f->readFloat( binio::Single );
+
+        pitch_events.push_back( event );
+    }
+}
+//---------------------------------------------------------
+bool CrolPlayer::load_bnk_info( binistream *f, SBnkHeader &header )
+{
+  header.version_major = f->readInt(1);
+  header.version_minor = f->readInt(1);
+  f->readString( header.signature, 6 );
+
+  header.number_of_list_entries_used  = f->readInt( 2 );
+  header.total_number_of_list_entries = f->readInt( 2 );
+
+  header.abs_offset_of_name_list = f->readInt( 4 );
+  header.abs_offset_of_data      = f->readInt( 4 );
+
+  f->seek( header.abs_offset_of_name_list, binio::Set );
+
+  TInstrumentNames &ins_name_list = header.ins_name_list;
+  ins_name_list.reserve( header.number_of_list_entries_used );
+
+  for(int i=0; i<header.number_of_list_entries_used; ++i)
+    {
+      SInstrumentName instrument;
+
+      instrument.index = f->readInt( 2 );
+      instrument.record_used = f->readInt(1);
+      f->readString( instrument.name, 9 );
+
+      // printf("%s = #%d\n", instrument.name, i );
+
+      ins_name_list.push_back( instrument );
+    }
+
+  //std::sort( ins_name_list.begin(), ins_name_list.end(), StringCompare() );
+
+  return true;
+}
+//---------------------------------------------------------
+int CrolPlayer::load_rol_instrument( binistream *f, SBnkHeader const &header, std::string &name )
+{
+    TInstrumentNames const &ins_name_list = header.ins_name_list;
+
+    int const ins_index = get_ins_index( name );
+
+    if( ins_index != -1 )
+    {
+        return ins_index;
+    }
+
+    typedef TInstrumentNames::const_iterator TInsIter;
+    typedef std::pair<TInsIter, TInsIter>    TInsIterPair;
+
+    TInsIterPair range = std::equal_range( ins_name_list.begin(), 
+                                           ins_name_list.end(), 
+                                           name, 
+                                           StringCompare() );
+
+    if( range.first != range.second )
+    {
+        int const seekOffs = header.abs_offset_of_data + (range.first->index*kSizeofDataRecord);
+        f->seek( seekOffs, binio::Set );
+    }
+
+    SUsedList usedIns;
+    usedIns.name = name;
+
+    if( range.first != range.second )
+    {
+        read_rol_instrument( f, usedIns.instrument );
+    }
+    else
+    {
+        // set up default instrument data here
+        memset( &usedIns.instrument, 0, kSizeofDataRecord );
+    }
+    ins_list.push_back( usedIns );
+
+    return ins_list.size()-1;
+}
+//---------------------------------------------------------
+int CrolPlayer::get_ins_index( std::string const &name ) const
+{
+    for(unsigned int i=0; i<ins_list.size(); ++i)
+    {
+        if( stricmp(ins_list[i].name.c_str(), name.c_str()) == 0 )
+        {
+            return i;
+        }
+    }
+
+    return -1;
+}
+//---------------------------------------------------------
+void CrolPlayer::read_rol_instrument( binistream *f, SRolInstrument &ins )
+{
+  ins.mode = f->readInt(1);
+  ins.voice_number = f->readInt(1);
+
+  read_fm_operator( f, ins.modulator );
+  read_fm_operator( f, ins.carrier );
+
+  ins.modulator.waveform = f->readInt(1);
+  ins.carrier.waveform = f->readInt(1);
+}
+//---------------------------------------------------------
+void CrolPlayer::read_fm_operator( binistream *f, SOPL2Op &opl2_op )
+{
+  SFMOperator fm_op;
+
+  fm_op.key_scale_level = f->readInt(1);
+  fm_op.freq_multiplier = f->readInt(1);
+  fm_op.feed_back = f->readInt(1);
+  fm_op.attack_rate = f->readInt(1);
+  fm_op.sustain_level = f->readInt(1);
+  fm_op.sustaining_sound = f->readInt(1);
+  fm_op.decay_rate = f->readInt(1);
+  fm_op.release_rate = f->readInt(1);
+  fm_op.output_level = f->readInt(1);
+  fm_op.amplitude_vibrato = f->readInt(1);
+  fm_op.frequency_vibrato = f->readInt(1);
+  fm_op.envelope_scaling = f->readInt(1);
+  fm_op.fm_type = f->readInt(1);
+
+  opl2_op.ammulti = fm_op.amplitude_vibrato << 7 | fm_op.frequency_vibrato << 6 | fm_op.sustaining_sound << 5 | fm_op.envelope_scaling << 4 | fm_op.freq_multiplier;
+  opl2_op.ksltl   = fm_op.key_scale_level   << 6 | fm_op.output_level;
+  opl2_op.ardr    = fm_op.attack_rate       << 4 | fm_op.decay_rate;
+  opl2_op.slrr    = fm_op.sustain_level     << 4 | fm_op.release_rate;
+  opl2_op.fbc     = fm_op.feed_back         << 1 | (fm_op.fm_type ^ 1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/rol.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,308 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * rol.h - ROL Player by OPLx <oplx@yahoo.com>
+ *
+ * Visit:  http://tenacity.hispeed.com/aomit/oplx/
+ */
+#ifndef H_ROLPLAYER
+#define H_ROLPLAYER
+
+#include <vector>
+#include <string>
+
+#include "player.h"
+
+class CrolPlayer: public CPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+    CrolPlayer(Copl *newopl);
+
+    ~CrolPlayer();
+
+    bool  load      (const std::string &filename, const CFileProvider &fp);
+    bool  update    ();
+    void  rewind    (int subsong);	// rewinds to specified subsong
+    float getrefresh();			// returns needed timer refresh rate
+
+    std::string gettype() { return std::string("Adlib Visual Composer"); }
+
+private:
+    typedef unsigned short    uint16;
+    typedef signed   short    int16;
+#ifdef __x86_64__
+    typedef signed   int      int32;
+#else
+    typedef signed long int   int32;
+#endif
+    typedef float             real32;
+
+    typedef struct
+    {
+        uint16 version_major;
+        uint16 version_minor;
+        char   unused0[40];
+        uint16 ticks_per_beat;
+        uint16 beats_per_measure;
+        uint16 edit_scale_y;
+        uint16 edit_scale_x;
+        char   unused1;
+        char   mode;
+        char   unused2[90];
+        char   filler0[38];
+        char   filler1[15];
+        real32 basic_tempo;
+    } SRolHeader;
+
+    typedef struct
+    {
+        int16  time;
+        real32 multiplier;
+    } STempoEvent;
+
+    typedef struct
+    {
+        int16 number;
+        int16 duration;
+    } SNoteEvent;
+
+    typedef struct
+    {
+        int16 time;
+        char  name[9];
+        int16 ins_index;
+    } SInstrumentEvent;
+
+    typedef struct
+    {
+        int16  time;
+        real32 multiplier;
+    } SVolumeEvent;
+
+    typedef struct
+    {
+        int16  time;
+        real32 variation;
+    } SPitchEvent;
+
+    typedef std::vector<SNoteEvent>       TNoteEvents;
+    typedef std::vector<SInstrumentEvent> TInstrumentEvents;
+    typedef std::vector<SVolumeEvent>     TVolumeEvents;
+    typedef std::vector<SPitchEvent>      TPitchEvents;
+
+#define bit_pos( pos ) (1<<pos)
+
+    class CVoiceData
+    {
+    public:
+        enum EEventStatus
+        {
+            kES_NoteEnd   = bit_pos( 0 ),
+            kES_PitchEnd  = bit_pos( 1 ),
+            kES_InstrEnd  = bit_pos( 2 ),
+            kES_VolumeEnd = bit_pos( 3 ),
+
+            kES_None     = 0
+        };
+
+        explicit CVoiceData()
+            :   mForceNote           ( true )
+               ,mEventStatus         ( kES_None )
+               ,current_note         ( 0 )
+               ,current_note_duration( 0 )
+               ,mNoteDuration        ( 0 )
+               ,next_instrument_event( 0 )
+               ,next_volume_event    ( 0 )
+               ,next_pitch_event     ( 0 )
+        {
+        }
+
+        void Reset()
+        {
+            mForceNote            = true;
+            mEventStatus          = kES_None;
+            current_note          = 0;
+            current_note_duration = 0;
+            mNoteDuration         = 0;
+            next_instrument_event = 0;
+            next_volume_event     = 0;
+            next_pitch_event      = 0;
+        }
+
+        TNoteEvents       note_events;
+        TInstrumentEvents instrument_events;
+        TVolumeEvents     volume_events;
+        TPitchEvents      pitch_events;
+
+        bool              mForceNote : 1;
+        int               mEventStatus;
+        unsigned int      current_note;
+        int               current_note_duration;
+        int               mNoteDuration;
+        unsigned int      next_instrument_event;
+        unsigned int      next_volume_event;
+        unsigned int      next_pitch_event;
+    };
+
+    typedef struct
+    {
+        uint16 index;
+        char   record_used;
+        char   name[9];
+    } SInstrumentName;
+
+    typedef std::vector<SInstrumentName> TInstrumentNames;
+
+    typedef struct
+    {
+        char   version_major;
+        char   version_minor;
+        char   signature[6];
+        uint16 number_of_list_entries_used;
+        uint16 total_number_of_list_entries;
+        int32  abs_offset_of_name_list;
+        int32  abs_offset_of_data;
+
+        TInstrumentNames ins_name_list;
+    } SBnkHeader;
+
+    typedef struct
+    {
+        unsigned char key_scale_level;
+        unsigned char freq_multiplier;
+        unsigned char feed_back;
+        unsigned char attack_rate;
+        unsigned char sustain_level;
+        unsigned char sustaining_sound;
+        unsigned char decay_rate;
+        unsigned char release_rate;
+        unsigned char output_level;
+        unsigned char amplitude_vibrato;
+        unsigned char frequency_vibrato;
+        unsigned char envelope_scaling;
+        unsigned char fm_type;
+    } SFMOperator;
+
+    typedef struct
+    {
+        unsigned char ammulti;
+        unsigned char ksltl;
+        unsigned char ardr;  
+        unsigned char slrr;
+        unsigned char fbc;
+        unsigned char waveform;
+    } SOPL2Op;
+
+    typedef struct
+    {
+        char        mode;
+        char        voice_number;
+        SOPL2Op     modulator;
+        SOPL2Op     carrier;
+    } SRolInstrument;
+
+    typedef struct
+    {
+        std::string    name;
+        SRolInstrument instrument;
+    } SUsedList;
+
+    void load_tempo_events     ( binistream *f );
+    bool load_voice_data       ( binistream *f, std::string const &bnk_filename, const CFileProvider &fp );
+    void load_note_events      ( binistream *f, CVoiceData &voice );
+    void load_instrument_events( binistream *f, CVoiceData &voice,
+                                 binistream *bnk_file, SBnkHeader const &bnk_header );
+    void load_volume_events    ( binistream *f, CVoiceData &voice );
+    void load_pitch_events     ( binistream *f, CVoiceData &voice );
+
+    bool load_bnk_info         ( binistream *f, SBnkHeader &header );
+    int  load_rol_instrument   ( binistream *f, SBnkHeader const &header, std::string &name );
+    void read_rol_instrument   ( binistream *f, SRolInstrument &ins );
+    void read_fm_operator      ( binistream *f, SOPL2Op &opl2_op );
+    int  get_ins_index( std::string const &name ) const;
+
+    void UpdateVoice( int const voice, CVoiceData &voiceData );
+    void SetNote( int const voice, int const note );
+    void SetNoteMelodic(  int const voice, int const note  );
+    void SetNotePercussive( int const voice, int const note );
+    void SetFreq   ( int const voice, int const note, bool const keyOn=false );
+    void SetPitch  ( int const voice, real32 const variation );
+    void SetVolume ( int const voice, int const volume );
+    void SetRefresh( float const multiplier );
+    void send_ins_data_to_chip( int const voice, int const ins_index );
+    void send_operator( int const voice, SOPL2Op const &modulator, SOPL2Op const &carrier );
+
+    class StringCompare
+    {
+    public:
+        bool operator()( SInstrumentName const &lhs, SInstrumentName const &rhs ) const
+        {
+            return keyLess(lhs.name, rhs.name);
+        }
+
+        bool operator()( SInstrumentName const &lhs, std::string const &rhs ) const
+        {
+            return keyLess(lhs.name, rhs.c_str());
+        }
+
+        bool operator()( std::string const &lhs, SInstrumentName const &rhs ) const
+        {
+            return keyLess(lhs.c_str(), rhs.name);
+        }
+    private:
+        bool keyLess( const char *const lhs, const char *const rhs ) const
+        {
+            return stricmp(lhs, rhs) < 0;
+        }
+    };
+
+    typedef std::vector<CVoiceData> TVoiceData;
+
+    SRolHeader *rol_header;
+    std::vector<STempoEvent>    mTempoEvents;
+    TVoiceData                  voice_data;
+    std::vector<SUsedList>      ins_list;
+
+    unsigned int                mNextTempoEvent;
+    int                         mCurrTick;
+    int                         mTimeOfLastNote;
+    float                       mRefresh;
+    unsigned char               bdRegister;
+    unsigned char               bxRegister[9];
+    unsigned char               volumeCache[11];
+    uint16			freqCache[11];
+    real32                      pitchCache[11];
+
+    static int    const kSizeofDataRecord;
+    static int    const kMaxTickBeat;
+    static int    const kSilenceNote;
+    static int    const kNumMelodicVoices;
+    static int    const kNumPercussiveVoices;
+    static int    const kBassDrumChannel;
+    static int    const kSnareDrumChannel;
+    static int    const kTomtomChannel;
+    static int    const kTomtomFreq;
+    static int    const kSnareDrumFreq;
+    static float  const kDefaultUpdateTme;
+    static float  const kPitchFactor;
+    static uint16 const kNoteTable[12];
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/s3m.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,517 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * s3m.c - S3M Player by Simon Peter <dn.tlp@gmx.net>
+ *
+ * BUGS:
+ * Extra Fine Slides (EEx, FEx) & Fine Vibrato (Uxy) are inaccurate
+ */
+
+#include "s3m.h"
+
+const char Cs3mPlayer::chnresolv[] =	// S3M -> adlib channel conversion
+	{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,-1,-1,-1,-1,-1,-1,-1};
+
+const unsigned short Cs3mPlayer::notetable[12] =		// S3M adlib note table
+			{340,363,385,408,432,458,485,514,544,577,611,647};
+
+const unsigned char Cs3mPlayer::vibratotab[32] =		// vibrato rate table
+			{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1};
+
+/*** public methods *************************************/
+
+CPlayer *Cs3mPlayer::factory(Copl *newopl)
+{
+  return new Cs3mPlayer(newopl);
+}
+
+Cs3mPlayer::Cs3mPlayer(Copl *newopl): CPlayer(newopl)
+{
+	int			i,j,k;
+
+	memset(pattern,255,sizeof(pattern));
+	memset(orders,255,sizeof(orders));
+
+	for(i=0;i<99;i++)		// setup pattern
+		for(j=0;j<64;j++)
+			for(k=0;k<32;k++) {
+				pattern[i][j][k].instrument = 0;
+				pattern[i][j][k].info = 0;
+			}
+}
+
+bool Cs3mPlayer::load(const std::string &filename, const CFileProvider &fp)
+{
+        binistream *f = fp.open(filename); if(!f) return false;
+	unsigned short	insptr[99],pattptr[99];
+	int		i,row;
+	unsigned char	bufval,bufval2;
+	unsigned short	ppatlen;
+	s3mheader	*checkhead;
+	bool		adlibins=false;
+
+	// file validation section
+	checkhead = new s3mheader;
+	load_header(f, checkhead);
+	if((checkhead->kennung != 0x1a) || (checkhead->typ != 16)) {
+		delete checkhead; fp.close(f); return false;
+	} else
+		if(strncmp(checkhead->scrm,"SCRM",4)) {
+			delete checkhead; fp.close(f); return false;
+		} else {	// is an adlib module?
+             	        f->seek(checkhead->ordnum, binio::Add);
+			for(i = 0; i < checkhead->insnum; i++)
+			  insptr[i] = f->readInt(2);
+			for(i=0;i<checkhead->insnum;i++) {
+				f->seek(insptr[i]*16);
+				if(f->readInt(1) >= 2) {
+					adlibins = true;
+					break;
+				}
+			}
+			delete checkhead;
+			if(!adlibins) { fp.close(f); return false; }
+		}
+
+	// load section
+	f->seek(0);	// rewind for load
+	load_header(f, &header);			// read header
+	for(i = 0; i < header.ordnum; i++) orders[i] = f->readInt(1);	// read orders
+	for(i = 0; i < header.insnum; i++) insptr[i] = f->readInt(2);	// instrument parapointers
+	for(i = 0; i < header.patnum; i++) pattptr[i] = f->readInt(2);	// pattern parapointers
+
+	for(i=0;i<header.insnum;i++) {	// load instruments
+		f->seek(insptr[i]*16);
+		inst[i].type = f->readInt(1);
+		f->readString(inst[i].filename, 15);
+		inst[i].d00 = f->readInt(1); inst[i].d01 = f->readInt(1);
+		inst[i].d02 = f->readInt(1); inst[i].d03 = f->readInt(1);
+		inst[i].d04 = f->readInt(1); inst[i].d05 = f->readInt(1);
+		inst[i].d06 = f->readInt(1); inst[i].d07 = f->readInt(1);
+		inst[i].d08 = f->readInt(1); inst[i].d09 = f->readInt(1);
+		inst[i].d0a = f->readInt(1); inst[i].d0b = f->readInt(1);
+		inst[i].volume = f->readInt(1); inst[i].dsk = f->readInt(1);
+		f->ignore(2);
+		inst[i].c2spd = f->readInt(4);
+		f->ignore(12);
+		f->readString(inst[i].name, 28);
+		f->readString(inst[i].scri, 4);
+	}
+
+	for(i=0;i<header.patnum;i++) {	// depack patterns
+		f->seek(pattptr[i]*16);
+		ppatlen = f->readInt(2);
+		unsigned long pattpos = f->pos();
+		for(row=0;(row<64) && (pattpos-pattptr[i]*16<=ppatlen);row++)
+			do {
+            		        bufval = f->readInt(1);
+				if(bufval & 32) {
+				        bufval2 = f->readInt(1);
+					pattern[i][row][bufval & 31].note = bufval2 & 15;
+					pattern[i][row][bufval & 31].oct = (bufval2 & 240) >> 4;
+					pattern[i][row][bufval & 31].instrument = f->readInt(1);
+				}
+				if(bufval & 64)
+				        pattern[i][row][bufval & 31].volume = f->readInt(1);
+				if(bufval & 128) {
+				        pattern[i][row][bufval & 31].command = f->readInt(1);
+					pattern[i][row][bufval & 31].info = f->readInt(1);
+				}
+			} while(bufval);
+	}
+
+	fp.close(f);
+	rewind(0);
+	return true;		// done
+}
+
+bool Cs3mPlayer::update()
+{
+	unsigned char	pattbreak=0,donote;		// remember vars
+	unsigned char	pattnr,chan,row,info;	// cache vars
+	signed char		realchan;
+
+	// effect handling (timer dependant)
+	for(realchan=0; realchan<9; realchan++) {
+		info = channel[realchan].info;	// fill infobyte cache
+		switch(channel[realchan].fx) {
+		case 11:
+		case 12: if(channel[realchan].fx == 11)								// dual command: H00 and Dxy
+					 vibrato(realchan,channel[realchan].dualinfo);
+				 else															// dual command: G00 and Dxy
+					 tone_portamento(realchan,channel[realchan].dualinfo);
+		case 4: if(info <= 0x0f)												// volume slide down
+					if(channel[realchan].vol - info >= 0)
+						channel[realchan].vol -= info;
+					else
+						channel[realchan].vol = 0;
+				if((info & 0x0f) == 0)											// volume slide up
+					if(channel[realchan].vol + (info >> 4) <= 63)
+						channel[realchan].vol += info >> 4;
+					else
+						channel[realchan].vol = 63;
+				setvolume(realchan);
+				break;
+		case 5: if(info == 0xf0 || info <= 0xe0) {								// slide down
+					slide_down(realchan,info);
+					setfreq(realchan);
+				}
+				break;
+		case 6: if(info == 0xf0 || info <= 0xe0) {								// slide up
+					slide_up(realchan,info);
+					setfreq(realchan);
+				}
+				break;
+		case 7: tone_portamento(realchan,channel[realchan].dualinfo); break;	// tone portamento
+		case 8: vibrato(realchan,channel[realchan].dualinfo); break;		// vibrato
+		case 10: channel[realchan].nextfreq = channel[realchan].freq;	// arpeggio
+				 channel[realchan].nextoct = channel[realchan].oct;
+				 switch(channel[realchan].trigger) {
+				 case 0: channel[realchan].freq = notetable[channel[realchan].note]; break;
+				 case 1: if(channel[realchan].note + ((info & 0xf0) >> 4) < 12)
+							 channel[realchan].freq = notetable[channel[realchan].note + ((info & 0xf0) >> 4)];
+						 else {
+							 channel[realchan].freq = notetable[channel[realchan].note + ((info & 0xf0) >> 4) - 12];
+							 channel[realchan].oct++;
+						 }
+						 break;
+				 case 2: if(channel[realchan].note + (info & 0x0f) < 12)
+							 channel[realchan].freq = notetable[channel[realchan].note + (info & 0x0f)];
+						 else {
+							 channel[realchan].freq = notetable[channel[realchan].note + (info & 0x0f) - 12];
+							 channel[realchan].oct++;
+						 }
+						 break;
+				 }
+				 if(channel[realchan].trigger < 2)
+					 channel[realchan].trigger++;
+				 else
+					 channel[realchan].trigger = 0;
+				 setfreq(realchan);
+				 channel[realchan].freq = channel[realchan].nextfreq;
+				 channel[realchan].oct = channel[realchan].nextoct;
+				 break;
+		case 21: vibrato(realchan,(unsigned char) (info / 4)); break;		// fine vibrato
+		}
+	}
+
+	if(del) {		// speed compensation
+		del--;
+		return !songend;
+	}
+
+	// arrangement handling
+	pattnr = orders[ord];
+	if(pattnr == 0xff || ord > header.ordnum) {	// "--" end of song
+		songend = 1;				// set end-flag
+		ord = 0;
+		pattnr = orders[ord];
+		if(pattnr == 0xff)
+			return !songend;
+	}
+	if(pattnr == 0xfe) {		// "++" skip marker
+		ord++; pattnr = orders[ord];
+	}
+
+	// play row
+	row = crow;	// fill row cache
+	for(chan=0;chan<32;chan++) {
+		if(!(header.chanset[chan] & 128))		// resolve S3M -> AdLib channels
+			realchan = chnresolv[header.chanset[chan] & 127];
+		else
+			realchan = -1;		// channel disabled
+		if(realchan != -1) {	// channel playable?
+			// set channel values
+			donote = 0;
+			if(pattern[pattnr][row][chan].note < 14)
+				// tone portamento
+				if(pattern[pattnr][row][chan].command == 7 || pattern[pattnr][row][chan].command == 12) {
+					channel[realchan].nextfreq = notetable[pattern[pattnr][row][chan].note];
+					channel[realchan].nextoct = pattern[pattnr][row][chan].oct;
+				} else {											// normal note
+					channel[realchan].note = pattern[pattnr][row][chan].note;
+					channel[realchan].freq = notetable[pattern[pattnr][row][chan].note];
+					channel[realchan].oct = pattern[pattnr][row][chan].oct;
+					channel[realchan].key = 1;
+					donote = 1;
+				}
+			if(pattern[pattnr][row][chan].note == 14) {	// key off (is 14 here, cause note is only first 4 bits)
+				channel[realchan].key = 0;
+				setfreq(realchan);
+			}
+			if((channel[realchan].fx != 8 && channel[realchan].fx != 11) &&		// vibrato begins
+				(pattern[pattnr][row][chan].command == 8 || pattern[pattnr][row][chan].command == 11)) {
+				channel[realchan].nextfreq = channel[realchan].freq;
+				channel[realchan].nextoct = channel[realchan].oct;
+			}
+			if(pattern[pattnr][row][chan].note >= 14)
+				if((channel[realchan].fx == 8 || channel[realchan].fx == 11) &&	// vibrato ends
+					(pattern[pattnr][row][chan].command != 8 && pattern[pattnr][row][chan].command != 11)) {
+					channel[realchan].freq = channel[realchan].nextfreq;
+					channel[realchan].oct = channel[realchan].nextoct;
+					setfreq(realchan);
+				}
+			if(pattern[pattnr][row][chan].instrument) {	// set instrument
+				channel[realchan].inst = pattern[pattnr][row][chan].instrument - 1;
+				if(inst[channel[realchan].inst].volume < 64)
+					channel[realchan].vol = inst[channel[realchan].inst].volume;
+				else
+					channel[realchan].vol = 63;
+				if(pattern[pattnr][row][chan].command != 7)
+					donote = 1;
+			}
+			if(pattern[pattnr][row][chan].volume != 255)
+				if(pattern[pattnr][row][chan].volume < 64)	// set volume
+					channel[realchan].vol = pattern[pattnr][row][chan].volume;
+				else
+					channel[realchan].vol = 63;
+			channel[realchan].fx = pattern[pattnr][row][chan].command;	// set command
+			if(pattern[pattnr][row][chan].info)			// set infobyte
+				channel[realchan].info = pattern[pattnr][row][chan].info;
+
+			// play note
+			if(donote)
+				playnote(realchan);
+			if(pattern[pattnr][row][chan].volume != 255)	// set volume
+				setvolume(realchan);
+
+			// command handling (row dependant)
+			info = channel[realchan].info;	// fill infobyte cache
+			switch(channel[realchan].fx) {
+			case 1: speed = info; break;							// set speed
+			case 2: if(info <= ord) songend = 1; ord = info; crow = 0; pattbreak = 1; break;	// jump to order
+			case 3: if(!pattbreak) { crow = info; ord++; pattbreak = 1; } break;	// pattern break
+			case 4: if(info > 0xf0)										// fine volume down
+						if(channel[realchan].vol - (info & 0x0f) >= 0)
+							channel[realchan].vol -= info & 0x0f;
+						else
+							channel[realchan].vol = 0;
+					if((info & 0x0f) == 0x0f && info >= 0x1f)			// fine volume up
+						if(channel[realchan].vol + ((info & 0xf0) >> 4) <= 63)
+							channel[realchan].vol += (info & 0xf0) >> 4;
+						else
+							channel[realchan].vol = 63;
+					setvolume(realchan);
+					break;
+			case 5: if(info > 0xf0)	{									// fine slide down
+						slide_down(realchan,(unsigned char) (info & 0x0f));
+						setfreq(realchan);
+					}
+					if(info > 0xe0 && info < 0xf0) {					// extra fine slide down
+						slide_down(realchan,(unsigned char) ((info & 0x0f) / 4));
+						setfreq(realchan);
+					}
+					break;
+			case 6: if(info > 0xf0) {									// fine slide up
+						slide_up(realchan,(unsigned char) (info & 0x0f));
+						setfreq(realchan);
+					}
+					if(info > 0xe0 && info < 0xf0) {					// extra fine slide up
+						slide_up(realchan,(unsigned char) ((info & 0x0f) / 4));
+						setfreq(realchan);
+					}
+					break;
+			case 7:														// tone portamento
+			case 8:	if((channel[realchan].fx == 7 ||				// vibrato (remember info for dual commands)
+					 channel[realchan].fx == 8) && pattern[pattnr][row][chan].info)
+						channel[realchan].dualinfo = info;
+					break;
+			case 10: channel[realchan].trigger = 0; break;			// arpeggio (set trigger)
+			case 19: if(info == 0xb0)									// set loop start
+						loopstart = row;
+					 if(info > 0xb0 && info <= 0xbf)					// pattern loop
+						if(!loopcnt) {
+							loopcnt = info & 0x0f;
+							crow = loopstart;
+							pattbreak = 1;
+						} else
+							if(--loopcnt > 0) {
+								crow = loopstart;
+								pattbreak = 1;
+							}
+					 if((info & 0xf0) == 0xe0)							// patterndelay
+						 del = speed * (info & 0x0f) - 1;
+					 break;
+			case 20: tempo = info; break;							// set tempo
+			}
+		}
+	}
+
+	if(!del)
+		del = speed - 1;// speed compensation
+	if(!pattbreak) {			// next row (only if no manual advance)
+		crow++;
+		if(crow > 63) {
+			crow = 0;
+			ord++;
+			loopstart = 0;
+		}
+	}
+
+	return !songend;		// still playing
+}
+
+void Cs3mPlayer::rewind(int subsong)
+{
+	// set basic variables
+	songend = 0; ord = 0; crow = 0; tempo = header.it;
+	speed = header.is; del = 0; loopstart = 0; loopcnt = 0;
+
+	memset(channel,0,sizeof(channel));
+
+	opl->init();				// reset OPL chip
+	opl->write(1,32);			// Go to ym3812 mode
+}
+
+std::string Cs3mPlayer::gettype()
+{
+	char filever[5];
+
+	switch(header.cwtv) {		// determine version number
+	case 0x1300: strcpy(filever,"3.00"); break;
+	case 0x1301: strcpy(filever,"3.01"); break;
+	case 0x1303: strcpy(filever,"3.03"); break;
+	case 0x1320: strcpy(filever,"3.20"); break;
+	default: strcpy(filever,"3.??");
+	}
+
+	return (std::string("Scream Tracker ") + filever);
+}
+
+float Cs3mPlayer::getrefresh()
+{
+	return (float) (tempo / 2.5);
+}
+
+/*** private methods *************************************/
+
+void Cs3mPlayer::load_header(binistream *f, s3mheader *h)
+{
+  int i;
+
+  f->readString(h->name, 28);
+  h->kennung = f->readInt(1); h->typ = f->readInt(1);
+  f->ignore(2);
+  h->ordnum = f->readInt(2); h->insnum = f->readInt(2);
+  h->patnum = f->readInt(2); h->flags = f->readInt(2);
+  h->cwtv = f->readInt(2); h->ffi = f->readInt(2);
+  f->readString(h->scrm, 4);
+  h->gv = f->readInt(1); h->is = f->readInt(1); h->it = f->readInt(1);
+  h->mv = f->readInt(1); h->uc = f->readInt(1); h->dp = f->readInt(1);
+  f->ignore(8);
+  h->special = f->readInt(2);
+  for(i = 0; i < 32; i++) h->chanset[i] = f->readInt(1);
+}
+
+void Cs3mPlayer::setvolume(unsigned char chan)
+{
+	unsigned char op = op_table[chan], insnr = channel[chan].inst;
+
+	opl->write(0x43 + op,(int)(63-((63-(inst[insnr].d03 & 63))/63.0)*channel[chan].vol) + (inst[insnr].d03 & 192));
+	if(inst[insnr].d0a & 1)
+		opl->write(0x40 + op,(int)(63-((63-(inst[insnr].d02 & 63))/63.0)*channel[chan].vol) + (inst[insnr].d02 & 192));
+}
+
+void Cs3mPlayer::setfreq(unsigned char chan)
+{
+	opl->write(0xa0 + chan, channel[chan].freq & 255);
+	if(channel[chan].key)
+		opl->write(0xb0 + chan, ((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2) | 32);
+	else
+		opl->write(0xb0 + chan, ((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2));
+}
+
+void Cs3mPlayer::playnote(unsigned char chan)
+{
+	unsigned char op = op_table[chan], insnr = channel[chan].inst;
+
+	opl->write(0xb0 + chan, 0);	// stop old note
+
+	// set instrument data
+	opl->write(0x20 + op, inst[insnr].d00);
+	opl->write(0x23 + op, inst[insnr].d01);
+	opl->write(0x40 + op, inst[insnr].d02);
+	opl->write(0x43 + op, inst[insnr].d03);
+	opl->write(0x60 + op, inst[insnr].d04);
+	opl->write(0x63 + op, inst[insnr].d05);
+	opl->write(0x80 + op, inst[insnr].d06);
+	opl->write(0x83 + op, inst[insnr].d07);
+	opl->write(0xe0 + op, inst[insnr].d08);
+	opl->write(0xe3 + op, inst[insnr].d09);
+	opl->write(0xc0 + chan, inst[insnr].d0a);
+
+	// set frequency & play
+	channel[chan].key = 1;
+	setfreq(chan);
+}
+
+void Cs3mPlayer::slide_down(unsigned char chan, unsigned char amount)
+{
+	if(channel[chan].freq - amount > 340)
+		channel[chan].freq -= amount;
+	else
+		if(channel[chan].oct > 0) {
+			channel[chan].oct--;
+			channel[chan].freq = 684;
+		} else
+			channel[chan].freq = 340;
+}
+
+void Cs3mPlayer::slide_up(unsigned char chan, unsigned char amount)
+{
+	if(channel[chan].freq + amount < 686)
+		channel[chan].freq += amount;
+	else
+		if(channel[chan].oct < 7) {
+			channel[chan].oct++;
+			channel[chan].freq = 341;
+		} else
+			channel[chan].freq = 686;
+}
+
+void Cs3mPlayer::vibrato(unsigned char chan, unsigned char info)
+{
+	unsigned char i,speed,depth;
+
+	speed = info >> 4;
+	depth = (info & 0x0f) / 2;
+
+	for(i=0;i<speed;i++) {
+		channel[chan].trigger++;
+		while(channel[chan].trigger >= 64)
+			channel[chan].trigger -= 64;
+		if(channel[chan].trigger >= 16 && channel[chan].trigger < 48)
+			slide_down(chan,(unsigned char) (vibratotab[channel[chan].trigger - 16] / (16-depth)));
+		if(channel[chan].trigger < 16)
+			slide_up(chan,(unsigned char) (vibratotab[channel[chan].trigger + 16] / (16-depth)));
+		if(channel[chan].trigger >= 48)
+			slide_up(chan,(unsigned char) (vibratotab[channel[chan].trigger - 48] / (16-depth)));
+	}
+	setfreq(chan);
+}
+
+void Cs3mPlayer::tone_portamento(unsigned char chan, unsigned char info)
+{
+	if(channel[chan].freq + (channel[chan].oct << 10) < channel[chan].nextfreq +
+		(channel[chan].nextoct << 10))
+		slide_up(chan,info);
+	if(channel[chan].freq + (channel[chan].oct << 10) > channel[chan].nextfreq +
+		(channel[chan].nextoct << 10))
+		slide_down(chan,info);
+	setfreq(chan);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/s3m.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,107 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * s3m.h - AdLib S3M Player by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#ifndef H_ADPLUG_S3M
+#define H_ADPLUG_S3M
+
+#include "player.h"
+
+class Cs3mPlayer: public CPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	Cs3mPlayer(Copl *newopl);
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+	bool update();
+	void rewind(int subsong);
+	float getrefresh();
+
+	std::string gettype();
+	std::string gettitle()
+	{ return std::string(header.name); };
+
+	unsigned int getpatterns()
+	{ return header.patnum; };
+	unsigned int getpattern()
+	{ return orders[ord]; };
+	unsigned int getorders()
+	{ return (header.ordnum-1); };
+	unsigned int getorder()
+	{ return ord; };
+	unsigned int getrow()
+	{ return crow; };
+	unsigned int getspeed()
+	{ return speed; };
+	unsigned int getinstruments()
+	{ return header.insnum; };
+	std::string getinstrument(unsigned int n)
+	{ return std::string(inst[n].name); };
+
+protected:
+	struct s3mheader {
+		char name[28];				// song name
+		unsigned char kennung,typ,dummy[2];
+		unsigned short ordnum,insnum,patnum,flags,cwtv,ffi;
+		char scrm[4];
+		unsigned char gv,is,it,mv,uc,dp,dummy2[8];
+		unsigned short special;
+		unsigned char chanset[32];
+	};
+
+	struct s3minst {
+		unsigned char type;
+		char filename[15];
+		unsigned char d00,d01,d02,d03,d04,d05,d06,d07,d08,d09,d0a,d0b,volume,dsk,dummy[2];
+		unsigned long c2spd;
+		char dummy2[12], name[28],scri[4];
+	} inst[99];
+
+	struct {
+		unsigned char note,oct,instrument,volume,command,info;
+	} pattern[99][64][32];
+
+	struct {
+		unsigned short freq,nextfreq;
+		unsigned char oct,vol,inst,fx,info,dualinfo,key,nextoct,trigger,note;
+	} channel[9];
+
+	s3mheader header;
+	unsigned char orders[256];
+	unsigned char crow,ord,speed,tempo,del,songend,loopstart,loopcnt;
+
+private:
+	static const char chnresolv[];
+	static const unsigned short notetable[12];
+	static const unsigned char vibratotab[32];
+
+	void load_header(binistream *f, s3mheader *h);
+	void setvolume(unsigned char chan);
+	void setfreq(unsigned char chan);
+	void playnote(unsigned char chan);
+	void slide_down(unsigned char chan, unsigned char amount);
+	void slide_up(unsigned char chan, unsigned char amount);
+	void vibrato(unsigned char chan, unsigned char info);
+	void tone_portamento(unsigned char chan, unsigned char info);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/sa2.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,263 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * sa2.cpp - SAdT2 Loader by Simon Peter <dn.tlp@gmx.net>
+ *           SAdT Loader by Mamiya <mamiya@users.sourceforge.net>
+ */
+
+#include <stdio.h>
+
+#include "sa2.h"
+#include "debug.h"
+
+CPlayer *Csa2Loader::factory(Copl *newopl)
+{
+  return new Csa2Loader(newopl);
+}
+
+bool Csa2Loader::load(const std::string &filename, const CFileProvider &fp)
+{
+        binistream *f = fp.open(filename); if(!f) return false;
+	struct {
+		unsigned char data[11],arpstart,arpspeed,arppos,arpspdcnt;
+	} insts;
+	unsigned char buf;
+	int i,j, k, notedis = 0;
+	const unsigned char convfx[16] = {0,1,2,3,4,5,6,255,8,255,10,11,12,13,255,15};
+	unsigned char sat_type;
+	enum SAT_TYPE {
+		HAS_ARPEGIOLIST = (1 << 7),
+		HAS_V7PATTERNS = (1 << 6),
+		HAS_ACTIVECHANNELS = (1 << 5),
+		HAS_TRACKORDER = (1 << 4),
+		HAS_ARPEGIO = (1 << 3),
+		HAS_OLDBPM = (1 << 2),
+		HAS_OLDPATTERNS = (1 << 1),
+		HAS_UNKNOWN127 = (1 << 0)
+	};
+
+	// read header
+	f->readString(header.sadt, 4);
+	header.version = f->readInt(1);
+
+	// file validation section
+	if(strncmp(header.sadt,"SAdT",4)) { fp.close(f); return false; }
+	switch(header.version) {
+	case 1:
+		notedis = +0x18;
+		sat_type = HAS_UNKNOWN127 | HAS_OLDPATTERNS | HAS_OLDBPM;
+		break;
+	case 2:
+		notedis = +0x18;
+		sat_type = HAS_OLDPATTERNS | HAS_OLDBPM;
+		break;
+	case 3:
+		notedis = +0x0c;
+		sat_type = HAS_OLDPATTERNS | HAS_OLDBPM;
+		break;
+	case 4:
+		notedis = +0x0c;
+		sat_type = HAS_ARPEGIO | HAS_OLDPATTERNS | HAS_OLDBPM;
+		break;
+	case 5:
+		notedis = +0x0c;
+		sat_type = HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_OLDPATTERNS | HAS_OLDBPM;
+		break;
+	case 6:
+		sat_type = HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_OLDPATTERNS | HAS_OLDBPM;
+		break;
+	case 7:
+		sat_type = HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_V7PATTERNS;
+		break;
+	case 8:
+		sat_type = HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_TRACKORDER;
+		break;
+	case 9:
+		sat_type = HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_TRACKORDER | HAS_ACTIVECHANNELS;
+		break;
+	default:	/* unknown */
+	        fp.close(f);
+		return false;
+	}
+
+	// load section
+	// instruments
+	for(i = 0; i < 31; i++) {
+		if(sat_type & HAS_ARPEGIO) {
+		        for(j = 0; j < 11; j++) insts.data[j] = f->readInt(1);
+			insts.arpstart = f->readInt(1);
+			insts.arpspeed = f->readInt(1);
+			insts.arppos = f->readInt(1);
+			insts.arpspdcnt = f->readInt(1);
+			inst[i].arpstart = insts.arpstart;
+			inst[i].arpspeed = insts.arpspeed;
+			inst[i].arppos = insts.arppos;
+			inst[i].arpspdcnt = insts.arpspdcnt;
+		} else {
+		        for(j = 0; j < 11; j++) insts.data[j] = f->readInt(1);
+			inst[i].arpstart = 0;
+			inst[i].arpspeed = 0;
+			inst[i].arppos = 0;
+			inst[i].arpspdcnt = 0;
+		}
+		for(j=0;j<11;j++)
+			inst[i].data[j] = insts.data[j];
+		inst[i].misc = 0;
+		inst[i].slide = 0;
+	}
+
+	// instrument names
+	for(i = 0; i < 29; i++) f->readString(instname[i], 17);
+
+	f->ignore(3);		// dummy bytes
+	for(i = 0; i < 128; i++) order[i] = f->readInt(1);	// pattern orders
+	if(sat_type & HAS_UNKNOWN127) f->ignore(127);
+
+	// infos
+	nop = f->readInt(2); length = f->readInt(1); restartpos = f->readInt(1);
+
+	// bpm
+	bpm = f->readInt(2);
+	if(sat_type & HAS_OLDBPM) {
+		bpm = bpm * 125 / 50;		// cps -> bpm
+	}
+
+	if(sat_type & HAS_ARPEGIOLIST) {
+	  init_specialarp();
+	  for(i = 0; i < 256; i++) arplist[i] = f->readInt(1);	// arpeggio list
+	  for(i = 0; i < 256; i++) arpcmd[i] = f->readInt(1);	// arpeggio commands
+	}
+
+	for(i=0;i<64;i++) {				// track orders
+	  for(j=0;j<9;j++) {
+	    if(sat_type & HAS_TRACKORDER)
+	      trackord[i][j] = f->readInt(1);
+	    else
+	      {
+		trackord[i][j] = i * 9 + j;
+	      }
+	  }
+	}
+
+	if(sat_type & HAS_ACTIVECHANNELS)
+	        activechan = f->readInt(2);		// active channels
+	else
+		activechan = 0xffff;
+
+        AdPlug_LogWrite("Csa2Loader::load(\"%s\"): sat_type = %x, nop = %d, "
+		 "length = %d, restartpos = %d, activechan = %x, bpm = %d\n",
+		 filename.c_str(), sat_type, nop, length, restartpos, activechan, bpm);
+
+	// track data
+	if(sat_type & HAS_OLDPATTERNS) {
+		i = 0;
+		while(!f->ateof()) {
+			for(j=0;j<64;j++) {
+				for(k=0;k<9;k++) {
+					buf = f->readInt(1);
+					tracks[i+k][j].note = buf ? (buf + notedis) : 0;
+					tracks[i+k][j].inst = f->readInt(1);
+					tracks[i+k][j].command = convfx[f->readInt(1) & 0xf];
+					tracks[i+k][j].param1 = f->readInt(1);
+					tracks[i+k][j].param2 = f->readInt(1);
+				}
+			}
+			i+=9;
+		}
+	} else
+	  if(sat_type & HAS_V7PATTERNS) {
+		i = 0;
+		while(!f->ateof()) {
+			for(j=0;j<64;j++) {
+				for(k=0;k<9;k++) {
+					buf = f->readInt(1);
+					tracks[i+k][j].note = buf >> 1;
+					tracks[i+k][j].inst = (buf & 1) << 4;
+					buf = f->readInt(1);
+					tracks[i+k][j].inst += buf >> 4;
+					tracks[i+k][j].command = convfx[buf & 0x0f];
+					buf = f->readInt(1);
+					tracks[i+k][j].param1 = buf >> 4;
+					tracks[i+k][j].param2 = buf & 0x0f;
+				}
+			}
+			i+=9;
+		}
+	  } else {
+		i = 0;
+		while(!f->ateof()) {
+			for(j=0;j<64;j++) {
+				buf = f->readInt(1);
+				tracks[i][j].note = buf >> 1;
+				tracks[i][j].inst = (buf & 1) << 4;
+				buf = f->readInt(1);
+				tracks[i][j].inst += buf >> 4;
+				tracks[i][j].command = convfx[buf & 0x0f];
+				buf = f->readInt(1);
+				tracks[i][j].param1 = buf >> 4;
+				tracks[i][j].param2 = buf & 0x0f;
+			}
+			i++;
+		}
+	  }
+	fp.close(f);
+
+	// fix instrument names
+	for(i=0;i<29;i++)
+		for(j=0;j<17;j++)
+			if(!instname[i][j])
+				instname[i][j] = ' ';
+
+	rewind(0);		// rewind module
+	return true;
+}
+
+std::string Csa2Loader::gettype()
+{
+	char tmpstr[40];
+
+	sprintf(tmpstr,"Surprise! Adlib Tracker 2 (version %d)",header.version);
+	return std::string(tmpstr);
+}
+
+std::string Csa2Loader::gettitle()
+{
+	char bufinst[29*17],buf[18];
+	int i,ptr;
+
+	// parse instrument names for song name
+	memset(bufinst,'\0',29*17);
+	for(i=0;i<29;i++) {
+		buf[16] = ' '; buf[17] = '\0';
+		memcpy(buf,instname[i]+1,16);
+		for(ptr=16;ptr>0;ptr--)
+			if(buf[ptr] == ' ')
+				buf[ptr] = '\0';
+			else {
+				if(ptr<16)
+					buf[ptr+1] = ' ';
+				break;
+			}
+		strcat(bufinst,buf);
+	}
+
+	if(strchr(bufinst,'"'))
+		return std::string(bufinst,strchr(bufinst,'"')-bufinst+1,strrchr(bufinst,'"')-strchr(bufinst,'"')-1);
+	else
+		return std::string();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/sa2.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,55 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * sa2.h - SAdT2 Loader by Simon Peter <dn.tlp@gmx.net>
+ *         SAdT Loader by Mamiya <mamiya@users.sourceforge.net>
+ */
+
+#include "protrack.h"
+
+class Csa2Loader: public CmodPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	Csa2Loader(Copl *newopl)
+		: CmodPlayer(newopl)
+	{ }
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+
+	std::string gettype();
+	std::string gettitle();
+	unsigned int getinstruments()
+	{ return 31; }
+	std::string getinstrument(unsigned int n)
+	{
+	  if(n < 29)
+	    return std::string(instname[n],1,16);
+	  else
+	    return std::string("-broken-");
+	}
+
+private:
+	struct sa2header {
+		char sadt[4];
+		unsigned char version;
+	} header;
+
+	char instname[29][17];
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/silentopl.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,30 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999, 2000, 2001 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * silentopl.h - Silent OPL device, by Simon Peter (dn.tlp@gmx.net)
+ */
+
+#include "opl.h"
+
+class CSilentopl: public Copl
+{
+public:
+	void write(int reg, int val) { };
+	void init() { };
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/sng.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,84 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2002 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * sng.cpp - SNG Player by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "sng.h"
+
+CPlayer *CsngPlayer::factory(Copl *newopl)
+{
+  return new CsngPlayer(newopl);
+}
+
+bool CsngPlayer::load(const std::string &filename, const CFileProvider &fp)
+{
+  binistream *f = fp.open(filename); if(!f) return false;
+  int i;
+
+  // load header
+  f->readString(header.id, 4);
+  header.length = f->readInt(2); header.start = f->readInt(2);
+  header.loop = f->readInt(2); header.delay = f->readInt(1);
+  header.compressed = f->readInt(1) ? true : false;
+
+  // file validation section
+  if(strncmp(header.id,"ObsM",4)) { fp.close(f); return false; }
+
+  // load section
+  header.length /= 2; header.start /= 2; header.loop /= 2;
+  data = new Sdata [header.length];
+  for(i = 0; i < header.length; i++) {
+    data[i].val = f->readInt(1);
+    data[i].reg = f->readInt(1);
+  }
+
+  rewind(0);
+  fp.close(f);
+  return true;
+}
+
+bool CsngPlayer::update()
+{
+  if(header.compressed && del) {
+    del--;
+    return !songend;
+  }
+
+  while(data[pos].reg) {
+    opl->write(data[pos].reg, data[pos].val);
+    pos++;
+    if(pos >= header.length) {
+      songend = true;
+      pos = header.loop;
+    }
+  }
+
+  if(!header.compressed)
+    opl->write(data[pos].reg, data[pos].val);
+
+  if(data[pos].val) del = data[pos].val - 1; pos++;
+  if(pos >= header.length) { songend = true; pos = header.loop; }
+  return !songend;
+}
+
+void CsngPlayer::rewind(int subsong)
+{
+  pos = header.start; del = header.delay; songend = false;
+  opl->init(); opl->write(1,32);	// go to OPL2 mode
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/sng.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,64 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2002 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * sng.h - SNG Player by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#ifndef H_ADPLUG_SNGPLAYER
+#define H_ADPLUG_SNGPLAYER
+
+#include "player.h"
+
+class CsngPlayer: public CPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+	CsngPlayer(Copl *newopl)
+		: CPlayer(newopl), data(0)
+	{ };
+	~CsngPlayer()
+	{ if(data) delete [] data; };
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+	bool update();
+	void rewind(int subsong);
+	float getrefresh()
+	{ return 70.0f; };
+
+	std::string gettype()
+	{ return std::string("SNG File Format"); };
+
+protected:
+	struct {
+		char id[4];
+		unsigned short length,start,loop;
+		unsigned char delay;
+		bool compressed;
+	} header;
+
+	struct Sdata {
+		unsigned char val,reg;
+	} *data;
+
+	unsigned char del;
+	unsigned short pos;
+	bool songend;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/u6m.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,923 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * u6m.cpp - Ultima 6 Music Player by Marc Winterrowd.
+ * This code extends the Adlib Winamp plug-in by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "u6m.h"
+
+CPlayer *Cu6mPlayer::factory(Copl *newopl)
+{
+  return new Cu6mPlayer(newopl);
+}
+
+bool Cu6mPlayer::load(const std::string &filename, const CFileProvider &fp)
+{
+    // file validation section
+    // this section only checks a few *necessary* conditions
+    unsigned long filesize, decompressed_filesize;
+    binistream *f;
+
+    f = fp.open(filename); if(!f) return false;
+    filesize = fp.filesize(f);
+
+    if (filesize >= 6)
+    {
+        // check if the file has a valid pseudo-header
+        unsigned char pseudo_header[6];
+        f->readString((char *)pseudo_header, 6);
+        decompressed_filesize = pseudo_header[0] + (pseudo_header[1] << 8);
+
+        if (!( (pseudo_header[2]==0) && (pseudo_header[3]==0) &&
+               (pseudo_header[4] + ((pseudo_header[5] & 0x1)<<8) == 0x100) &&
+               (decompressed_filesize > (filesize-4)) ))
+        {
+	    fp.close(f);
+            return(false);
+        }
+    }
+    else
+    {
+        fp.close(f);
+        return(false);
+    }
+
+    // load section
+    song_data = new unsigned char[decompressed_filesize];
+    unsigned char* compressed_song_data = new unsigned char[filesize-4];
+
+    f->seek(4);
+    f->readString((char *)compressed_song_data, filesize - 4);
+    fp.close(f);
+
+    // attempt to decompress the song data
+    // if unsuccessful, deallocate song_data[] on the spot, and return(false)
+    data_block source, destination;
+    source.size = filesize-4;
+    source.data = compressed_song_data;
+    destination.size = decompressed_filesize;
+    destination.data = song_data;
+	
+    if (!lzw_decompress(source,destination))
+    {
+        delete[] compressed_song_data;
+        delete[] song_data;
+        return(false);
+    }
+
+    // deallocation section
+    delete[] compressed_song_data;
+
+    rewind(0);
+    return (true);
+}
+
+
+bool Cu6mPlayer::update()
+{
+    if (!driver_active)
+    {
+        driver_active = true;
+        dec_clip(read_delay);
+        if (read_delay == 0)
+        {
+            command_loop();
+        }
+
+        // on all Adlib channels: freq slide/vibrato, mute factor slide
+        for (int i = 0; i < 9; i++)
+        {
+            if (channel_freq_signed_delta[i]!=0)
+            // frequency slide + mute factor slide
+            {
+                // freq slide
+                freq_slide(i);
+
+                // mute factor slide
+                if (carrier_mf_signed_delta[i]!=0)
+                {
+                    mf_slide(i);
+                }
+            }
+            else
+            // vibrato + mute factor slide
+            {
+                // vibrato
+                if ((vb_multiplier[i]!=0) && ((channel_freq[i].hi & 0x20)==0x20))
+                {
+                    vibrato(i);
+                }
+
+                // mute factor slide
+                if (carrier_mf_signed_delta[i]!=0)
+                {
+                    mf_slide(i);
+                }
+            }
+        }
+
+        driver_active = false;
+    }
+
+    return !songend;
+}
+
+
+void Cu6mPlayer::rewind(int subsong)
+{
+	played_ticks = 0;
+	songend = false;
+
+    // set the driver's internal variables
+    byte_pair freq_word = {0,0};
+
+    driver_active = false;
+    song_pos = 0;
+    loop_position = 0;   // position of the loop point
+    read_delay = 0;      // delay (in timer ticks) before further song data is read
+ 
+    for (int i = 0; i < 9; i++)
+    {
+        // frequency
+        channel_freq_signed_delta[i] = 0;
+        channel_freq[i] = freq_word;  // Adlib freq settings for each channel
+
+        // vibrato ("vb")
+        vb_current_value[i] = 0;
+        vb_double_amplitude[i] = 0;
+        vb_multiplier[i] = 0;
+        vb_direction_flag[i] = 0;
+
+        // mute factor ("mf") == ~(volume)
+        carrier_mf[i] = 0;
+        carrier_mf_signed_delta[i] = 0;
+        carrier_mf_mod_delay_backup[i] = 0;
+        carrier_mf_mod_delay[i] = 0;
+    }
+
+	while (!subsong_stack.empty())		// empty subsong stack
+		subsong_stack.pop();
+
+    opl->init();
+	out_adlib(1,32);	// go to OPL2 mode
+}
+
+
+float Cu6mPlayer::getrefresh()
+{
+    return ((float)60);   // the Ultima 6 music driver expects to be called at 60 Hz
+}
+
+
+// ============================================================================================
+//
+//
+//    Functions called by load()
+//
+//
+// ============================================================================================
+
+
+// decompress from memory to memory
+bool Cu6mPlayer::lzw_decompress(Cu6mPlayer::data_block source, Cu6mPlayer::data_block dest)
+{
+    bool end_marker_reached = false;
+    int codeword_size = 9;
+    long bits_read = 0;
+    int next_free_codeword = 0x102;
+    int dictionary_size = 0x200;
+    MyDict dictionary = MyDict();
+	std::stack<unsigned char> root_stack;
+
+    long bytes_written = 0;
+
+    int cW;
+    int pW;
+    unsigned char C;
+
+    while (!end_marker_reached)
+    {
+        cW = get_next_codeword(bits_read, source.data, codeword_size);
+        switch (cW)
+        {
+            // re-init the dictionary
+            case 0x100:
+                codeword_size = 9;
+                next_free_codeword = 0x102;
+                dictionary_size = 0x200;
+                dictionary.reset();
+                cW = get_next_codeword(bits_read, source.data, codeword_size);
+                output_root((unsigned char)cW, dest.data, bytes_written);
+                break;
+            // end of compressed file has been reached
+            case 0x101:
+                end_marker_reached = true;
+                break;
+            // (cW <> 0x100) && (cW <> 0x101)
+            default:
+                if (cW < next_free_codeword)  // codeword is already in the dictionary
+                {
+                    // create the string associated with cW (on the stack)
+                    get_string(cW,dictionary,root_stack);
+                    C = root_stack.top();
+                    // output the string represented by cW
+                    while (!root_stack.empty())
+                    {
+                        output_root(root_stack.top(), dest.data, bytes_written);
+                        root_stack.pop();
+                    }
+                    // add pW+C to the dictionary
+                    dictionary.add(C,pW);
+
+                    next_free_codeword++;
+                    if (next_free_codeword >= dictionary_size)
+                    {
+                        if (codeword_size < max_codeword_length)
+                        {
+                            codeword_size += 1;
+                            dictionary_size *= 2;
+                        }
+                    }
+                }
+                else  // codeword is not yet defined
+                {
+                    // create the string associated with pW (on the stack)
+                    get_string(pW,dictionary,root_stack);
+                    C = root_stack.top();
+                    // output the string represented by pW
+                    while (!root_stack.empty())
+                    {
+                        output_root(root_stack.top(), dest.data, bytes_written);
+                        root_stack.pop();
+                    }
+                    // output the char C
+                    output_root(C, dest.data, bytes_written);
+
+                    // the new dictionary entry must correspond to cW
+                    // if it doesn't, something is wrong with the lzw-compressed data.
+                    if (cW != next_free_codeword)
+                    {
+/*                        printf("cW != next_free_codeword!\n");
+                        exit(-1); */
+						return false;
+                    }
+                    // add pW+C to the dictionary
+                    dictionary.add(C,pW);
+ 
+                    next_free_codeword++;
+                    if (next_free_codeword >= dictionary_size)
+                    {
+                        if (codeword_size < max_codeword_length)
+                        {
+                            codeword_size += 1;
+                            dictionary_size *= 2;
+                        }
+                    }
+                };
+                break;
+        }
+        // shift roles - the current cW becomes the new pW
+        pW = cW;
+    }
+
+	return(true);   // indicate successful decompression
+}
+
+
+// --------------------
+// Additional functions
+// --------------------
+
+
+// Read the next code word from the source buffer
+int Cu6mPlayer::get_next_codeword (long& bits_read, unsigned char *source, int codeword_size)
+{
+    unsigned char b0,b1,b2;
+    int codeword;
+ 
+    b0 = source[bits_read/8];
+    b1 = source[bits_read/8+1];
+    b2 = source[bits_read/8+2];
+
+    codeword = ((b2 << 16) + (b1 << 8) + b0);
+    codeword = codeword >> (bits_read % 8);
+    switch (codeword_size)
+    {
+        case 0x9:
+           codeword = codeword & 0x1ff;
+            break;
+        case 0xa:
+            codeword = codeword & 0x3ff;
+            break;
+        case 0xb:
+            codeword = codeword & 0x7ff;
+            break;
+        case 0xc:
+            codeword = codeword & 0xfff;
+            break;
+        default:
+            codeword = -1;   // indicates that an error has occurred
+            break;
+    }
+
+    bits_read += codeword_size;
+    return (codeword);
+}
+
+
+// output a root to memory
+void Cu6mPlayer::output_root(unsigned char root, unsigned char *destination, long& position)
+{
+    destination[position] = root;
+    position++;
+}
+
+
+// output the string represented by a codeword
+void Cu6mPlayer::get_string(int codeword, Cu6mPlayer::MyDict& dictionary, std::stack<unsigned char>& root_stack)
+{
+   unsigned char root;
+   int current_codeword;
+
+   current_codeword = codeword;
+
+   while (current_codeword > 0xff)
+   {
+      root = dictionary.get_root(current_codeword);
+      current_codeword = dictionary.get_codeword(current_codeword);
+      root_stack.push(root);
+   }
+
+   // push the root at the leaf
+   root_stack.push((unsigned char)current_codeword);
+}
+
+
+// ============================================================================================
+//
+//
+//    Functions called by update()
+//
+//
+// ============================================================================================
+
+
+// This function reads the song data and executes the embedded commands.
+void Cu6mPlayer::command_loop()
+{
+    unsigned char command_byte;   // current command byte
+    int command_nibble_hi;        // command byte, bits 4-7
+    int command_nibble_lo;        // command byte, bite 0-3
+    bool repeat_loop = true;      //
+
+    do
+    {
+        // extract low and high command nibbles
+        command_byte = read_song_byte();   // implicitly increments song_pos
+        command_nibble_hi = command_byte >> 4;
+        command_nibble_lo = command_byte & 0xf;
+ 
+        switch (command_nibble_hi)
+        {
+            case 0x0: command_0(command_nibble_lo); break;
+            case 0x1: command_1(command_nibble_lo); break;
+            case 0x2: command_2(command_nibble_lo); break;
+            case 0x3: command_3(command_nibble_lo); break;
+            case 0x4: command_4(command_nibble_lo); break;
+            case 0x5: command_5(command_nibble_lo); break;
+            case 0x6: command_6(command_nibble_lo); break;
+            case 0x7: command_7(command_nibble_lo); break;
+            case 0x8:
+                switch (command_nibble_lo)
+                {
+                    case 1: command_81(); break;
+                    case 2: command_82(); repeat_loop = false; break;
+                    case 3: command_83(); break;
+                    case 5: command_85(); break;
+                    case 6: command_86(); break;
+                    default: break; // maybe generate an error?
+                }
+                break;
+            case 0xE: command_E(); break;
+            case 0xF: command_F(); break;
+            default: break; // maybe generate an error?
+        }
+
+    } while (repeat_loop);
+}
+
+
+// --------------------------------------------------------
+//    The commands supported by the U6 music file format
+// --------------------------------------------------------
+
+// ----------------------------------------
+// Set octave and frequency, note off
+// Format: 0c nn
+// c = channel, nn = packed Adlib frequency
+// ----------------------------------------
+void Cu6mPlayer::command_0(int channel)
+{
+    unsigned char freq_byte;
+    byte_pair freq_word;
+
+    freq_byte = read_song_byte();
+    freq_word = expand_freq_byte(freq_byte);
+    set_adlib_freq(channel,freq_word);
+}
+
+
+// ---------------------------------------------------
+// Set octave and frequency, old note off, new note on
+// Format: 1c nn
+// c = channel, nn = packed Adlib frequency
+// ---------------------------------------------------
+void Cu6mPlayer::command_1(int channel)
+{
+    unsigned char freq_byte;
+    byte_pair freq_word;
+
+    vb_direction_flag[channel] = 0;
+    vb_current_value[channel] = 0;
+ 
+    freq_byte = read_song_byte();
+    freq_word = expand_freq_byte(freq_byte);
+    set_adlib_freq(channel,freq_word);
+
+    freq_word.hi = freq_word.hi | 0x20; // note on
+    set_adlib_freq(channel,freq_word);
+}
+
+
+// ----------------------------------------
+// Set octave and frequency, note on
+// Format: 2c nn
+// c = channel, nn = packed Adlib frequency
+// ----------------------------------------
+void Cu6mPlayer::command_2(int channel)
+{
+    unsigned char freq_byte;
+    byte_pair freq_word;
+ 
+    freq_byte = read_song_byte();
+    freq_word = expand_freq_byte(freq_byte);
+    freq_word.hi = freq_word.hi | 0x20; // note on
+    set_adlib_freq(channel,freq_word);
+}
+
+
+// --------------------------------------
+// Set "carrier mute factor"==not(volume)
+// Format: 3c nn
+// c = channel, nn = mute factor
+// --------------------------------------
+void Cu6mPlayer::command_3(int channel)
+{
+    unsigned char mf_byte;
+
+    carrier_mf_signed_delta[channel] = 0;
+    mf_byte = read_song_byte();
+    set_carrier_mf(channel,mf_byte);
+}
+
+
+// ----------------------------------------
+// set "modulator mute factor"==not(volume)
+// Format: 4c nn
+// c = channel, nn = mute factor
+// ----------------------------------------
+void Cu6mPlayer::command_4(int channel)
+{
+    unsigned char mf_byte;
+
+    mf_byte = read_song_byte();
+    set_modulator_mf(channel,mf_byte);
+}
+
+
+// --------------------------------------------
+// Set portamento (pitch slide)
+// Format: 5c nn
+// c = channel, nn = signed channel pitch delta
+// --------------------------------------------
+void Cu6mPlayer::command_5(int channel)
+{
+    channel_freq_signed_delta[channel] = read_signed_song_byte();
+}
+
+
+// --------------------------------------------
+// Set vibrato paramters
+// Format: 6c mn
+// c = channel
+// m = vibrato double amplitude
+// n = vibrato multiplier
+// --------------------------------------------
+void Cu6mPlayer::command_6(int channel)
+{
+    unsigned char vb_parameters;
+
+    vb_parameters = read_song_byte();
+    vb_double_amplitude[channel] = vb_parameters >> 4; // high nibble
+    vb_multiplier[channel] = vb_parameters & 0xF; // low nibble
+}
+
+
+// ----------------------------------------
+// Assign Adlib instrument to Adlib channel
+// Format: 7c nn
+// c = channel, nn = instrument number
+// ----------------------------------------
+void Cu6mPlayer::command_7(int channel)
+{
+    int instrument_offset = instrument_offsets[read_song_byte()];
+    out_adlib_opcell(channel, false, 0x20, *(song_data + instrument_offset+0));
+    out_adlib_opcell(channel, false, 0x40, *(song_data + instrument_offset+1));
+    out_adlib_opcell(channel, false, 0x60, *(song_data + instrument_offset+2));
+    out_adlib_opcell(channel, false, 0x80, *(song_data + instrument_offset+3));
+    out_adlib_opcell(channel, false, 0xE0, *(song_data + instrument_offset+4));
+    out_adlib_opcell(channel, true, 0x20, *(song_data + instrument_offset+5));
+    out_adlib_opcell(channel, true, 0x40, *(song_data + instrument_offset+6));
+    out_adlib_opcell(channel, true, 0x60, *(song_data + instrument_offset+7));
+    out_adlib_opcell(channel, true, 0x80, *(song_data + instrument_offset+8));
+    out_adlib_opcell(channel, true, 0xE0, *(song_data + instrument_offset+9));
+    out_adlib(0xC0+channel, *(song_data + instrument_offset+10));
+}
+
+
+// -------------------------------------------
+// Branch to a new subsong
+// Format: 81 nn aa bb
+// nn == number of times to repeat the subsong
+// aa == subsong offset (low byte)
+// bb == subsong offset (high byte)
+// -------------------------------------------
+void Cu6mPlayer::command_81()
+{
+    subsong_info new_ss_info;
+ 
+    new_ss_info.subsong_repetitions = read_song_byte();
+    new_ss_info.subsong_start = read_song_byte(); new_ss_info.subsong_start += read_song_byte() << 8;
+    new_ss_info.continue_pos = song_pos;
+
+    subsong_stack.push(new_ss_info);
+    song_pos = new_ss_info.subsong_start;
+}
+
+
+// ------------------------------------------------------------
+// Stop interpreting commands for this timer tick
+// Format: 82 nn
+// nn == delay (in timer ticks) until further data will be read
+// ------------------------------------------------------------
+void Cu6mPlayer::command_82()
+{
+    read_delay = read_song_byte();
+}
+
+
+// -----------------------------
+// Adlib instrument data follows
+// Format: 83 nn <11 bytes>
+// nn == instrument number
+// -----------------------------
+void Cu6mPlayer::command_83()
+{
+    unsigned char instrument_number = read_song_byte();
+    instrument_offsets[instrument_number] = song_pos;
+    song_pos += 11;
+}
+
+
+// ----------------------------------------------
+// Set -1 mute factor slide (upward volume slide)
+// Format: 85 cn
+// c == channel
+// n == slide delay
+// ----------------------------------------------
+void Cu6mPlayer::command_85()
+{
+    unsigned char data_byte = read_song_byte();
+    int channel = data_byte >> 4; // high nibble
+    unsigned char slide_delay = data_byte & 0xF; // low nibble
+    carrier_mf_signed_delta[channel] = +1;
+    carrier_mf_mod_delay[channel] = slide_delay + 1;
+    carrier_mf_mod_delay_backup[channel] = slide_delay + 1;
+}
+
+
+// ------------------------------------------------
+// Set +1 mute factor slide (downward volume slide)
+// Format: 86 cn
+// c == channel
+// n == slide speed
+// ------------------------------------------------
+void Cu6mPlayer::command_86()
+{
+    unsigned char data_byte = read_song_byte();
+    int channel = data_byte >> 4; // high nibble
+    unsigned char slide_delay = data_byte & 0xF; // low nibble
+    carrier_mf_signed_delta[channel] = -1;
+    carrier_mf_mod_delay[channel] = slide_delay + 1;
+    carrier_mf_mod_delay_backup[channel] = slide_delay + 1;
+}
+
+
+// --------------
+// Set loop point
+// Format: E?
+// --------------
+void Cu6mPlayer::command_E()
+{
+    loop_position = song_pos;
+}
+
+
+// ---------------------------
+// Return from current subsong
+// Format: F?
+// ---------------------------
+void Cu6mPlayer::command_F()
+{
+    if (!subsong_stack.empty())
+    {
+        subsong_info temp = subsong_stack.top();
+        subsong_stack.pop();
+        temp.subsong_repetitions--;
+        if (temp.subsong_repetitions==0)
+        {
+            song_pos = temp.continue_pos;
+        }
+        else
+        {
+            song_pos = temp.subsong_start;
+            subsong_stack.push(temp);
+        }
+    }
+    else
+    {
+        song_pos = loop_position;
+		songend = true;
+    }
+}
+
+
+// --------------------
+// Additional functions
+// --------------------
+
+// This function decrements its argument, without allowing it to become negative.
+void Cu6mPlayer::dec_clip(int& param)
+{
+    param--;
+    if (param < 0) { param = 0; }
+}
+
+
+// Returns the byte at the current song position.
+// Side effect: increments song_pos.
+unsigned char Cu6mPlayer::read_song_byte()
+{
+    unsigned char song_byte;
+    song_byte = song_data[song_pos];
+    song_pos++;
+    return(song_byte);
+}
+
+
+// Same as read_song_byte(), except that it returns a signed byte
+signed char Cu6mPlayer::read_signed_song_byte()
+{
+    unsigned char song_byte;
+    int signed_value;
+    song_byte = *(song_data + song_pos);
+    song_pos++;
+    if (song_byte <= 127)
+    {
+        signed_value = song_byte;
+    }
+    else
+    {
+        signed_value = (int)song_byte - 0x100;
+    }
+    return((signed char)signed_value);
+}
+
+
+Cu6mPlayer::byte_pair Cu6mPlayer::expand_freq_byte(unsigned char freq_byte)
+{
+    const byte_pair freq_table[24] =
+        {
+          {0x00,0x00}, {0x58,0x01}, {0x82,0x01}, {0xB0,0x01},
+          {0xCC,0x01}, {0x03,0x02}, {0x41,0x02}, {0x86,0x02},
+          {0x00,0x00}, {0x6A,0x01}, {0x96,0x01}, {0xC7,0x01},
+          {0xE4,0x01}, {0x1E,0x02}, {0x5F,0x02}, {0xA8,0x02},
+          {0x00,0x00}, {0x47,0x01}, {0x6E,0x01}, {0x9A,0x01},
+          {0xB5,0x01}, {0xE9,0x01}, {0x24,0x02}, {0x66,0x02}
+        };
+
+    int packed_freq;
+    int octave;
+    byte_pair freq_word;
+
+    packed_freq = freq_byte & 0x1F;
+    octave = freq_byte >> 5;
+
+    // range check (not present in the original U6 music driver)
+    if (packed_freq >= 24) { packed_freq = 0; }
+
+    freq_word.hi = freq_table[packed_freq].hi + (octave << 2);
+    freq_word.lo = freq_table[packed_freq].lo;
+
+    return(freq_word);
+}
+
+
+void Cu6mPlayer::set_adlib_freq(int channel,Cu6mPlayer::byte_pair freq_word)
+{
+    out_adlib(0xA0+channel,freq_word.lo);
+    out_adlib(0xB0+channel,freq_word.hi);
+    // update the Adlib register backups
+    channel_freq[channel] = freq_word;
+}
+
+
+// this function sets the Adlib frequency, but does not update the register backups
+void Cu6mPlayer::set_adlib_freq_no_update(int channel,Cu6mPlayer::byte_pair freq_word)
+{
+    out_adlib(0xA0+channel,freq_word.lo);
+    out_adlib(0xB0+channel,freq_word.hi);
+}
+
+
+void Cu6mPlayer::set_carrier_mf(int channel,unsigned char mute_factor)
+{
+    out_adlib_opcell(channel,true,0x40,mute_factor);
+    carrier_mf[channel] = mute_factor;
+}
+
+
+void Cu6mPlayer::set_modulator_mf(int channel,unsigned char mute_factor)
+{
+    out_adlib_opcell(channel,false,0x40,mute_factor);
+}
+
+
+void Cu6mPlayer::freq_slide(int channel)
+{
+    byte_pair freq = channel_freq[channel];
+
+    long freq_word = freq.lo + (freq.hi << 8) + channel_freq_signed_delta[channel];
+    if (freq_word < 0) { freq_word += 0x10000; }
+    if (freq_word > 0xFFFF) { freq_word -= 0x10000; }
+
+    freq.lo = freq_word & 0xFF;
+    freq.hi = (freq_word >> 8) & 0xFF;
+    set_adlib_freq(channel,freq);
+}
+
+
+void Cu6mPlayer::vibrato(int channel)
+{
+    byte_pair freq;
+
+    if (vb_current_value[channel] >= vb_double_amplitude[channel])
+    { vb_direction_flag[channel] = 1; }
+    else if (vb_current_value[channel] <= 0)
+    { vb_direction_flag[channel] = 0; }
+
+    if (vb_direction_flag[channel]==0)
+    { vb_current_value[channel]++; }
+    else
+    { vb_current_value[channel]--; }
+
+    long freq_word = channel_freq[channel].lo + (channel_freq[channel].hi << 8);
+    freq_word += (vb_current_value[channel] - (vb_double_amplitude[channel] >> 1))
+                 * vb_multiplier[channel];
+    if (freq_word < 0) { freq_word += 0x10000; }
+    if (freq_word > 0xFFFF) { freq_word -= 0x10000; }
+
+    freq.lo = freq_word & 0xFF;
+    freq.hi = (freq_word >> 8) & 0xFF;
+    set_adlib_freq_no_update(channel,freq);
+}
+
+
+void Cu6mPlayer::mf_slide(int channel)
+{
+    carrier_mf_mod_delay[channel]--;
+    if (carrier_mf_mod_delay[channel]==0)
+    {
+        carrier_mf_mod_delay[channel] = carrier_mf_mod_delay_backup[channel];
+        int current_mf = carrier_mf[channel] + carrier_mf_signed_delta[channel];
+        if (current_mf > 0x3F)
+        {
+            current_mf = 0x3F;
+            carrier_mf_signed_delta[channel] = 0;
+        }
+        else if (current_mf < 0)
+            {
+                current_mf = 0;
+                carrier_mf_signed_delta[channel] = 0;
+            }
+
+        set_carrier_mf(channel,(unsigned char)current_mf);
+    }
+}
+
+
+void Cu6mPlayer::out_adlib(unsigned char adlib_register, unsigned char adlib_data)
+{
+    opl->write(adlib_register,adlib_data);
+}
+
+
+void Cu6mPlayer::out_adlib_opcell(int channel, bool carrier, unsigned char adlib_register, unsigned char out_byte)
+{
+    const unsigned char adlib_channel_to_carrier_offset[9] =
+        {0x03,0x04,0x05,0x0B,0x0C,0x0D,0x13,0x14,0x15};
+    const unsigned char adlib_channel_to_modulator_offset[9] =
+        {0x00,0x01,0x02,0x08,0x09,0x0A,0x10,0x11,0x12};
+
+    if (carrier)
+    {
+        out_adlib(adlib_register+adlib_channel_to_carrier_offset[channel],out_byte);
+    }
+    else
+    {
+        out_adlib(adlib_register+adlib_channel_to_modulator_offset[channel],out_byte);
+    }
+}
+
+
+// ============================================================================================
+//
+//
+//    The Dictionary
+//
+//
+// ============================================================================================
+
+
+Cu6mPlayer::MyDict::MyDict()
+{
+    dict_size = default_dict_size;
+    dictionary = new dict_entry[dict_size-0x100]; // don't allocate space for the roots
+    contains = 0x102;
+}
+
+
+Cu6mPlayer::MyDict::MyDict(int max_size)
+{
+    dict_size = max_size;
+    dictionary = new dict_entry[dict_size-0x100]; // don't allocate space for the roots
+    contains = 0x102;
+}
+
+
+// re-initializes the dictionary
+void Cu6mPlayer::MyDict::reset()
+{
+    contains = 0x102;
+}
+
+
+// Note: If the dictionary is already full, this function does nothing.
+void Cu6mPlayer::MyDict::add(unsigned char root, int codeword)
+{
+    if (contains < dict_size)
+    {
+        dictionary[contains-0x100].root = root;
+        dictionary[contains-0x100].codeword = codeword;
+        contains++;
+    }
+}
+
+
+unsigned char Cu6mPlayer::MyDict::get_root(int codeword)
+{
+    return (dictionary[codeword-0x100].root);
+}
+
+
+int Cu6mPlayer::MyDict::get_codeword(int codeword)
+{
+    return (dictionary[codeword-0x100].codeword);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/u6m.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,168 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * u6m.h - Ultima 6 Music Player by Marc Winterrowd.
+ * This code extends the Adlib Winamp plug-in by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include <stack>
+
+#include "player.h"
+
+#define default_dict_size 4096     // because maximum codeword size == 12 bits
+#define max_codeword_length 12     // maximum codeword length in bits
+
+class Cu6mPlayer: public CPlayer
+{
+    public:
+  static CPlayer *factory(Copl *newopl);
+
+        Cu6mPlayer(Copl *newopl) : CPlayer(newopl), song_data(0)
+    {
+    };
+
+
+	~Cu6mPlayer()
+    {
+        if(song_data) delete[] song_data;
+    };
+
+	bool load(const std::string &filename, const CFileProvider &fp);
+	bool update();
+	void rewind(int subsong);
+	float getrefresh();
+
+	std::string gettype()
+    {
+        return std::string("Ultima 6 Music");
+    };
+
+
+    protected:
+
+    struct byte_pair
+	{
+        unsigned char lo;
+        unsigned char hi;
+	};
+
+	struct subsong_info   // information about a subsong
+	{
+	    int continue_pos;
+		int subsong_repetitions;
+	    int subsong_start;
+	};
+
+	struct dict_entry   // dictionary entry
+	{
+	    unsigned char root;
+		int codeword;
+	};
+
+	struct data_block   // 
+	{
+	    long size;
+	    unsigned char *data;
+	};
+
+    class MyDict
+    {
+        private:
+        // The actual number of dictionary entries allocated
+	    // is (dictionary_size-256), because there are 256 roots
+		// that do not need to be stored.
+        int contains; // number of entries currently in the dictionary
+        int dict_size; // max number of entries that will fit into the dictionary
+		dict_entry* dictionary;
+
+        public:
+        MyDict(); // use dictionary size of 4096
+        MyDict(int); // let the caller specify a dictionary size
+        void reset(); // re-initializes the dictionary
+        void add(unsigned char, int);
+        unsigned char get_root(int);
+        int get_codeword(int);
+    };
+
+
+    // class variables
+    long played_ticks;
+
+    unsigned char* song_data;   // the uncompressed .m file (the "song")
+    bool driver_active;         // flag to prevent reentrancy
+	bool songend;				// indicates song end
+    int song_pos;               // current offset within the song
+    int loop_position;          // position of the loop point
+    int read_delay;             // delay (in timer ticks) before further song data is read
+	std::stack<subsong_info> subsong_stack;
+
+    int instrument_offsets[9];  // offsets of the adlib instrument data
+    // vibrato ("vb")
+    unsigned char vb_current_value[9];
+    unsigned char vb_double_amplitude[9];
+    unsigned char vb_multiplier[9];
+    unsigned char vb_direction_flag[9];
+    // mute factor ("mf") = not(volume)
+    unsigned char carrier_mf[9];
+    signed char carrier_mf_signed_delta[9];
+    unsigned char carrier_mf_mod_delay_backup[9];
+    unsigned char carrier_mf_mod_delay[9];
+    // frequency
+	byte_pair channel_freq[9];  // adlib freq settings for each channel
+    signed char channel_freq_signed_delta[9];
+
+    // protected functions used by update()
+    void command_loop();
+    unsigned char read_song_byte();
+    signed char read_signed_song_byte();
+    void dec_clip(int&);
+    byte_pair expand_freq_byte(unsigned char);
+    void set_adlib_freq(int channel,byte_pair freq_word);
+    void set_adlib_freq_no_update(int channel,byte_pair freq_word);
+    void set_carrier_mf(int channel,unsigned char mute_factor);
+    void set_modulator_mf(int channel,unsigned char mute_factor);
+    void freq_slide(int channel);
+    void vibrato(int channel);
+    void mf_slide(int channel);
+
+    void command_0(int channel);
+    void command_1(int channel);
+    void command_2(int channel);
+    void command_3(int channel);
+    void command_4(int channel);
+    void command_5(int channel);
+    void command_6(int channel);
+    void command_7(int channel);
+    void command_81();
+    void command_82();
+    void command_83();
+    void command_85();
+    void command_86();
+    void command_E();
+    void command_F();
+
+    void out_adlib(unsigned char adlib_register, unsigned char adlib_data);
+    void out_adlib_opcell(int channel, bool carrier, unsigned char adlib_register, unsigned char out_byte);
+
+    // protected functions used by load()
+    bool lzw_decompress(data_block source, data_block dest);
+    int get_next_codeword (long& bits_read, unsigned char *source, int codeword_size);
+    void output_root(unsigned char root, unsigned char *destination, long& position);
+    void get_string(int codeword, MyDict& dictionary, std::stack<unsigned char>& root_stack);
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/xad.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,140 @@
+/*
+  Adplug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  xad.cpp - XAD shell player by Riven the Mage <riven@ok.ru>
+*/
+
+#include "xad.h"
+#include "debug.h"
+
+/* -------- Public Methods -------------------------------- */
+
+CxadPlayer::CxadPlayer(Copl * newopl) : CPlayer(newopl)
+{
+  tune = 0;
+}
+
+CxadPlayer::~CxadPlayer()
+{
+  if (tune)
+    delete [] tune;
+}
+
+bool CxadPlayer::load(const std::string &filename, const CFileProvider &fp)
+{
+  binistream *f = fp.open(filename); if(!f) return false;
+  bool ret = false;
+
+  // load header
+  xad.id = f->readInt(4);
+  f->readString(xad.title, 36);
+  f->readString(xad.author, 36);
+  xad.fmt = f->readInt(2);
+  xad.speed = f->readInt(1);
+  xad.reserved_a = f->readInt(1);
+
+  // 'XAD!' - signed ?
+  if(xad.id != 0x21444158) { fp.close(f); return false; }
+
+  // get file size
+  tune_size = fp.filesize(f) - 80;
+
+  // load()
+  tune = new unsigned char [tune_size];
+  f->readString((char *)tune, tune_size);
+  fp.close(f);
+
+  ret = xadplayer_load();
+
+  if (ret)
+    rewind(0);
+
+  return ret;
+}
+
+void CxadPlayer::rewind(int subsong)
+{
+  opl->init();
+
+  plr.speed = xad.speed;
+  plr.speed_counter = 1;
+  plr.playing = 1;
+  plr.looping = 0;
+
+  // rewind()
+  xadplayer_rewind(subsong);
+
+#ifdef DEBUG
+  AdPlug_LogWrite("-----------\n");
+#endif
+}
+
+bool CxadPlayer::update()
+{
+  if (--plr.speed_counter)
+    goto update_end;
+
+  plr.speed_counter = plr.speed;
+
+  // update()
+  xadplayer_update();
+
+update_end:
+  return (plr.playing && (!plr.looping));
+}
+
+float CxadPlayer::getrefresh()
+{
+  return xadplayer_getrefresh();
+}
+
+std::string CxadPlayer::gettype()
+{
+  return xadplayer_gettype();
+}
+
+std::string CxadPlayer::gettitle()
+{
+  return xadplayer_gettitle();
+}
+
+std::string CxadPlayer::getauthor()
+{
+  return xadplayer_getauthor();
+}
+
+std::string CxadPlayer::getinstrument(unsigned int i)
+{
+  return xadplayer_getinstrument(i);
+}
+
+unsigned int CxadPlayer::getinstruments()
+{
+  return xadplayer_getinstruments();
+}
+
+/* -------- Protected Methods ------------------------------- */
+
+void CxadPlayer::opl_write(int reg, int val)
+{
+  adlib[reg] = val;
+#ifdef DEBUG
+  AdPlug_LogWrite("[ %02X ] = %02X\n",reg,val);
+#endif
+  opl->write(reg,val);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/xad.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,97 @@
+/*
+  AdPlug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2003 Simon Peter <dn.tlp@gmx.net>, et al.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  xad.h - XAD shell player by Riven the Mage <riven@ok.ru>
+*/
+
+#ifndef H_ADPLUG_XAD
+#define H_ADPLUG_XAD
+
+#include "player.h"
+
+class CxadPlayer: public CPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl);
+
+        CxadPlayer(Copl * newopl);
+        ~CxadPlayer();
+
+        bool	load(const std::string &filename, const CFileProvider &fp);
+        bool	update();
+        void	rewind(int subsong);
+        float	getrefresh();
+
+        std::string     gettype();
+        std::string     gettitle();
+        std::string     getauthor();
+        std::string     getinstrument(unsigned int i);
+        unsigned int    getinstruments();
+
+protected:
+	virtual void xadplayer_rewind(int subsong) = 0;
+	virtual bool xadplayer_load() = 0;
+	virtual void xadplayer_update() = 0;
+	virtual float xadplayer_getrefresh() = 0;
+	virtual std::string xadplayer_gettype() = 0;
+	virtual std::string xadplayer_gettitle()
+	  {
+	    return std::string(xad.title);
+	  }
+	virtual std::string xadplayer_getauthor()
+	  {
+	    return std::string(xad.author);
+	  }
+	virtual std::string xadplayer_getinstrument(unsigned int i)
+	  {
+	    return std::string("");
+	  }
+	virtual unsigned int xadplayer_getinstruments()
+	  {
+	    return 0;
+	  }
+
+	enum { HYP=1, PSI, FLASH, BMF, RAT, HYBRID };
+
+        struct xad_header
+        {
+	    unsigned long   id;
+            char            title[36];
+            char            author[36];
+            unsigned short  fmt;
+            unsigned char   speed;
+            unsigned char   reserved_a;
+        } xad;
+
+        unsigned char * tune;
+        unsigned long   tune_size;
+
+        struct
+        {
+            int             playing;
+            int             looping;
+            unsigned char   speed;
+            unsigned char   speed_counter;
+        } plr;
+
+        unsigned char   adlib[256];
+
+        void opl_write(int reg, int val);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/xsm.cpp	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,117 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * xsm.cpp - eXtra Simple Music Player, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include <string.h>
+
+#include "xsm.h"
+
+CxsmPlayer::CxsmPlayer(Copl *newopl)
+  : CPlayer(newopl), music(0)
+{
+}
+
+CxsmPlayer::~CxsmPlayer()
+{
+  if(music) delete [] music;
+}
+
+bool CxsmPlayer::load(const std::string &filename, const CFileProvider &fp)
+{
+  binistream *f = fp.open(filename); if(!f) return false;
+  char			id[6];
+  int			i, j;
+
+  // check if header matches
+  f->readString(id, 6); songlen = f->readInt(2);
+  if(strncmp(id, "ofTAZ!", 6) || songlen > 3200) { fp.close(f); return false; }
+
+  // read and set instruments
+  for(i = 0; i < 9; i++) {
+    opl->write(0x20 + op_table[i], f->readInt(1));
+    opl->write(0x23 + op_table[i], f->readInt(1));
+    opl->write(0x40 + op_table[i], f->readInt(1));
+    opl->write(0x43 + op_table[i], f->readInt(1));
+    opl->write(0x60 + op_table[i], f->readInt(1));
+    opl->write(0x63 + op_table[i], f->readInt(1));
+    opl->write(0x80 + op_table[i], f->readInt(1));
+    opl->write(0x83 + op_table[i], f->readInt(1));
+    opl->write(0xe0 + op_table[i], f->readInt(1));
+    opl->write(0xe3 + op_table[i], f->readInt(1));
+    opl->write(0xc0 + op_table[i], f->readInt(1));
+    f->ignore(5);
+  }
+
+  // read song data
+  music = new char [songlen * 9];
+  for(i = 0; i < 9; i++)
+    for(j = 0; j < songlen; j++)
+      music[j * 9 + i] = f->readInt(1);
+
+  // success
+  fp.close(f);
+  rewind(0);
+  return true;
+}
+
+bool CxsmPlayer::update()
+{
+  int c;
+
+  if(notenum >= songlen) {
+    songend = true;
+    notenum = last = 0;
+  }
+
+  for(c = 0; c < 9; c++)
+    if(music[notenum * 9 + c] != music[last * 9 + c])
+      opl->write(0xb0 + c, 0);
+
+  for(c = 0; c < 9; c++) {
+    if(music[notenum * 9 + c])
+      play_note(c, music[notenum * 9 + c] % 12, music[notenum * 9 + c] / 12);
+    else
+      play_note(c, 0, 0);
+  }
+
+  last = notenum;
+  notenum++;
+  return !songend;
+}
+
+void CxsmPlayer::rewind(int subsong)
+{
+  notenum = last = 0;
+  songend = false;
+}
+
+float CxsmPlayer::getrefresh()
+{
+  return 5.0f;
+}
+
+void CxsmPlayer::play_note(int c, int note, int octv)
+{
+  int freq = note_table[note];
+
+  if(!note && !octv) freq = 0;
+  opl->write(0xa0 + c, freq & 0xff);
+  opl->write(0xb0 + c, (freq / 0xff) | 32 | (octv * 4));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/adplug/core/xsm.h	Fri Dec 30 16:31:39 2005 -0800
@@ -0,0 +1,46 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * xsm.h - eXtra Simple Music Player, by Simon Peter <dn.tlp@gmx.net>
+ */
+
+#include "player.h"
+
+class CxsmPlayer: public CPlayer
+{
+public:
+  static CPlayer *factory(Copl *newopl) { return new CxsmPlayer(newopl); }
+
+  CxsmPlayer(Copl *newopl);
+  ~CxsmPlayer();
+
+  bool load(const std::string &filename, const CFileProvider &fp);
+  bool update();
+  void rewind(int subsong);
+  float getrefresh();
+
+  std::string gettype() { return std::string("eXtra Simple Music"); }
+
+private:
+  unsigned short	songlen;
+  char			*music;
+  unsigned int		last, notenum;
+  bool			songend;
+
+  void play_note(int c, int note, int octv);
+};
--- a/configure.ac	Fri Dec 30 14:17:35 2005 -0800
+++ b/configure.ac	Fri Dec 30 16:31:39 2005 -0800
@@ -326,6 +326,22 @@
 fi
 AM_CONDITIONAL([HAVE_LIRC], test "$have_lirc" = "yes")
 
+dnl *** AdPlug requirement (libbinio) _ZN8binfbase3posEv
+
+AC_ARG_ENABLE(adplug,
+    [  --disable-adplug        disable AdPlug plugin (default=enabled)],
+    [enable_adplug=$enableval],
+    [enable_adplug="yes"]
+)
+
+if test "$enable_lirc" = "yes"; then
+    AC_CHECK_LIB([binio],[_ZN8binfbase3posEv],[have_adplug=yes],[have_adplug=no])
+else
+    AC_MSG_RESULT([*** AdPlug plugin disabled per user request ***])
+    have_adplug="no"
+fi
+AM_CONDITIONAL([HAVE_ADPLUG], test "$have_lirc" = "yes")
+
 dnl *** Ogg Vorbis
 
 AC_ARG_ENABLE(vorbis,
@@ -804,6 +820,8 @@
 	Plugins/Input/timidity/libtimidity/Makefile
 	Plugins/Input/timidity/src/Makefile
 	Plugins/Input/sexypsf/Makefile
+	Plugins/Input/adplug/Makefile
+	Plugins/Input/adplug/core/Makefile
         Plugins/Visualization/Makefile
         Plugins/Visualization/blur_scope/Makefile
 	Plugins/Visualization/libvisual-proxy/Makefile
@@ -871,6 +889,7 @@
 echo "  Commodore 64 audio (sid):               $have_sidplay"
 echo "  Game music (spc, nsf & gbs):            yes"
 echo "  PlayStation audio (sexypsf):            yes"
+echo "  AdLib synthesizer (adplug):             $have_adplug"
 echo
 echo "  General"
 echo "  -------"