[packages/xmp] - updated to 4.1.0 - removed outdated nondfsg patch (no longer applicable, no fmopl in sources) - ar

qboosh qboosh at pld-linux.org
Mon May 22 21:37:04 CEST 2017


commit 60f1a56f47df0e76e28f5d38f8191c8411922c5d
Author: Jakub Bogusz <qboosh at pld-linux.org>
Date:   Mon May 22 21:37:55 2017 +0200

    - updated to 4.1.0
    - removed outdated nondfsg patch (no longer applicable, no fmopl in sources)
    - arts,esd,nas outputs are gone
    - xmms plugin is gone (last version i.e. 3.5.0 saved in xmms-input-xmp.spec)

 xmp-fix-shared.patch |  111 --
 xmp-gcc33.patch      |   54 -
 xmp-load-fix.patch   |   27 -
 xmp-nondfsg.patch    | 3409 --------------------------------------------------
 xmp.spec             |   85 +-
 5 files changed, 24 insertions(+), 3662 deletions(-)
---
diff --git a/xmp.spec b/xmp.spec
index 1ecb2d3..609b923 100644
--- a/xmp.spec
+++ b/xmp.spec
@@ -1,35 +1,24 @@
-# TODO: bmp, audacious plugins
 #
 # Conditional build:
-%bcond_with	arts		# aRts audio driver
-%bcond_with	esd		# EsounD audio output driver
-%bcond_without	nas		# NAS audio output driver
 %bcond_without	pulseaudio	# PulseAudio audio output driver
-%bcond_without	xmms		# XMP as XMMS plugin
-%bcond_with	nonfree		# with recent fmopl (GPL-incompatible - non-distributable)
 #
 Summary:	Extended Module Player
-Summary(pl.UTF-8):	Rozszerzony odtwarzacz modułów
+Summary(pl.UTF-8):	Extended Module Player - rozszerzony odtwarzacz modułów
 Name:		xmp
-Version:	3.4.1
+Version:	4.1.0
 Release:	1
-License:	GPL%{?with_nonfree: with non-commercial additions}
+License:	GPL v2+
 Group:		Applications/Sound
 Source0:	http://downloads.sourceforge.net/xmp/%{name}-%{version}.tar.gz
-# Source0-md5:	cae0d0879b51f36a1056196522c899b1
-Patch0:		%{name}-nondfsg.patch
+# Source0-md5:	d9661b0be1a7ec79fd6185b166c4e9dd
 URL:		http://xmp.sourceforge.net/
-%{?with_arts:BuildRequires:	arts-devel}
-BuildRequires:	autoconf
+BuildRequires:	alsa-lib-devel
+BuildRequires:	autoconf >= 2.50
 BuildRequires:	automake
-%{?with_esd:BuildRequires:	esound-devel}
-%{?with_nas:BuildRequires:	nas-devel}
+BuildRequires:	libxmp-devel >= 4.4
 BuildRequires:	pkgconfig
 %{?with_pulseaudio:BuildRequires:	pulseaudio-devel}
-%{?with_xmms:BuildRequires:	rpmbuild(macros) >= 1.125}
-%{?with_xmms:BuildRequires:	xmms-devel}
-BuildRequires:	xorg-lib-libX11-devel
-BuildRequires:	xorg-lib-libXt-devel
+Requires:	libxmp >= 4.4
 Obsoletes:	xmp-X11
 Obsoletes:	xmp-output-arts
 Obsoletes:	xmp-output-esd
@@ -37,51 +26,31 @@ Obsoletes:	xmp-output-nas
 BuildRoot:	%{tmpdir}/%{name}-%{version}-root-%(id -u -n)
 
 %description
-xmp is a multi-format module player for UNIX. In machines with GUS or
-AWE cards xmp takes advantage of the OSS sequencer to play modules
-with virtually no system load. Using software mixing, xmp plays at
-sampling rates up to 48kHz in mono or stereo, 8 or 16 bits, signed or
-unsigned, little or big endian samples with 32 bit linear
-interpolation.
+This is the Extended Module Player, a portable module player that
+plays over 90 mainstream and obscure module formats, including
+Protracker MOD, Fasttracker II XM, Scream Tracker 3 S3M and Impulse
+Tracker IT files.
 
 %description -l pl.UTF-8
-xmp jest odtwarzaczem modułów w wielu formatach. Potrafi obsłużyć
-karty GUS i AWE, korzystając z sekwencera OSS, aby nie obciążać
-systemu. Używając programowego miksowania, może odgrywać z
-częstotliwością próbkowania do 48kHz mono lub stereo, 8 lub 16 bitów,
-próbki ze znakiem lub bez, little- lub big-endian z 32-bitową
-interpolacją.
-
-%package -n xmms-input-xmp
-Summary:	XMMS plugin that uses XMP library to play music modules
-Summary(pl.UTF-8):	Wtyczka dla XMMS-a odtwarzająca moduły dźwiękowe z użyciem XMP
-Group:		X11/Applications/Sound
-Requires:	%{name} = %{version}-%{release}
-Requires:	xmms
-
-%description -n xmms-input-xmp
-XMMS plugin that uses XMP library to play music modules.
-
-%description -n xmms-input-xmp -l pl.UTF-8
-Wtyczka dla XMMS-a odtwarzająca moduły dźwiękowe z użyciem biblioteki
-XMP.
+XMP (Extended Module Player - rozszerzony odtwarzacz modułów) to
+przenośny odtwarzacz modułów muzycznych, znający ponad 90 głównych i
+mniej znanych formatów, w tym: Protracker (MOD), Scream Tracker 3
+(S3M), Fast Tracker II (XM) oraz Impulse Tracker (IT).
 
 %prep
 %setup -q
-%{?with_nonfree:%patch0 -p1}
 
 %build
-cp -f /usr/share/automake/config.* scripts
 %{__aclocal}
 %{__autoconf}
+%{__automake}
 %configure \
-	%{?with_arts:--enable-arts} \
-	%{?with_esd:--enable-esd} \
-	%{?with_nas:--enable-nas} \
-	%{?with_pulseaudio:--enable-pulseaudio} \
-	%{?with_xmms:--enable-xmms-plugin}
-%{__make} -j1 \
-	V=1
+	%{!?with_pulseaudio:--disable-pulseaudio} \
+	--disable-silent-rules
+
+%{__make}
+# -j1 \
+#	V=1
 
 %install
 rm -rf $RPM_BUILD_ROOT
@@ -98,15 +67,9 @@ rm -rf $RPM_BUILD_ROOT
 
 %files
 %defattr(644,root,root,755)
-%doc README docs/{CREDITS,ChangeLog,README.{awebug,fixloop,trackers,unsqsh},formats}
+%doc CREDITS Changelog README
 %dir %{_sysconfdir}/xmp
 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/xmp/modules.conf
 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/xmp/xmp.conf
 %attr(755,root,root) %{_bindir}/xmp
 %{_mandir}/man1/xmp.1*
-
-%if %{with xmms}
-%files -n xmms-input-xmp
-%defattr(644,root,root,755)
-%attr(755,root,root) %{xmms_input_plugindir}/xmp-xmms.so
-%endif
diff --git a/xmp-fix-shared.patch b/xmp-fix-shared.patch
deleted file mode 100644
index 2cafaa1..0000000
--- a/xmp-fix-shared.patch
+++ /dev/null
@@ -1,111 +0,0 @@
---- xmp-2.0.5-pre3/lib/Makefile.orig	2001-02-18 04:56:08.000000000 +0100
-+++ xmp-2.0.5-pre3/lib/Makefile	2003-07-23 21:34:04.000000000 +0200
-@@ -23,8 +23,8 @@
- install::
- ifdef DYNDRV
- 	[ -d $(LIB_DIR)/xmp/drivers ] || mkdir -p $(LIB_DIR)/xmp/drivers
--	$(INSTALL) -m644 $(MYSHLIB).$(VERSION) $(LIB_DIR)/xmp
--	$(INSTALL) -m644 drivers/*.so $(LIB_DIR)/xmp/drivers
-+	$(INSTALL) -m755 $(MYSHLIB).$(VERSION) $(LIB_DIR)
-+	$(INSTALL) -m755 drivers/*.so $(LIB_DIR)/xmp/drivers
- endif
- 
- shared: $(MYSHLIB).$(VERSION)
-@@ -32,7 +32,7 @@
- $(MYSHLIB).$(VERSION): $(MYLIB)
- 	rm -f $(MYSHLIB)* *.o
- 	$(AR) xv $(MYLIB)
--	ld -shared -o $(MYSHLIB).$(VERSION) *.o
-+	$(LD) -shared -o $(MYSHLIB).$(VERSION) *.o -Wl,-soname=$(MYSHLIB).$(VERSION)
- 	rm -f *.o
- 	ln -s $(MYSHLIB).$(VERSION) $(MYSHLIB)
- 	
-@@ -40,6 +40,5 @@
- 	@echo Installing libraries in $(LIB_DIR)...
- 	@[ -d $(LIB_DIR) ] || mkdir -p $(LIB_DIR)
- 	$(INSTALL) -m755 $(MYLIB) $(LIB_DIR)
--	$(STRIP) -g $(LIB_DIR)/$(MYLIB)
- 
- 
---- xmp-2.0.5-pre3/src/drivers/Makefile.orig	2001-02-24 20:32:38.000000000 +0100
-+++ xmp-2.0.5-pre3/src/drivers/Makefile	2003-07-23 21:36:13.000000000 +0200
-@@ -1,7 +1,7 @@
- # Extended Module Player src/drivers/Makefile
- # $Id$
- 
--XCFLAGS	= -I../include
-+XCFLAGS	= -I../include -fPIC
- OBJS	= file.o
- DRV	= file.c oss_mix.c hpux.c bsd.c solaris.c oss_seq.c alsa_mix.c esd.c \
- 	  sgi.c os2_dart.c netbsd.c openbsd.c aix.c nas.c arts.c qnx.c win32.c
-@@ -30,13 +30,13 @@
- 	$(CC) $(CFLAGS) $(XCFLAGS) `artsc-config --cflags` -o $@ arts.c
- 
- arts.so: arts.o
--	ld -shared -o $@ $+ -lartsc
-+	ld -shared -o $@ $+ -lartsc -lc
- 
- esd.so: esd.o
--	ld -shared -o $@ $+ -lesd
-+	ld -shared -o $@ $+ -lesd -lc
- 	
- nas.so: nas.o
--	ld -shared -o $@ $+ -laudio $(X_LIB) -lXt -lX11
-+	ld -shared -o $@ $+ -laudio $(X_LIB) -lXt -lX11 -lc
- 	
- include depend
- 
---- xmp-2.0.5-pre3/src/loaders/Makefile.orig	2001-02-26 01:11:49.000000000 +0100
-+++ xmp-2.0.5-pre3/src/loaders/Makefile	2003-07-23 21:37:10.000000000 +0200
-@@ -1,7 +1,7 @@
- # Extended Module Player src/loaders/Makefile
- # $Id$
- 
--XCFLAGS	= -I../include -Iinclude
-+XCFLAGS	= -I../include -Iinclude -fPIC
- LOADERS	= xm_load.o mod_load.o s3m_load.o stm_load.o 669_load.o far_load.o \
- 	  mtm_load.o ptm_load.o okt_load.o alm_load.o amd_load.o rad_load.o \
- 	  ult_load.o pru1_load.o pru2_load.o kris_load.o ac1d_load.o \
---- xmp-2.0.5-pre3/src/player/Makefile.orig	2001-01-21 19:38:51.000000000 +0100
-+++ xmp-2.0.5-pre3/src/player/Makefile	2003-07-23 21:40:21.000000000 +0200
-@@ -1,7 +1,7 @@
- # Extended Module Player src/player/Makefile
- # $Id$
- 
--XCFLAGS	= -I../include -DLIBDIR='"$(LIB_DIR)"'
-+XCFLAGS	= -I../include -DLIBDIR='"$(LIB_DIR)"' -fPIC
- OBJS	= convert.o driver.o formats.o misc.o period.o player.o \
- 	  readrc.o scan.o ulaw.o med_synth.o cruncher.o filter.o \
- 	  fmopl.o synth.o
---- xmp-2.0.5-pre3/src/misc/Makefile.orig	2001-01-02 23:49:25.000000000 +0100
-+++ xmp-2.0.5-pre3/src/misc/Makefile	2003-07-23 21:37:45.000000000 +0200
-@@ -1,6 +1,6 @@
- # Extended Module Player src/misc/Makefile
- 
--XCFLAGS	= -I../include
-+XCFLAGS	= -I../include -fPIC
- OBJS	= control.o info.o ipc.o load.o depack.o unsqsh.o crc32.o mmcmp.o
- XDEPS	=
- XLIBS	= -L../../lib -lxmp
---- xmp-2.0.5-pre3/src/xmms/Makefile.orig	2001-01-29 00:19:21.000000000 +0100
-+++ xmp-2.0.5-pre3/src/xmms/Makefile	2003-07-23 21:35:57.000000000 +0200
-@@ -1,7 +1,7 @@
- # Extended Module Player src/xmms/Makefile
- # $Id$
- 
--XCFLAGS	= -I../include -I../main -DVERSION=\"$(VERSION)\" `xmms-config --cflags` -DXMMS_PLUGIN -D_REENTRANT #-DDEBUG
-+XCFLAGS	= -I../include -I../main -DVERSION=\"$(VERSION)\" `xmms-config --cflags` -DXMMS_PLUGIN -D_REENTRANT -fPIC #-DDEBUG
- DFILES	= Makefile README xmp-plugin.h $(OBJS:.o=.c)
- CFILES	= xmp-plugin.so
- INSTDIR	= $(DEST_DIR)`xmms-config --input-plugin-dir`
---- xmp-2.0.5-pre3/Makefile.rules.in.orig	2001-02-26 01:39:23.000000000 +0100
-+++ xmp-2.0.5-pre3/Makefile.rules.in	2003-07-23 21:35:05.000000000 +0200
-@@ -48,7 +48,7 @@
- 	$(CC) $(CFLAGS) -o $*.o $<
- 
- .o.so:
--	ld -shared -o $*.so $<
-+	ld -shared -o $*.so $< -lc
- 
- dummy:
- 
diff --git a/xmp-gcc33.patch b/xmp-gcc33.patch
deleted file mode 100644
index 2e80a23..0000000
--- a/xmp-gcc33.patch
+++ /dev/null
@@ -1,54 +0,0 @@
---- xmp-2.0.5-pre3/src/loaders/it_load.c.orig	2000-12-29 19:08:28.000000000 +0100
-+++ xmp-2.0.5-pre3/src/loaders/it_load.c	2003-07-22 21:17:01.000000000 +0200
-@@ -327,14 +327,14 @@
- 
- #define BUILD_ENV(X) { \
- 	    fread (&env, 1, sizeof (env), f); \
--	    xxih[i].##X##ei.flg = env.flg & IT_ENV_ON ? XXM_ENV_ON : 0; \
--	    xxih[i].##X##ei.flg |= env.flg & IT_ENV_LOOP ? XXM_ENV_LOOP : 0; \
--	    xxih[i].##X##ei.flg |= env.flg & IT_ENV_SLOOP ? XXM_ENV_SUS : 0; \
--	    xxih[i].##X##ei.npt = env.num; \
--	    xxih[i].##X##ei.sus = env.slb; \
--	    xxih[i].##X##ei.sue = env.sle; \
--	    xxih[i].##X##ei.lps = env.lpb; \
--	    xxih[i].##X##ei.lpe = env.lpe; \
-+	    xxih[i].X##ei.flg = env.flg & IT_ENV_ON ? XXM_ENV_ON : 0; \
-+	    xxih[i].X##ei.flg |= env.flg & IT_ENV_LOOP ? XXM_ENV_LOOP : 0; \
-+	    xxih[i].X##ei.flg |= env.flg & IT_ENV_SLOOP ? XXM_ENV_SUS : 0; \
-+	    xxih[i].X##ei.npt = env.num; \
-+	    xxih[i].X##ei.sus = env.slb; \
-+	    xxih[i].X##ei.sue = env.sle; \
-+	    xxih[i].X##ei.lps = env.lpb; \
-+	    xxih[i].X##ei.lpe = env.lpe; \
- 	    if (env.num) xx##X##e[i] = calloc (4, env.num); \
- 	    for (j = 0; j < env.num; j++) { \
- 		L_ENDIAN16 (env.node[j].x); \
---- xmp-2.0.5-pre3/src/xmms/plugin.c.orig	2001-02-04 01:47:38.000000000 +0100
-+++ xmp-2.0.5-pre3/src/xmms/plugin.c	2003-07-22 21:18:31.000000000 +0200
-@@ -284,7 +284,7 @@
- 	xmp_cfg.filter = TRUE;
- 	xmp_cfg.pan_amplitude = 80;
- 
--#define CFGREADINT(x) xmms_cfg_read_int (cfg, "XMP", #x, &xmp_cfg.##x)
-+#define CFGREADINT(x) xmms_cfg_read_int (cfg, "XMP", #x, &xmp_cfg.x)
- 
- 	filename = g_strconcat(g_get_home_dir(), "/.xmms/config", NULL);
- 	if ((cfg = xmms_cfg_open_file(filename))) {
-@@ -673,7 +673,7 @@
- 	gtk_object_set_data(GTK_OBJECT(xmp_conf_window), #w, w);	\
- 	gtk_widget_show(w);						\
- 	gtk_box_pack_start(GTK_BOX(vbox6), w, TRUE, TRUE, 0);		\
--	if (xmp_cfg.##o == 1)						\
-+	if (xmp_cfg.o == 1)						\
- 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), TRUE); \
- }
- 
-@@ -773,7 +773,7 @@
- 	if (!cfg)
- 		cfg = xmms_cfg_new();
- 
--#define CFGWRITEINT(x) xmms_cfg_write_int (cfg, "XMP", #x, xmp_cfg.##x)
-+#define CFGWRITEINT(x) xmms_cfg_write_int (cfg, "XMP", #x, xmp_cfg.x)
- 
- 	CFGWRITEINT (mixing_freq);
- 	CFGWRITEINT (force8bit);
diff --git a/xmp-load-fix.patch b/xmp-load-fix.patch
deleted file mode 100644
index e265367..0000000
--- a/xmp-load-fix.patch
+++ /dev/null
@@ -1,27 +0,0 @@
---- xmp-2.0.5-pre3/src/player/driver.c.orig	2001-02-24 20:32:41.000000000 +0100
-+++ xmp-2.0.5-pre3/src/player/driver.c	2003-07-23 22:22:18.000000000 +0200
-@@ -140,7 +140,7 @@
-     char buf[256];
- 
-     n = scandir (p, &file, select_file, alphasort);
--    if (!n)
-+    if (n <= 0)
- 	return -1;
- 
-     for (i = 0; i < n; i++) {
-@@ -213,11 +213,12 @@
- 
- #else
- {
--    char *p = malloc (MAXPATHLEN);
-+    char *p = malloc (MAXPATHLEN), *ep = getenv ("XMP_LIB_PATH");
- 
--    snprintf (p, MAXPATHLEN, "%s/drivers/", getenv ("XMP_LIB_PATH"));
-+    if (ep != NULL)
-+    snprintf (p, MAXPATHLEN, "%s/drivers/", ep);
- 
--    if (load_drivers (p) < 0)
-+    if ((ep == NULL) || (load_drivers (p) < 0))
-         load_drivers (DYNDRV_PREFIX "/drivers/");
- 
-     free (p);
diff --git a/xmp-nondfsg.patch b/xmp-nondfsg.patch
deleted file mode 100644
index 06dc180..0000000
--- a/xmp-nondfsg.patch
+++ /dev/null
@@ -1,3409 +0,0 @@
-diff --git a/src/player/fmopl.c b/src/player/fmopl.c
-index 607bf9f..c573ffa 100644
---- a/src/player/fmopl.c
-+++ b/src/player/fmopl.c
-@@ -1,17 +1,52 @@
- /*
- **
--** File: fmopl.c -- software implementation of FM sound generator
-+** File: fmopl.c - software implementation of FM sound generator
-+**                                            types OPL and OPL2
- **
--** Copyright (C) 1999 Tatsuyuki Satoh , MultiArcadeMachineEmurator development
-+** Copyright (C) 1999,2000 Tatsuyuki Satoh , MultiArcadeMachineEmulator development
-+** Copyright (C) 2002 Jarek Burczynski
- **
--** Version 0.36f
-+** Version 0.60
- **
--*/
- 
--/*
--	preliminary :
--	Problem :
--	note:
-+Revision History:
-+
-+04-28-2002 Jarek Burczynski:
-+ - binary exact Envelope Generator (verified on real YM3812);
-+   compared to YM2151: the EG clock is equal to internal_clock,
-+   rates are 2 times slower and volume resolution is one bit less
-+ - modified interface functions (they no longer return pointer -
-+   that's internal to the emulator now):
-+    - new wrapper functions for OPLCreate: YM3526Init(), YM3812Init() and Y8950Init()
-+ - corrected 'off by one' error in feedback calculations (when feedback is off)
-+ - enabled waveform usage (credit goes to Vlad Romascanu and zazzal22)
-+ - speeded up noise generator calculations (Nicola Salmoria)
-+
-+03-24-2002 Jarek Burczynski (thanks to Dox for the YM3812 chip)
-+ Complete rewrite (all verified on real YM3812):
-+ - corrected sin_tab and tl_tab data
-+ - corrected operator output calculations
-+ - corrected waveform_select_enable register;
-+   simply: ignore all writes to waveform_select register when
-+   waveform_select_enable == 0 and do not change the waveform previously selected.
-+ - corrected KSR handling
-+ - corrected Envelope Generator: attack shape, Sustain mode and
-+   Percussive/Non-percussive modes handling
-+ - Envelope Generator rates are two times slower now
-+ - LFO amplitude (tremolo) and phase modulation (vibrato)
-+ - rhythm sounds phase generation
-+ - white noise generator (big thanks to Olivier Galibert for mentioning Berlekamp-Massey algorithm)
-+ - corrected key on/off handling (the 'key' signal is ORed from three sources: FM, rhythm and CSM)
-+ - funky details (like ignoring output of operator 1 in BD rhythm sound when connect == 1)
-+
-+12-28-2001 Acho A. Tang
-+ - reflected Delta-T EOS status on Y8950 status port.
-+ - fixed subscription range of attack/decay tables
-+
-+
-+	To do:
-+		add delay before key off in CSM mode (see CSMKeyControll)
-+		verify volume of the FM part on the Y8950
- */
- 
- #include <stdio.h>
-@@ -19,80 +54,235 @@
- #include <string.h>
- #include <stdarg.h>
- #include <math.h>
--#include "driver.h"		/* use M.A.M.E. */
--
--/*** For xmp ***/
--#define HAS_YM3812 1
--#define INLINE static inline
--/* $Id$ */
--
- #include "fmopl.h"
- 
- #ifndef PI
- #define PI 3.14159265358979323846
- #endif
- 
-+#ifdef _MSC_VER
-+#  define INLINE __inline
-+#elif defined(__GNUC__)
-+#  define INLINE static inline
-+#else
-+#  define INLINE
-+#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)
-+/* output final shift */
-+#if (OPL_SAMPLE_BITS==16)
-+	#define FINAL_SH	(0)
-+	#define MAXOUT		(+32767)
-+	#define MINOUT		(-32768)
-+#else
-+	#define FINAL_SH	(8)
-+	#define MAXOUT		(+127)
-+	#define MINOUT		(-128)
-+#endif
- 
--/* 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 --------------------- */
-+#define FREQ_SH			16  /* 16.16 fixed point (frequency calculations) */
-+#define EG_SH			16  /* 16.16 fixed point (EG timing)              */
-+#define LFO_SH			24  /*  8.24 fixed point (LFO calculations)       */
-+#define TIMER_SH		16  /* 16.16 fixed point (timers calculations)    */
- 
--/* sinwave entries */
--/* used static memory = SIN_ENT * 4 (byte) */
--#define SIN_ENT 2048
-+#define FREQ_MASK		((1<<FREQ_SH)-1)
- 
--/* 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 ENV_BITS		10
-+#define ENV_LEN			(1<<ENV_BITS)
-+#define ENV_STEP		(128.0/ENV_LEN)
- 
--#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 MAX_ATT_INDEX	((1<<(ENV_BITS-1))-1) /*511*/
-+#define MIN_ATT_INDEX	(0)
- 
--#define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step  */
-+/* sinwave entries */
-+#define SIN_BITS		10
-+#define SIN_LEN			(1<<SIN_BITS)
-+#define SIN_MASK		(SIN_LEN-1)
- 
--/* LFO table entries */
--#define VIB_ENT 512
--#define VIB_SHIFT (32-9)
--#define AMS_ENT 512
--#define AMS_SHIFT (32-9)
-+#define TL_RES_LEN		(256)	/* 8 bits addressing (real chip) */
- 
--#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
-+/* Envelope Generator phases */
-+
-+#define EG_ATT			4
-+#define EG_DEC			3
-+#define EG_SUS			2
-+#define EG_REL			1
-+#define EG_OFF			0
-+
-+
-+/* save output as raw 16-bit sample */
-+
-+/*#define SAVE_SAMPLE*/
-+
-+#ifdef SAVE_SAMPLE
-+static FILE *sample[1];
-+	#if 1	/*save to MONO file */
-+		#define SAVE_ALL_CHANNELS \
-+		{	signed int pom = lt; \
-+			fputc((unsigned short)pom&0xff,sample[0]); \
-+			fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
-+		}
-+	#else	/*save to STEREO file */
-+		#define SAVE_ALL_CHANNELS \
-+		{	signed int pom = lt; \
-+			fputc((unsigned short)pom&0xff,sample[0]); \
-+			fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
-+			pom = rt; \
-+			fputc((unsigned short)pom&0xff,sample[0]); \
-+			fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
-+		}
-+	#endif
-+#endif
-+
-+/* #define LOG_CYM_FILE */
-+#ifdef LOG_CYM_FILE
-+	FILE * cymfile = NULL;
-+#endif
-+
-+
-+
-+#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			*/
-+
-+/* ---------- 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)
-+
-+
-+
-+/* Saving is necessary for member of the 'R' mark for suspend/resume */
-+
-+typedef struct{
-+	UINT32	ar;			/* attack rate: AR<<2			*/
-+	UINT32	dr;			/* decay rate:  DR<<2			*/
-+	UINT32	rr;			/* release rate:RR<<2			*/
-+	UINT8	KSR;		/* key scale rate				*/
-+	UINT8	ksl;		/* keyscale level				*/
-+	UINT8	ksr;		/* key scale rate: kcode>>KSR	*/
-+	UINT8	mul;		/* multiple: mul_tab[ML]		*/
-+
-+	/* Phase Generator */
-+	UINT32	Cnt;		/* frequency counter			*/
-+	UINT32	Incr;		/* frequency counter step		*/
-+	UINT8   FB;			/* feedback shift value			*/
-+	INT32   *connect1;	/* slot1 output pointer			*/
-+	INT32   op1_out[2];	/* slot1 output for feedback	*/
-+	UINT8   CON;		/* connection (algorithm) type	*/
-+
-+	/* Envelope Generator */
-+	UINT8	eg_type;	/* percussive/non-percussive mode */
-+	UINT8	state;		/* phase type					*/
-+	UINT32	TL;			/* total level: TL << 2			*/
-+	INT32	TLL;		/* adjusted now TL				*/
-+	INT32	volume;		/* envelope counter				*/
-+	UINT32	sl;			/* sustain level: sl_tab[SL]	*/
-+
-+	UINT8	eg_sh_ar;	/* (attack state)				*/
-+	UINT8	eg_sel_ar;	/* (attack state)				*/
-+	UINT8	eg_sh_dr;	/* (decay state)				*/
-+	UINT8	eg_sel_dr;	/* (decay state)				*/
-+	UINT8	eg_sh_rr;	/* (release state)				*/
-+	UINT8	eg_sel_rr;	/* (release state)				*/
-+
-+	UINT32	key;		/* 0 = KEY OFF, >0 = KEY ON		*/
-+
-+	/* LFO */
-+	UINT32	AMmask;		/* LFO Amplitude Modulation enable mask */
-+	UINT8	vib;		/* LFO Phase Modulation enable flag (active high)*/
-+
-+	/* waveform select */
-+	unsigned int wavetable;
-+} OPL_SLOT;
-+
-+typedef struct{
-+	OPL_SLOT SLOT[2];
-+	/* phase generator state */
-+	UINT32  block_fnum;	/* block+fnum					*/
-+	UINT32  fc;			/* Freq. Increment base			*/
-+	UINT32  ksl_base;	/* KeyScaleLevel Base step		*/
-+	UINT8   kcode;		/* key code (for key scaling)	*/
-+} OPL_CH;
-+
-+/* OPL state */
-+typedef struct fm_opl_f {
-+	/* FM channel slots */
-+	OPL_CH	P_CH[9];				/* OPL/OPL2 chips have 9 channels*/
-+
-+	UINT32	eg_cnt;					/* global envelope generator counter	*/
-+	UINT32	eg_timer;				/* global envelope generator counter works at frequency = chipclock/72 */
-+	UINT32	eg_timer_add;			/* step of eg_timer						*/
-+	UINT32	eg_timer_overflow;		/* envelope generator timer overlfows every 1 sample (on real chip) */
-+
-+	UINT8	rhythm;					/* Rhythm mode					*/
-+
-+	UINT32	fn_tab[1024];			/* fnumber->increment counter	*/
-+
-+	/* LFO */
-+	UINT8	lfo_am_depth;
-+	UINT8	lfo_pm_depth_range;
-+	UINT32	lfo_am_cnt;
-+	UINT32	lfo_am_inc;
-+	UINT32	lfo_pm_cnt;
-+	UINT32	lfo_pm_inc;
-+
-+	UINT32	noise_rng;				/* 23 bit noise shift register	*/
-+	UINT32	noise_p;				/* current noise 'phase'		*/
-+	UINT32	noise_f;				/* current noise period			*/
-+
-+	UINT8	wavesel;				/* waveform select enable flag	*/
-+
-+	int		T[2];					/* timer counters				*/
-+	UINT8	st[2];					/* timer enable					*/
-+
-+#if BUILD_Y8950
-+	/* Delta-T ADPCM unit (Y8950) */
-+
-+	YM_DELTAT *deltat;
-+
-+	/* Keyboard / I/O interface unit*/
-+	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;
-+#endif
-+
-+	/* external event callback handlers */
-+	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		*/
-+
-+	UINT8 type;						/* chip type					*/
-+	UINT8 address;					/* address register				*/
-+	UINT8 status;					/* status flag					*/
-+	UINT8 statusmask;				/* status mask					*/
-+	UINT8 mode;						/* Reg.08 : CSM,notesel,etc.	*/
-+
-+	int clock;						/* master clock  (Hz)			*/
-+	int rate;						/* sampling rate (Hz)			*/
-+	double freqbase;				/* frequency base				*/
-+	double TimerBase;				/* Timer base time (==sampling time)*/
-+} FM_OPL;
-+
-+
- 
--/* -------------------- tables --------------------- */
-+/* mapping of register number (offset) to slot number used by the emulator */
- static const int slot_array[32]=
- {
- 	 0, 2, 4, 1, 3, 5,-1,-1,
-@@ -102,135 +292,322 @@ static const int slot_array[32]=
- };
- 
- /* key scale level */
--#define ML (0.1875*2/EG_STEP)
--static const UINT32 KSL_TABLE[8*16]=
-+/* table is 3dB/octave , DV converts this into 6dB/octave */
-+/* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */
-+#define DV (0.1875/2.0)
-+static const UINT32 ksl_tab[8*16]=
- {
- 	/* OCT 0 */
--	 0.000*ML, 0.000*ML, 0.000*ML, 0.000*ML,
--	 0.000*ML, 0.000*ML, 0.000*ML, 0.000*ML,
--	 0.000*ML, 0.000*ML, 0.000*ML, 0.000*ML,
--	 0.000*ML, 0.000*ML, 0.000*ML, 0.000*ML,
-+	 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*ML, 0.000*ML, 0.000*ML, 0.000*ML,
--	 0.000*ML, 0.000*ML, 0.000*ML, 0.000*ML,
--	 0.000*ML, 0.750*ML, 1.125*ML, 1.500*ML,
--	 1.875*ML, 2.250*ML, 2.625*ML, 3.000*ML,
-+	 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*ML, 0.000*ML, 0.000*ML, 0.000*ML,
--	 0.000*ML, 1.125*ML, 1.875*ML, 2.625*ML,
--	 3.000*ML, 3.750*ML, 4.125*ML, 4.500*ML,
--	 4.875*ML, 5.250*ML, 5.625*ML, 6.000*ML,
-+	 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*ML, 0.000*ML, 0.000*ML, 1.875*ML,
--	 3.000*ML, 4.125*ML, 4.875*ML, 5.625*ML,
--	 6.000*ML, 6.750*ML, 7.125*ML, 7.500*ML,
--	 7.875*ML, 8.250*ML, 8.625*ML, 9.000*ML,
-+	 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*ML, 0.000*ML, 3.000*ML, 4.875*ML,
--	 6.000*ML, 7.125*ML, 7.875*ML, 8.625*ML,
--	 9.000*ML, 9.750*ML,10.125*ML,10.500*ML,
--	10.875*ML,11.250*ML,11.625*ML,12.000*ML,
-+	 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*ML, 3.000*ML, 6.000*ML, 7.875*ML,
--	 9.000*ML,10.125*ML,10.875*ML,11.625*ML,
--	12.000*ML,12.750*ML,13.125*ML,13.500*ML,
--	13.875*ML,14.250*ML,14.625*ML,15.000*ML,
-+	 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*ML, 6.000*ML, 9.000*ML,10.875*ML,
--	12.000*ML,13.125*ML,13.875*ML,14.625*ML,
--	15.000*ML,15.750*ML,16.125*ML,16.500*ML,
--	16.875*ML,17.250*ML,17.625*ML,18.000*ML,
-+	 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*ML, 9.000*ML,12.000*ML,13.875*ML,
--	15.000*ML,16.125*ML,16.875*ML,17.625*ML,
--	18.000*ML,18.750*ML,19.125*ML,19.500*ML,
--	19.875*ML,20.250*ML,20.625*ML,21.000*ML
-+	 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 ML
-+#undef DV
- 
--/* sustain lebel table (3db per step) */
-+/* sustain level 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]={
-+#define SC(db) (UINT32) ( db * (2.0/ENV_STEP) )
-+static const UINT32 sl_tab[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;
-+#define RATE_STEPS (8)
-+static const unsigned char eg_inc[15*RATE_STEPS]={
-+
-+/*cycle:0 1  2 3  4 5  6 7*/
-+
-+/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */
-+/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..12 1 */
-+/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..12 2 */
-+/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..12 3 */
-+
-+/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 13 0 (increment by 1) */
-+/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 13 1 */
-+/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 13 2 */
-+/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 13 3 */
-+
-+/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 14 0 (increment by 2) */
-+/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 14 1 */
-+/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 14 2 */
-+/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 14 3 */
-+
-+/*12 */ 4,4, 4,4, 4,4, 4,4, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 4) */
-+/*13 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 2, 15 3 for attack */
-+/*14 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */
-+};
-+
-+
-+#define O(a) (a*RATE_STEPS)
-+
-+/*note that there is no O(13) in this table - it's directly in the code */
-+static const unsigned char eg_rate_select[16+64+16]={	/* Envelope Generator rates (16 + 64 rates + 16 RKS) */
-+/* 16 dummy (infinite time) rates */
-+O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
-+O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
-+
-+/* rates 00-12 */
-+O( 0),O( 1),O( 2),O( 3),
-+O( 0),O( 1),O( 2),O( 3),
-+O( 0),O( 1),O( 2),O( 3),
-+O( 0),O( 1),O( 2),O( 3),
-+O( 0),O( 1),O( 2),O( 3),
-+O( 0),O( 1),O( 2),O( 3),
-+O( 0),O( 1),O( 2),O( 3),
-+O( 0),O( 1),O( 2),O( 3),
-+O( 0),O( 1),O( 2),O( 3),
-+O( 0),O( 1),O( 2),O( 3),
-+O( 0),O( 1),O( 2),O( 3),
-+O( 0),O( 1),O( 2),O( 3),
-+O( 0),O( 1),O( 2),O( 3),
-+
-+/* rate 13 */
-+O( 4),O( 5),O( 6),O( 7),
-+
-+/* rate 14 */
-+O( 8),O( 9),O(10),O(11),
- 
--/* LFO table */
--static INT32 *AMS_TABLE;
--static INT32 *VIB_TABLE;
-+/* rate 15 */
-+O(12),O(12),O(12),O(12),
-+
-+/* 16 dummy rates (same as 15 3) */
-+O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),
-+O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),
-+
-+};
-+#undef O
-+
-+//rate  0,    1,    2,    3,   4,   5,   6,  7,  8,  9,  10, 11, 12, 13, 14, 15
-+//shift 12,   11,   10,   9,   8,   7,   6,  5,  4,  3,  2,  1,  0,  0,  0,  0
-+//mask  4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7,  3,  1,  0,  0,  0,  0
-+
-+#define O(a) (a*1)
-+static const unsigned char eg_rate_shift[16+64+16]={	/* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */
-+/* 16 infinite time rates */
-+O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
-+O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
-+
-+/* rates 00-12 */
-+O(12),O(12),O(12),O(12),
-+O(11),O(11),O(11),O(11),
-+O(10),O(10),O(10),O(10),
-+O( 9),O( 9),O( 9),O( 9),
-+O( 8),O( 8),O( 8),O( 8),
-+O( 7),O( 7),O( 7),O( 7),
-+O( 6),O( 6),O( 6),O( 6),
-+O( 5),O( 5),O( 5),O( 5),
-+O( 4),O( 4),O( 4),O( 4),
-+O( 3),O( 3),O( 3),O( 3),
-+O( 2),O( 2),O( 2),O( 2),
-+O( 1),O( 1),O( 1),O( 1),
-+O( 0),O( 0),O( 0),O( 0),
-+
-+/* rate 13 */
-+O( 0),O( 0),O( 0),O( 0),
-+
-+/* rate 14 */
-+O( 0),O( 0),O( 0),O( 0),
-+
-+/* rate 15 */
-+O( 0),O( 0),O( 0),O( 0),
-+
-+/* 16 dummy rates (same as 15 3) */
-+O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
-+O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
-+
-+};
-+#undef O
- 
--/* 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 */
-+static const UINT8 mul_tab[16]= {
-+/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,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};
-+/*	TL_TAB_LEN is calculated as:
-+*	12 - sinus amplitude bits     (Y axis)
-+*	2  - sinus sign bit           (Y axis)
-+*	TL_RES_LEN - sinus resolution (X axis)
-+*/
-+#define TL_TAB_LEN (12*2*TL_RES_LEN)
-+static signed int tl_tab[TL_TAB_LEN];
-+
-+#define ENV_QUIET		(TL_TAB_LEN>>4)
-+
-+/* sin waveform table in 'decibel' scale */
-+/* four waveforms on OPL2 type chips */
-+static unsigned int sin_tab[SIN_LEN * 4];
-+
-+
-+/* LFO Amplitude Modulation table (verified on real YM3812)
-+   27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples
-+
-+   Length: 210 elements.
-+
-+	Each of the elements has to be repeated
-+	exactly 64 times (on 64 consecutive samples).
-+	The whole table takes: 64 * 210 = 13440 samples.
-+
-+	When AM = 1 data is used directly
-+	When AM = 0 data is divided by 4 before being used (loosing precision is important)
-+*/
-+
-+#define LFO_AM_TAB_ELEMENTS 210
-+
-+static const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = {
-+0,0,0,0,0,0,0,
-+1,1,1,1,
-+2,2,2,2,
-+3,3,3,3,
-+4,4,4,4,
-+5,5,5,5,
-+6,6,6,6,
-+7,7,7,7,
-+8,8,8,8,
-+9,9,9,9,
-+10,10,10,10,
-+11,11,11,11,
-+12,12,12,12,
-+13,13,13,13,
-+14,14,14,14,
-+15,15,15,15,
-+16,16,16,16,
-+17,17,17,17,
-+18,18,18,18,
-+19,19,19,19,
-+20,20,20,20,
-+21,21,21,21,
-+22,22,22,22,
-+23,23,23,23,
-+24,24,24,24,
-+25,25,25,25,
-+26,26,26,
-+25,25,25,25,
-+24,24,24,24,
-+23,23,23,23,
-+22,22,22,22,
-+21,21,21,21,
-+20,20,20,20,
-+19,19,19,19,
-+18,18,18,18,
-+17,17,17,17,
-+16,16,16,16,
-+15,15,15,15,
-+14,14,14,14,
-+13,13,13,13,
-+12,12,12,12,
-+11,11,11,11,
-+10,10,10,10,
-+9,9,9,9,
-+8,8,8,8,
-+7,7,7,7,
-+6,6,6,6,
-+5,5,5,5,
-+4,4,4,4,
-+3,3,3,3,
-+2,2,2,2,
-+1,1,1,1
-+};
-+
-+/* LFO Phase Modulation table (verified on real YM3812) */
-+static const INT8 lfo_pm_table[8*8*2] = {
-+
-+/* FNUM2/FNUM = 00 0xxxxxxx (0x0000) */
-+0, 0, 0, 0, 0, 0, 0, 0,	/*LFO PM depth = 0*/
-+0, 0, 0, 0, 0, 0, 0, 0,	/*LFO PM depth = 1*/
-+
-+/* FNUM2/FNUM = 00 1xxxxxxx (0x0080) */
-+0, 0, 0, 0, 0, 0, 0, 0,	/*LFO PM depth = 0*/
-+1, 0, 0, 0,-1, 0, 0, 0,	/*LFO PM depth = 1*/
-+
-+/* FNUM2/FNUM = 01 0xxxxxxx (0x0100) */
-+1, 0, 0, 0,-1, 0, 0, 0,	/*LFO PM depth = 0*/
-+2, 1, 0,-1,-2,-1, 0, 1,	/*LFO PM depth = 1*/
-+
-+/* FNUM2/FNUM = 01 1xxxxxxx (0x0180) */
-+1, 0, 0, 0,-1, 0, 0, 0,	/*LFO PM depth = 0*/
-+3, 1, 0,-1,-3,-1, 0, 1,	/*LFO PM depth = 1*/
-+
-+/* FNUM2/FNUM = 10 0xxxxxxx (0x0200) */
-+2, 1, 0,-1,-2,-1, 0, 1,	/*LFO PM depth = 0*/
-+4, 2, 0,-2,-4,-2, 0, 2,	/*LFO PM depth = 1*/
-+
-+/* FNUM2/FNUM = 10 1xxxxxxx (0x0280) */
-+2, 1, 0,-1,-2,-1, 0, 1,	/*LFO PM depth = 0*/
-+5, 2, 0,-2,-5,-2, 0, 2,	/*LFO PM depth = 1*/
-+
-+/* FNUM2/FNUM = 11 0xxxxxxx (0x0300) */
-+3, 1, 0,-1,-3,-1, 0, 1,	/*LFO PM depth = 0*/
-+6, 3, 0,-3,-6,-3, 0, 3,	/*LFO PM depth = 1*/
-+
-+/* FNUM2/FNUM = 11 1xxxxxxx (0x0380) */
-+3, 1, 0,-1,-3,-1, 0, 1,	/*LFO PM depth = 0*/
-+7, 3, 0,-3,-7,-3, 0, 3	/*LFO PM depth = 1*/
-+};
- 
--/* -------------------- static state --------------------- */
- 
- /* lock level of common table */
- static int num_lock = 0;
- 
- /* work table */
- static void *cur_chip = NULL;	/* current chip point */
--/* current chip state */
--/* static FMSAMPLE  *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 */
-+static signed int phase_modulation;		/* phase modulation input (SLOT 2) */
-+static signed int output[1];
- 
--/* log output level */
--#define LOG_ERR  3      /* ERROR       */
--#define LOG_WAR  2      /* WARNING     */
--#define LOG_INF  1      /* INFORMATION */
-+#if BUILD_Y8950
-+static INT32 output_deltat[4];		/* for Y8950 DELTA-T */
-+#endif
- 
--#define LOG_LEVEL LOG_INF
-+static UINT32	LFO_AM;
-+static INT32	LFO_PM;
- 
--static void Log(int level,char *format,...)
--{
--#if 0
--	va_list argptr;
--
--	if( level < LOG_LEVEL ) return;
--	va_start(argptr,format);
--	/* */
--	if (errorlog) vfprintf( errorlog, format , argptr);
--#endif
--}
- 
--/* --------------------- subroutines  --------------------- */
- 
--INLINE int Limit( int val, int max, int min ) {
-+INLINE int limit( int val, int max, int min ) {
- 	if ( val > max )
- 		val = max;
- 	else if ( val < min )
-@@ -239,6 +616,7 @@ INLINE int Limit( int val, int max, int min ) {
- 	return val;
- }
- 
-+
- /* status set and IRQ handling */
- INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag)
- {
-@@ -280,469 +658,784 @@ INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
- 	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)
-+
-+/* advance LFO to next sample */
-+INLINE void advance_lfo(FM_OPL *OPL)
- {
--	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;
--	}
-+	UINT8 tmp;
-+
-+	/* LFO */
-+	OPL->lfo_am_cnt += OPL->lfo_am_inc;
-+	if (OPL->lfo_am_cnt >= (LFO_AM_TAB_ELEMENTS<<LFO_SH) )	/* lfo_am_table is 210 elements long */
-+		OPL->lfo_am_cnt -= (LFO_AM_TAB_ELEMENTS<<LFO_SH);
-+
-+	tmp = lfo_am_table[ OPL->lfo_am_cnt >> LFO_SH ];
-+
-+	if (OPL->lfo_am_depth)
-+		LFO_AM = tmp;
-+	else
-+		LFO_AM = tmp>>2;
-+
-+	OPL->lfo_pm_cnt += OPL->lfo_pm_inc;
-+	LFO_PM = ((OPL->lfo_pm_cnt>>LFO_SH) & 7) | OPL->lfo_pm_depth_range;
- }
- 
--/* ---------- calcrate Envelope Generator & Phase Generator ---------- */
--/* return : envelope output */
--INLINE UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT )
-+/* advance to next sample */
-+INLINE void advance(FM_OPL *OPL)
- {
--	/* calcrate envelope generator */
--	if( (SLOT->evc+=SLOT->evs) >= SLOT->eve )
-+	OPL_CH *CH;
-+	OPL_SLOT *op;
-+	int i;
-+
-+	OPL->eg_timer += OPL->eg_timer_add;
-+
-+	while (OPL->eg_timer >= OPL->eg_timer_overflow)
- 	{
--		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)
-+		OPL->eg_timer -= OPL->eg_timer_overflow;
-+
-+		OPL->eg_cnt++;
-+
-+		for (i=0; i<9*2; i++)
-+		{
-+			CH  = &OPL->P_CH[i/2];
-+			op  = &CH->SLOT[i&1];
-+
-+			/* Envelope Generator */
-+			switch(op->state)
- 			{
--				SLOT->evs = 0;
--			}
--			else
-+			case EG_ATT:		/* attack phase */
- 			{
--				SLOT->evm = ENV_MOD_RR;
--				SLOT->evs = SLOT->evsr;
-+
-+				if ( !(OPL->eg_cnt & ((1<<op->eg_sh_ar)-1) ) )
-+				{
-+					op->volume += (~op->volume *
-+	                        		           (eg_inc[op->eg_sel_ar + ((OPL->eg_cnt>>op->eg_sh_ar)&7)])
-+        			                          ) >>3;
-+
-+					if (op->volume <= MIN_ATT_INDEX)
-+					{
-+						op->volume = MIN_ATT_INDEX;
-+						op->state = EG_DEC;
-+					}
-+
-+				}
-+
- 			}
- 			break;
--		case ENV_MOD_RR: /* RR -> OFF */
--			SLOT->evc = EG_OFF;
--			SLOT->eve = EG_OFF+1;
--			SLOT->evs = 0;
-+
-+			case EG_DEC:	/* decay phase */
-+				if ( !(OPL->eg_cnt & ((1<<op->eg_sh_dr)-1) ) )
-+				{
-+					op->volume += eg_inc[op->eg_sel_dr + ((OPL->eg_cnt>>op->eg_sh_dr)&7)];
-+
-+					if ( op->volume >= op->sl )
-+						op->state = EG_SUS;
-+
-+				}
-+			break;
-+
-+			case EG_SUS:	/* sustain phase */
-+
-+				/* this is important behaviour:
-+				one can change percusive/non-percussive modes on the fly and
-+				the chip will remain in sustain phase - verified on real YM3812 */
-+
-+				if(op->eg_type)		/* non-percussive mode */
-+				{
-+									/* do nothing */
-+				}
-+				else				/* percussive mode */
-+				{
-+					/* during sustain phase chip adds Release Rate (in percussive mode) */
-+					if ( !(OPL->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )
-+					{
-+						op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];
-+
-+						if ( op->volume >= MAX_ATT_INDEX )
-+							op->volume = MAX_ATT_INDEX;
-+					}
-+					/* else do nothing in sustain phase */
-+				}
-+			break;
-+
-+			case EG_REL:	/* release phase */
-+				if ( !(OPL->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )
-+				{
-+					op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];
-+
-+					if ( op->volume >= MAX_ATT_INDEX )
-+					{
-+						op->volume = MAX_ATT_INDEX;
-+						op->state = EG_OFF;
-+					}
-+
-+				}
-+			break;
-+
-+			default:
- 			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;
--}
-+	for (i=0; i<9*2; i++)
-+	{
-+		CH  = &OPL->P_CH[i/2];
-+		op  = &CH->SLOT[i&1];
- 
--/* ---------- frequency counter for operater update ---------- */
--INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
--{
--	int ksr;
-+		/* Phase Generator */
-+		if(op->vib)
-+		{
-+			UINT8 block;
-+			unsigned int block_fnum = CH->block_fnum;
- 
--	/* frequency step counter */
--	SLOT->Incr = CH->fc * SLOT->mul;
--	ksr = CH->kcode >> SLOT->KSR;
-+			unsigned int fnum_lfo   = (block_fnum&0x0380) >> 7;
- 
--	if( SLOT->ksr != ksr )
-+			signed int lfo_fn_table_index_offset = lfo_pm_table[LFO_PM + 16*fnum_lfo ];
-+
-+			if (lfo_fn_table_index_offset)	/* LFO phase modulation active */
-+			{
-+				block_fnum += lfo_fn_table_index_offset;
-+				block = (block_fnum&0x1c00) >> 10;
-+				op->Cnt += (OPL->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul;//ok
-+			}
-+			else	/* LFO phase modulation  = zero */
-+			{
-+				op->Cnt += op->Incr;
-+			}
-+		}
-+		else	/* LFO phase modulation disabled for this operator */
-+		{
-+			op->Cnt += op->Incr;
-+		}
-+	}
-+
-+	/*	The Noise Generator of the YM3812 is 23-bit shift register.
-+	*	Period is equal to 2^23-2 samples.
-+	*	Register works at sampling frequency of the chip, so output
-+	*	can change on every sample.
-+	*
-+	*	Output of the register and input to the bit 22 is:
-+	*	bit0 XOR bit14 XOR bit15 XOR bit22
-+	*
-+	*	Simply use bit 22 as the noise output.
-+	*/
-+
-+	OPL->noise_p += OPL->noise_f;
-+	i = OPL->noise_p >> FREQ_SH;		/* number of events (shifts of the shift register) */
-+	OPL->noise_p &= FREQ_MASK;
-+	while (i)
- 	{
--		SLOT->ksr = ksr;
--		/* attack , decay rate recalcration */
--		SLOT->evsa = SLOT->AR[ksr];
--		SLOT->evsd = SLOT->DR[ksr];
--		SLOT->evsr = SLOT->RR[ksr];
-+		/*
-+		UINT32 j;
-+		j = ( (OPL->noise_rng) ^ (OPL->noise_rng>>14) ^ (OPL->noise_rng>>15) ^ (OPL->noise_rng>>22) ) & 1;
-+		OPL->noise_rng = (j<<22) | (OPL->noise_rng>>1);
-+		*/
-+
-+		/*
-+			Instead of doing all the logic operations above, we
-+			use a trick here (and use bit 0 as the noise output).
-+			The difference is only that the noise bit changes one
-+			step ahead. This doesn't matter since we don't know
-+			what is real state of the noise_rng after the reset.
-+		*/
-+
-+		if (OPL->noise_rng & 1) OPL->noise_rng ^= 0x800302;
-+		OPL->noise_rng >>= 1;
-+
-+		i--;
- 	}
--	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)
-+
-+INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)
- {
--	OPL_CH   *CH   = &OPL->P_CH[slot/2];
--	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
-+	UINT32 p;
- 
--	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);
-+	p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<16))) >> FREQ_SH ) & SIN_MASK) ];
-+
-+	if (p >= TL_TAB_LEN)
-+		return 0;
-+	return tl_tab[p];
- }
- 
--/* set ksl & tl */
--INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v)
-+INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)
- {
--	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 */
-+	UINT32 p;
-+	INT32  i;
- 
--	SLOT->ksl = ksl ? 3-ksl : 31;
--	SLOT->TL  = (v&0x3f)*(0.75/EG_STEP); /* 0.75db step */
-+	i = (phase & ~FREQ_MASK) + pm;
- 
--	if( !(OPL->mode&0x80) )
--	{	/* not CSM latch total level */
--		SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
--	}
--}
-+/*logerror("i=%08x (i>>16)&511=%8i phase=%i [pm=%08x] ",i, (i>>16)&511, phase>>FREQ_SH, pm);*/
- 
--/* 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;
-+	p = (env<<4) + sin_tab[ wave_tab + ((i>>FREQ_SH) & SIN_MASK)];
- 
--	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;
-+/*logerror("(p&255=%i p>>8=%i) out= %i\n", p&255,p>>8, tl_tab[p&255]>>(p>>8) );*/
- 
--	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;
-+	if (p >= TL_TAB_LEN)
-+		return 0;
-+	return tl_tab[p];
- }
- 
--/* 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;
--}
-+#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (LFO_AM & (OP)->AMmask))
- 
--/* 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 ---------- */
-+/* calculate output */
- INLINE void OPL_CALC_CH( OPL_CH *CH )
- {
--	UINT32 env_out;
- 	OPL_SLOT *SLOT;
-+	unsigned int env;
-+	signed int out;
-+
-+	phase_modulation = 0;
- 
--	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
-+	env  = volume_calc(SLOT);
-+	out  = SLOT->op1_out[0] + SLOT->op1_out[1];
-+	SLOT->op1_out[0] = SLOT->op1_out[1];
-+	*SLOT->connect1 += SLOT->op1_out[0];
-+	SLOT->op1_out[1] = 0;
-+	if( env < ENV_QUIET )
- 	{
--		CH->op1_out[1] = CH->op1_out[0];
--		CH->op1_out[0] = 0;
-+		if (!SLOT->FB)
-+			out = 0;
-+		SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable );
- 	}
-+
- 	/* 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);
--	}
-+	SLOT++;
-+	env = volume_calc(SLOT);
-+	if( env < ENV_QUIET )
-+		output[0] += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable);
- }
- 
--/* ---------- 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;
-+/*
-+	operators used in the rhythm sounds generation process:
-+
-+	Envelope Generator:
-+
-+channel  operator  register number   Bass  High  Snare Tom  Top
-+/ slot   number    TL ARDR SLRR Wave Drum  Hat   Drum  Tom  Cymbal
-+ 6 / 0   12        50  70   90   f0  +
-+ 6 / 1   15        53  73   93   f3  +
-+ 7 / 0   13        51  71   91   f1        +
-+ 7 / 1   16        54  74   94   f4              +
-+ 8 / 0   14        52  72   92   f2                    +
-+ 8 / 1   17        55  75   95   f5                          +
-+
-+	Phase Generator:
- 
-+channel  operator  register number   Bass  High  Snare Tom  Top
-+/ slot   number    MULTIPLE          Drum  Hat   Drum  Tom  Cymbal
-+ 6 / 0   12        30                +
-+ 6 / 1   15        33                +
-+ 7 / 0   13        31                      +     +           +
-+ 7 / 1   16        34                -----  n o t  u s e d -----
-+ 8 / 0   14        32                                  +
-+ 8 / 1   17        35                      +                 +
-+
-+channel  operator  register number   Bass  High  Snare Tom  Top
-+number   number    BLK/FNUM2 FNUM    Drum  Hat   Drum  Tom  Cymbal
-+   6     12,15     B6        A6      +
-+
-+   7     13,16     B7        A7            +     +           +
-+
-+   8     14,17     B8        A8            +           +     +
-+
-+*/
-+
-+/* calculate rhythm */
-+
-+INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise )
-+{
- 	OPL_SLOT *SLOT;
--	int env_out;
-+	signed int out;
-+	unsigned int env;
-+
-+
-+	/* Bass Drum (verified on real YM3812):
-+	  - depends on the channel 6 'connect' register:
-+	      when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out)
-+	      when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored
-+	  - output sample always is multiplied by 2
-+	*/
- 
--	/* BD : same as FM serial mode and output level is large */
--	feedback2 = 0;
-+	phase_modulation = 0;
- 	/* SLOT 1 */
- 	SLOT = &CH[6].SLOT[SLOT1];
--	env_out=OPL_CALC_SLOT(SLOT);
--	if( env_out < EG_ENT-1 )
-+	env = volume_calc(SLOT);
-+
-+	out = SLOT->op1_out[0] + SLOT->op1_out[1];
-+	SLOT->op1_out[0] = SLOT->op1_out[1];
-+
-+	if (!SLOT->CON)
-+		phase_modulation = SLOT->op1_out[0];
-+	//else ignore output of operator 1
-+
-+	SLOT->op1_out[1] = 0;
-+	if( env < ENV_QUIET )
- 	{
--		/* PG */
--		if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
--		else          SLOT->Cnt += SLOT->Incr;
--		/* connectoion */
--		if(CH[6].FB)
-+		if (!SLOT->FB)
-+			out = 0;
-+		SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<<SLOT->FB), SLOT->wavetable );
-+	}
-+
-+	/* SLOT 2 */
-+	SLOT++;
-+	env = volume_calc(SLOT);
-+	if( env < ENV_QUIET )
-+		output[0] += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable) * 2;
-+
-+
-+	/* Phase generation is based on: */
-+	// HH  (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases)
-+	// SD  (16) channel 7->slot 1
-+	// TOM (14) channel 8->slot 1
-+	// TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases)
-+
-+	/* Envelope generation based on: */
-+	// HH  channel 7->slot1
-+	// SD  channel 7->slot2
-+	// TOM channel 8->slot1
-+	// TOP channel 8->slot2
-+
-+
-+	/* The following formulas can be well optimized.
-+	   I leave them in direct form for now (in case I've missed something).
-+	*/
-+
-+	/* High Hat (verified on real YM3812) */
-+	env = volume_calc(SLOT7_1);
-+	if( env < ENV_QUIET )
-+	{
-+
-+		/* high hat phase generation:
-+			phase = d0 or 234 (based on frequency only)
-+			phase = 34 or 2d0 (based on noise)
-+		*/
-+
-+		/* base frequency derived from operator 1 in channel 7 */
-+		unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1;
-+		unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1;
-+		unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1;
-+
-+		unsigned char res1 = (bit2 ^ bit7) | bit3;
-+
-+		/* when res1 = 0 phase = 0x000 | 0xd0; */
-+		/* when res1 = 1 phase = 0x200 | (0xd0>>2); */
-+		UINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0;
-+
-+		/* enable gate based on frequency of operator 2 in channel 8 */
-+		unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1;
-+		unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1;
-+
-+		unsigned char res2 = (bit3e ^ bit5e);
-+
-+		/* when res2 = 0 pass the phase from calculation above (res1); */
-+		/* when res2 = 1 phase = 0x200 | (0xd0>>2); */
-+		if (res2)
-+			phase = (0x200|(0xd0>>2));
-+
-+
-+		/* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */
-+		/* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */
-+		if (phase&0x200)
- 		{
--			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);
-+			if (noise)
-+				phase = 0x200|0xd0;
- 		}
- 		else
-+		/* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */
-+		/* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */
- 		{
--			feedback2 = OP_OUT(SLOT,env_out,0);
-+			if (noise)
-+				phase = 0xd0>>2;
- 		}
--	}else
-+
-+		output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT->wavetable) * 2;
-+	}
-+
-+	/* Snare Drum (verified on real YM3812) */
-+	env = volume_calc(SLOT7_2);
-+	if( env < ENV_QUIET )
- 	{
--		feedback2 = 0;
--		CH[6].op1_out[1] = CH[6].op1_out[0];
--		CH[6].op1_out[0] = 0;
-+		/* base frequency derived from operator 1 in channel 7 */
-+		unsigned char bit8 = ((SLOT7_1->Cnt>>FREQ_SH)>>8)&1;
-+
-+		/* when bit8 = 0 phase = 0x100; */
-+		/* when bit8 = 1 phase = 0x200; */
-+		UINT32 phase = bit8 ? 0x200 : 0x100;
-+
-+		/* Noise bit XOR'es phase by 0x100 */
-+		/* when noisebit = 0 pass the phase from calculation above */
-+		/* when noisebit = 1 phase ^= 0x100; */
-+		/* in other words: phase ^= (noisebit<<8); */
-+		if (noise)
-+			phase ^= 0x100;
-+
-+		output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT->wavetable) * 2;
- 	}
--	/* SLOT 2 */
--	SLOT = &CH[6].SLOT[SLOT2];
--	env_out=OPL_CALC_SLOT(SLOT);
--	if( env_out < EG_ENT-1 )
-+
-+	/* Tom Tom (verified on real YM3812) */
-+	env = volume_calc(SLOT8_1);
-+	if( env < ENV_QUIET )
-+		output[0] += op_calc(SLOT8_1->Cnt, env, 0, SLOT->wavetable) * 2;
-+
-+	/* Top Cymbal (verified on real YM3812) */
-+	env = volume_calc(SLOT8_2);
-+	if( env < ENV_QUIET )
- 	{
--		/* 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;
-+		/* base frequency derived from operator 1 in channel 7 */
-+		unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1;
-+		unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1;
-+		unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1;
-+
-+		unsigned char res1 = (bit2 ^ bit7) | bit3;
-+
-+		/* when res1 = 0 phase = 0x000 | 0x100; */
-+		/* when res1 = 1 phase = 0x200 | 0x100; */
-+		UINT32 phase = res1 ? 0x300 : 0x100;
-+
-+		/* enable gate based on frequency of operator 2 in channel 8 */
-+		unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1;
-+		unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1;
-+
-+		unsigned char res2 = (bit3e ^ bit5e);
-+		/* when res2 = 0 pass the phase from calculation above (res1); */
-+		/* when res2 = 1 phase = 0x200 | 0x100; */
-+		if (res2)
-+			phase = 0x300;
-+
-+		output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT->wavetable) * 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 )
-+}
-+
-+
-+/* generic table initialize */
-+static int init_tables(void)
- {
--	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;
-+	signed int i,x;
-+	signed int n;
-+	double o,m;
-+
-+
-+	for (x=0; x<TL_RES_LEN; x++)
-+	{
-+		m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);
-+		m = floor(m);
-+
-+		/* we never reach (1<<16) here due to the (x+1) */
-+		/* result fits within 16 bits at maximum */
-+
-+		n = (int)m;		/* 16 bits here */
-+		n >>= 4;		/* 12 bits here */
-+		if (n&1)		/* round to nearest */
-+			n = (n>>1)+1;
-+		else
-+			n = n>>1;
-+						/* 11 bits here (rounded) */
-+		n <<= 1;		/* 12 bits here (as in real chip) */
-+		tl_tab[ x*2 + 0 ] = n;
-+		tl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ];
-+
-+		for (i=1; i<12; i++)
-+		{
-+			tl_tab[ x*2+0 + i*2*TL_RES_LEN ] =  tl_tab[ x*2+0 ]>>i;
-+			tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ];
-+		}
-+	#if 0
-+			logerror("tl %04i", x*2);
-+			for (i=0; i<12; i++)
-+				logerror(", [%02i] %5i", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ] );
-+			logerror("\n");
-+	#endif
- 	}
--	for (i = 60;i < 76;i++)
-+	/*logerror("FMOPL.C: TL_TAB_LEN = %i elements (%i bytes)\n",TL_TAB_LEN, (int)sizeof(tl_tab));*/
-+
-+
-+	for (i=0; i<SIN_LEN; i++)
- 	{
--		OPL->AR_TABLE[i] = EG_AED-1;
--		OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
-+		/* non-standard sinus */
-+		m = sin( ((i*2)+1) * PI / SIN_LEN ); /* checked against the real chip */
-+
-+		/* we never reach zero here due to ((i*2)+1) */
-+
-+		if (m>0.0)
-+			o = 8*log(1.0/m)/log(2);	/* convert to 'decibels' */
-+		else
-+			o = 8*log(-1.0/m)/log(2);	/* convert to 'decibels' */
-+
-+		o = o / (ENV_STEP/4);
-+
-+		n = (int)(2.0*o);
-+		if (n&1)						/* round to nearest */
-+			n = (n>>1)+1;
-+		else
-+			n = n>>1;
-+
-+		sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 );
-+
-+		/*logerror("FMOPL.C: sin [%4i (hex=%03x)]= %4i (tl_tab value=%5i)\n", i, i, sin_tab[i], tl_tab[sin_tab[i]] );*/
- 	}
--#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) );
-+
-+	for (i=0; i<SIN_LEN; i++)
-+	{
-+		/* waveform 1:  __      __     */
-+		/*             /  \____/  \____*/
-+		/* output only first half of the sinus waveform (positive one) */
-+
-+		if (i & (1<<(SIN_BITS-1)) )
-+			sin_tab[1*SIN_LEN+i] = TL_TAB_LEN;
-+		else
-+			sin_tab[1*SIN_LEN+i] = sin_tab[i];
-+
-+		/* waveform 2:  __  __  __  __ */
-+		/*             /  \/  \/  \/  \*/
-+		/* abs(sin) */
-+
-+		sin_tab[2*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>1) ];
-+
-+		/* waveform 3:  _   _   _   _  */
-+		/*             / |_/ |_/ |_/ |_*/
-+		/* abs(output only first quarter of the sinus waveform) */
-+
-+		if (i & (1<<(SIN_BITS-2)) )
-+			sin_tab[3*SIN_LEN+i] = TL_TAB_LEN;
-+		else
-+			sin_tab[3*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>2)];
-+
-+		/*logerror("FMOPL.C: sin1[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[1*SIN_LEN+i], tl_tab[sin_tab[1*SIN_LEN+i]] );
-+		logerror("FMOPL.C: sin2[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[2*SIN_LEN+i], tl_tab[sin_tab[2*SIN_LEN+i]] );
-+		logerror("FMOPL.C: sin3[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[3*SIN_LEN+i], tl_tab[sin_tab[3*SIN_LEN+i]] );*/
- 	}
-+	/*logerror("FMOPL.C: ENV_QUIET= %08x (dec*8=%i)\n", ENV_QUIET, ENV_QUIET*8 );*/
-+
-+
-+#ifdef SAVE_SAMPLE
-+	sample[0]=fopen("sampsum.pcm","wb");
- #endif
-+
-+	return 1;
- }
- 
--/* ---------- generic table initialize ---------- */
--static int OPLOpenTable( void )
-+static void OPLCloseTable( void )
- {
--	int s,t;
--	double rate;
--	int i,j;
--	double pom;
-+#ifdef SAVE_SAMPLE
-+	fclose(sample[0]);
-+#endif
-+}
- 
--	/* 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)
-+
-+
-+static void OPL_initalize(FM_OPL *OPL)
-+{
-+	int i;
-+
-+	/* frequency base */
-+#if 1
-+	OPL->freqbase  = (OPL->rate) ? ((double)OPL->clock / 72.0) / OPL->rate  : 0;
-+#else
-+	OPL->rate = (double)OPL->clock / 72.0;
-+	OPL->freqbase  = 1.0;
-+#endif
-+
-+	/* Timer base time */
-+	OPL->TimerBase = 1.0 / ((double)OPL->clock / 72.0 );
-+
-+	/* make fnumber -> increment counter table */
-+	for( i=0 ; i < 1024 ; i++ )
- 	{
--		free(TL_TABLE);
--		return 0;
-+		/* opn phase increment counter = 20bit */
-+		OPL->fn_tab[i] = (UINT32)( (double)i * 64 * OPL->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */
-+#if 0
-+		logerror("FMOPL.C: fn_tab[%4i] = %08x (dec=%8i)\n",
-+				 i, OPL->fn_tab[i]>>6, OPL->fn_tab[i]>>6 );
-+#endif
- 	}
--	if( (AMS_TABLE = malloc(AMS_ENT*2 *sizeof(INT32))) == NULL)
-+
-+#if 0
-+	for( i=0 ; i < 16 ; i++ )
- 	{
--		free(TL_TABLE);
--		free(SIN_TABLE);
--		return 0;
-+		logerror("FMOPL.C: sl_tab[%i] = %08x\n",
-+			i, sl_tab[i] );
- 	}
--	if( (VIB_TABLE = malloc(VIB_ENT*2 *sizeof(INT32))) == NULL)
-+	for( i=0 ; i < 8 ; i++ )
- 	{
--		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;
-+		int j;
-+		logerror("FMOPL.C: ksl_tab[oct=%2i] =",i);
-+		for (j=0; j<16; j++)
-+		{
-+			logerror("%08x ", ksl_tab[i*16+j] );
-+		}
-+		logerror("\n");
- 	}
-+#endif
- 
--	/* 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++)
-+	/* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */
-+	/* One entry from LFO_AM_TABLE lasts for 64 samples */
-+	OPL->lfo_am_inc = (1.0 / 64.0 ) * (1<<LFO_SH) * OPL->freqbase;
-+
-+	/* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */
-+	OPL->lfo_pm_inc = (1.0 / 1024.0) * (1<<LFO_SH) * OPL->freqbase;
-+
-+	/*logerror ("OPL->lfo_am_inc = %8x ; OPL->lfo_pm_inc = %8x\n", OPL->lfo_am_inc, OPL->lfo_pm_inc);*/
-+
-+	/* Noise generator: a step takes 1 sample */
-+	OPL->noise_f = (1.0 / 1.0) * (1<<FREQ_SH) * OPL->freqbase;
-+
-+	OPL->eg_timer_add  = (1<<EG_SH)  * OPL->freqbase;
-+	OPL->eg_timer_overflow = ( 1 ) * (1<<EG_SH);
-+	/*logerror("OPLinit eg_timer_add=%8x eg_timer_overflow=%8x\n", OPL->eg_timer_add, OPL->eg_timer_overflow);*/
-+
-+}
-+
-+INLINE void FM_KEYON(OPL_SLOT *SLOT, UINT32 key_set)
-+{
-+	if( !SLOT->key )
- 	{
--		/* 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;
-+		/* restart Phase Generator */
-+		SLOT->Cnt = 0;
-+		/* phase -> Attack */
-+		SLOT->state = EG_ATT;
- 	}
--	/* off */
--	ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1;
--	/* make LFO ams table */
--	for (i=0; i<AMS_ENT; i++)
-+	SLOT->key |= key_set;
-+}
-+
-+INLINE void FM_KEYOFF(OPL_SLOT *SLOT, UINT32 key_clr)
-+{
-+	if( SLOT->key )
- 	{
--		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 */
-+		SLOT->key &= key_clr;
-+
-+		if( !SLOT->key )
-+		{
-+			/* phase -> Release */
-+			if (SLOT->state>EG_REL)
-+				SLOT->state = EG_REL;
-+		}
- 	}
--	/* make LFO vibrate table */
--	for (i=0; i<VIB_ENT; i++)
-+}
-+
-+/* update phase increment counter of operator (also update the EG rates if necessary) */
-+INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
-+{
-+	int ksr;
-+
-+	/* (frequency) phase increment counter */
-+	SLOT->Incr = CH->fc * SLOT->mul;
-+	ksr = CH->kcode >> SLOT->KSR;
-+
-+	if( SLOT->ksr != ksr )
- 	{
--		/* 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]); */
-+		SLOT->ksr = ksr;
-+
-+		/* calculate envelope generator rates */
-+		if ((SLOT->ar + SLOT->ksr) < 16+62)
-+		{
-+			SLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];
-+			SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
-+		}
-+		else
-+		{
-+			SLOT->eg_sh_ar  = 0;
-+			SLOT->eg_sel_ar = 13*RATE_STEPS;
-+		}
-+		SLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];
-+		SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
-+		SLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];
-+		SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
- 	}
--	return 1;
- }
- 
--
--static void OPLCloseTable( void )
-+/* set multi,am,vib,EG-TYP,KSR,mul */
-+INLINE void set_mul(FM_OPL *OPL,int slot,int v)
- {
--	free(TL_TABLE);
--	free(SIN_TABLE);
--	free(AMS_TABLE);
--	free(VIB_TABLE);
-+	OPL_CH   *CH   = &OPL->P_CH[slot/2];
-+	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
-+
-+	SLOT->mul     = mul_tab[v&0x0f];
-+	SLOT->KSR     = (v&0x10) ? 0 : 2;
-+	SLOT->eg_type = (v&0x20);
-+	SLOT->vib     = (v&0x40);
-+	SLOT->AMmask  = (v&0x80) ? ~0 : 0;
-+	CALC_FCSLOT(CH,SLOT);
- }
- 
--/* CSM Key Controll */
--INLINE void CSMKeyControll(OPL_CH *CH)
-+/* set ksl & tl */
-+INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v)
- {
--	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)
-+	OPL_CH   *CH   = &OPL->P_CH[slot/2];
-+	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
-+	int ksl = v>>6; /* 0 / 1.5 / 3.0 / 6.0 dB/OCT */
-+
-+	SLOT->ksl = ksl ? 3-ksl : 31;
-+	SLOT->TL  = (v&0x3f)<<(ENV_BITS-1-7); /* 7 bits TL (bit 6 = always 0) */
-+
-+	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)
- {
--	int fn;
-+	OPL_CH   *CH   = &OPL->P_CH[slot/2];
-+	OPL_SLOT *SLOT = &CH->SLOT[slot&1];
- 
--	/* 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++ )
-+	SLOT->ar = (v>>4)  ? 16 + ((v>>4)  <<2) : 0;
-+
-+	if ((SLOT->ar + SLOT->ksr) < 16+62)
- 	{
--		OPL->FN_TABLE[fn] = OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2;
-+		SLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];
-+		SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
- 	}
--	/* 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;
-+	else
-+	{
-+		SLOT->eg_sh_ar  = 0;
-+		SLOT->eg_sel_ar = 13*RATE_STEPS;
-+	}
-+
-+	SLOT->dr    = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
-+	SLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];
-+	SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
- }
- 
--/* ---------- write a OPL registers ---------- */
-+/* 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];
-+
-+	SLOT->sl  = sl_tab[ v>>4 ];
-+
-+	SLOT->rr  = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
-+	SLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];
-+	SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
-+}
-+
-+
-+/* write a value v to register r on OPL chip */
- static void OPLWriteReg(FM_OPL *OPL, int r, int v)
- {
- 	OPL_CH *CH;
- 	int slot;
- 	int block_fnum;
- 
-+
-+	/* adjust bus to 8 bits */
-+	r &= 0xff;
-+	v &= 0xff;
-+
-+#ifdef LOG_CYM_FILE
-+	if ((cymfile) && (r!=0) )
-+	{
-+		fputc( (unsigned char)r, cymfile );
-+		fputc( (unsigned char)v, cymfile );
-+	}
-+#endif
-+
-+
- 	switch(r&0xe0)
- 	{
- 	case 0x00: /* 00-1f:controll */
-@@ -753,24 +1446,15 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
- 			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];
--					}
--				}
-+				/* do not change the waveform previously selected */
- 			}
--			return;
-+			break;
- 		case 0x02:	/* Timer 1 */
- 			OPL->T[0] = (256-v)*4;
- 			break;
- 		case 0x03:	/* Timer 2 */
- 			OPL->T[1] = (256-v)*16;
--			return;
-+			break;
- 		case 0x04:	/* IRQ clear / mask and Timer enable */
- 			if(v&0x80)
- 			{	/* IRQ flag clear */
-@@ -798,7 +1482,7 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
- 					if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+0,interval);
- 				}
- 			}
--			return;
-+			break;
- #if BUILD_Y8950
- 		case 0x06:		/* Key Board OUT */
- 			if(OPL->type&OPL_TYPE_KEYBOARD)
-@@ -806,13 +1490,13 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
- 				if(OPL->keyboardhandler_w)
- 					OPL->keyboardhandler_w(OPL->keyboard_param,v);
- 				else
--					Log(LOG_WAR,"OPL:write unmapped KEYBOARD port\n");
-+					logerror("OPL:write unmapped KEYBOARD port\n");
- 			}
--			return;
-+			break;
- 		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;
-+			break;
- 		case 0x08:	/* MODE,DELTA-T : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */
- 			OPL->mode = v;
- 			v&=0x1f;	/* for DELTA-T unit */
-@@ -828,16 +1512,16 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
- 		case 0x12: 		/* EG-CTRL    */
- 			if(OPL->type&OPL_TYPE_ADPCM)
- 				YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
--			return;
-+			break;
- #if 0
- 		case 0x15:		/* DAC data    */
- 		case 0x16:
- 		case 0x17:		/* SHIFT    */
--			return;
-+			break;
- 		case 0x18:		/* I/O CTRL (Direction) */
- 			if(OPL->type&OPL_TYPE_IO)
- 				OPL->portDirection = v&0x0f;
--			return;
-+			break;
- 		case 0x19:		/* I/O DATA */
- 			if(OPL->type&OPL_TYPE_IO)
- 			{
-@@ -845,87 +1529,80 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
- 				if(OPL->porthandler_w)
- 					OPL->porthandler_w(OPL->port_param,v&OPL->portDirection);
- 			}
--			return;
-+			break;
- 		case 0x1a:		/* PCM data */
--			return;
-+			break;
- #endif
- #endif
- 		}
- 		break;
--	case 0x20:	/* am,vib,ksr,eg type,mul */
-+	case 0x20:	/* am ON, vib ON, ksr, eg_type, mul */
- 		slot = slot_array[r&0x1f];
--		if(slot == -1) return;
-+		if(slot < 0) return;
- 		set_mul(OPL,slot,v);
--		return;
-+		break;
- 	case 0x40:
- 		slot = slot_array[r&0x1f];
--		if(slot == -1) return;
-+		if(slot < 0) return;
- 		set_ksl_tl(OPL,slot,v);
--		return;
-+		break;
- 	case 0x60:
- 		slot = slot_array[r&0x1f];
--		if(slot == -1) return;
-+		if(slot < 0) return;
- 		set_ar_dr(OPL,slot,v);
--		return;
-+		break;
- 	case 0x80:
- 		slot = slot_array[r&0x1f];
--		if(slot == -1) return;
-+		if(slot < 0) return;
- 		set_sl_rr(OPL,slot,v);
--		return;
-+		break;
- 	case 0xa0:
--		switch(r)
-+		if (r == 0xbd)			/* am depth, vibrato depth, r,bd,sd,tom,tc,hh */
- 		{
--		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)
-+			OPL->lfo_am_depth = v & 0x80;
-+			OPL->lfo_pm_depth_range = (v&0x40) ? 8 : 0;
-+
-+			OPL->rhythm  = v&0x3f;
-+
-+			if(OPL->rhythm&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&0x10)
- 				{
--					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]);
-+					FM_KEYON (&OPL->P_CH[6].SLOT[SLOT1], 2);
-+					FM_KEYON (&OPL->P_CH[6].SLOT[SLOT2], 2);
- 				}
--				/* TOP-CY key on/off */
--				if(rkey&0x02)
-+				else
- 				{
--					if(v&0x02) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);
--					else       OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);
-+					FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2);
-+					FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2);
- 				}
- 				/* 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]);
--				}
-+				if(v&0x01) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT1], 2);
-+				else       FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2);
-+				/* SD key on/off */
-+				if(v&0x08) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT2], 2);
-+				else       FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2);
-+				/* TOM key on/off */
-+				if(v&0x04) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT1], 2);
-+				else       FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2);
-+				/* TOP-CY key on/off */
-+				if(v&0x02) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT2], 2);
-+				else       FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2);
- 			}
-+			else
-+			{
-+				/* BD key off */
-+				FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2);
-+				FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2);
-+				/* HH key off */
-+				FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2);
-+				/* SD key off */
-+				FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2);
-+				/* TOM key off */
-+				FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2);
-+				/* TOP-CY off */
-+				FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2);
- 			}
- 			return;
- 		}
-@@ -938,75 +1615,105 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
- 		}
- 		else
- 		{	/* b0-b8 */
--			int keyon = (v>>5)&1;
- 			block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);
--			if(CH->keyon != keyon)
-+
-+			if(v&0x20)
- 			{
--				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]);
--				}
-+				FM_KEYON (&CH->SLOT[SLOT1], 1);
-+				FM_KEYON (&CH->SLOT[SLOT2], 1);
-+			}
-+			else
-+			{
-+				FM_KEYOFF(&CH->SLOT[SLOT1],~1);
-+				FM_KEYOFF(&CH->SLOT[SLOT2],~1);
- 			}
- 		}
- 		/* update */
- 		if(CH->block_fnum != block_fnum)
- 		{
--			int blockRv = 7-(block_fnum>>10);
--			int fnum   = block_fnum&0x3ff;
-+			UINT8 block  = block_fnum >> 10;
-+
- 			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;
-+			CH->ksl_base = ksl_tab[block_fnum>>6];
-+			CH->fc       = OPL->fn_tab[block_fnum&0x03ff] >> (7-block);
-+
-+			/* BLK 2,1,0 bits -> bits 3,2,1 of kcode */
-+			CH->kcode    = (CH->block_fnum&0x1c00)>>9;
-+
-+			 /* the info below is actually opposite to what is stated in the Manuals (verifed on real YM3812) */
-+			/* if notesel == 0 -> lsb of kcode is bit 10 (MSB) of fnum  */
-+			/* if notesel == 1 -> lsb of kcode is bit 9 (MSB-1) of fnum */
-+			if (OPL->mode&0x40)
-+				CH->kcode |= (CH->block_fnum&0x100)>>8;	/* notesel == 1 */
-+			else
-+				CH->kcode |= (CH->block_fnum&0x200)>>9;	/* notesel == 0 */
-+
-+			/* refresh Total Level in both SLOTs of this channel */
-+			CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);
-+			CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);
-+
-+			/* refresh frequency counter in both SLOTs of this channel */
- 			CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
- 			CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
- 		}
--		return;
-+		break;
- 	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];
-+		CH->SLOT[SLOT1].FB  = (v>>1)&7 ? ((v>>1)&7) + 7 : 0;
-+		CH->SLOT[SLOT1].CON = v&1;
-+		CH->SLOT[SLOT1].connect1 = CH->SLOT[SLOT1].CON ? &output[0] : &phase_modulation;
-+		break;
-+	case 0xe0: /* waveform select */
-+		/* simply ignore write to the waveform select register if selecting not enabled in test register */
- 		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];
-+			slot = slot_array[r&0x1f];
-+			if(slot < 0) return;
-+			CH = &OPL->P_CH[slot/2];
-+
-+			CH->SLOT[slot&1].wavetable = (v&0x03)*SIN_LEN;
- 		}
--		return;
-+		break;
-+	}
-+}
-+
-+#ifdef LOG_CYM_FILE
-+static void cymfile_callback (int n)
-+{
-+	if (cymfile)
-+	{
-+		fputc( (unsigned char)0, cymfile );
- 	}
- }
-+#endif
- 
- /* 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() )
-+	if( !init_tables() )
- 	{
- 		num_lock--;
- 		return -1;
- 	}
-+
-+#ifdef LOG_CYM_FILE
-+	cymfile = fopen("3812_.cym","wb");
-+	if (cymfile)
-+		timer_pulse ( TIME_IN_HZ(110), 0, cymfile_callback); /*110 Hz pulse timer*/
-+	else
-+		logerror("Could not create file 3812_.cym\n");
-+#endif
-+
- 	return 0;
- }
- 
-@@ -1014,159 +1721,48 @@ 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                                          */
--/******************************************************************************/
--
--/*** Prototype changed to use with xmp ***/
--/* ---------- update one of chip ----------- */
--void YM3812UpdateOne(FM_OPL *OPL, FMSAMPLE *bk, int len, int vl, int vr, int st)
--{
--	int data;
--	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;
--        while (len--) {
--		/* 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);
--		/* Rythm part */
--		if(rythm)
--			OPL_CALC_RH(S_CH);
--		/* limit check */
--		data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
- 
--		/* store to sound buffer - changed to use with xmp */
--		if (st) 
--			*(bk++) += (data >> OPL_OUTSB) * vr;
--		*(bk++) += (data >> OPL_OUTSB) * vl;
--	}
--
--	OPL->amsCnt = amsCnt;
--	OPL->vibCnt = vibCnt;
--}
--#endif /* (BUILD_YM3812 || BUILD_YM3526) */
--
--#if BUILD_Y8950
--
--void Y8950UpdateOne(FM_OPL *OPL, void *buffer, int length)
--{
--    int i;
--	int data;
--	FMSAMPLE *buf = (FMSAMPLE *)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);
-+#ifdef LOG_CYM_FILE
-+	fclose (cymfile);
-+	cymfile = NULL;
-+#endif
- 
--	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->flag )
--			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->flag )
--		OPL->status &= 0xfe;
- }
--#endif
- 
--/* ---------- reset one of chip ---------- */
--void OPLResetChip(FM_OPL *OPL)
-+static void OPLResetChip(FM_OPL *OPL)
- {
- 	int c,s;
- 	int i;
- 
--	/* reset chip */
-+	OPL->eg_timer = 0;
-+	OPL->eg_cnt   = 0;
-+
-+	OPL->noise_rng = 1;	/* noise shift register */
- 	OPL->mode   = 0;	/* normal mode */
- 	OPL_STATUS_RESET(OPL,0x7f);
-+
- 	/* reset with register write */
--	OPLWriteReg(OPL,0x01,0); /* wabesel disable */
-+	OPLWriteReg(OPL,0x01,0); /* wavesel 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++ )
-+
-+	/* reset operator parameters */
-+	for( c = 0 ; c < 9 ; 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;
-+			CH->SLOT[s].wavetable = 0;
-+			CH->SLOT[s].state     = EG_OFF;
-+			CH->SLOT[s].volume    = MAX_ATT_INDEX;
- 		}
- 	}
- #if BUILD_Y8950
-@@ -1175,93 +1771,90 @@ void OPLResetChip(FM_OPL *OPL)
- 		YM_DELTAT *DELTAT = OPL->deltat;
- 
- 		DELTAT->freqbase = OPL->freqbase;
--		DELTAT->output_pointer = outd;
-+		DELTAT->output_pointer = &output_deltat[0];
- 		DELTAT->portshift = 5;
--		DELTAT->output_range = DELTAT_MIXING_LEVEL<<TL_BITS;
-+		DELTAT->output_range = 1<<23;
- 		YM_DELTAT_ADPCM_Reset(DELTAT,0);
- 	}
- #endif
- }
- 
--/* ----------  Create one of virtual YM3812 ----------       */
--/* 'rate'  is sampling rate and 'bufsiz' is the size of the  */
--FM_OPL *OPLCreate(int type, int clock, int rate)
-+/* Create one of virtual YM3812 */
-+/* 'clock' is chip clock in Hz  */
-+/* 'rate'  is sampling rate  */
-+static 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 */
-+	if (OPL_LockTable() ==-1) return NULL;
-+
-+	/* calculate OPL state size */
- 	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);
-+	if (type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT);
- #endif
-+
- 	/* allocate memory block */
- 	ptr = malloc(state_size);
--	if(ptr==NULL) return NULL;
-+
-+	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;
-+
-+	OPL  = (FM_OPL *)ptr;
-+
-+	ptr += sizeof(FM_OPL);
-+
- #if BUILD_Y8950
--	if(type&OPL_TYPE_ADPCM) OPL->deltat = (YM_DELTAT *)ptr; ptr+=sizeof(YM_DELTAT);
-+	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 */
-+
-+	/* init global tables */
- 	OPL_initalize(OPL);
-+
- 	/* reset chip */
- 	OPLResetChip(OPL);
- 	return OPL;
- }
- 
--/* ----------  Destroy one of vietual YM3812 ----------       */
--void OPLDestroy(FM_OPL *OPL)
-+/* Destroy one of virtual YM3812 */
-+static void OPLDestroy(FM_OPL *OPL)
- {
- 	OPL_UnLockTable();
- 	free(OPL);
- }
- 
--/* ----------  Option handlers ----------       */
-+/* Option handlers */
- 
--void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset)
-+static 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)
-+static 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)
-+static 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)
-+/* YM3812 I/O interface */
-+static int OPLWrite(FM_OPL *OPL,int a,int v)
- {
- 	if( !(a&1) )
- 	{	/* address port */
-@@ -1275,12 +1868,15 @@ int OPLWrite(FM_OPL *OPL,int a,int v)
- 	return OPL->status>>7;
- }
- 
--unsigned char OPLRead(FM_OPL *OPL,int a)
-+static unsigned char OPLRead(FM_OPL *OPL,int a)
- {
- 	if( !(a&1) )
--	{	/* status port */
-+	{
-+		/* status port */
- 		return OPL->status & (OPL->statusmask|0x80);
- 	}
-+
-+#if BUILD_Y8950
- 	/* data port */
- 	switch(OPL->address)
- 	{
-@@ -1290,7 +1886,7 @@ unsigned char OPLRead(FM_OPL *OPL,int a)
- 			if(OPL->keyboardhandler_r)
- 				return OPL->keyboardhandler_r(OPL->keyboard_param);
- 			else
--				Log(LOG_WAR,"OPL:read unmapped KEYBOARD port\n");
-+				logerror("OPL:read unmapped KEYBOARD port\n");
- 		}
- 		return 0;
- #if 0
-@@ -1303,16 +1899,31 @@ unsigned char OPLRead(FM_OPL *OPL,int a)
- 			if(OPL->porthandler_r)
- 				return OPL->porthandler_r(OPL->port_param);
- 			else
--				Log(LOG_WAR,"OPL:read unmapped I/O port\n");
-+				logerror("OPL:read unmapped I/O port\n");
- 		}
- 		return 0;
- 	case 0x1a: /* PCM-DATA    */
- 		return 0;
- 	}
--	return 0;
-+#endif
-+
-+	return 0xff;
- }
- 
--int OPLTimerOver(FM_OPL *OPL,int c)
-+/* CSM Key Controll */
-+INLINE void CSMKeyControll(OPL_CH *CH)
-+{
-+	FM_KEYON (&CH->SLOT[SLOT1], 4);
-+	FM_KEYON (&CH->SLOT[SLOT2], 4);
-+
-+	/* The key off should happen exactly one sample later - not implemented correctly yet */
-+
-+	FM_KEYOFF(&CH->SLOT[SLOT1], ~4);
-+	FM_KEYOFF(&CH->SLOT[SLOT2], ~4);
-+}
-+
-+
-+static int OPLTimerOver(FM_OPL *OPL,int c)
- {
- 	if( c )
- 	{	/* Timer B */
-@@ -1334,3 +1945,489 @@ int OPLTimerOver(FM_OPL *OPL,int c)
- 	if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase);
- 	return OPL->status>>7;
- }
-+
-+
-+#define MAX_OPL_CHIPS 2
-+
-+
-+#if (BUILD_YM3812)
-+
-+static FM_OPL *OPL_YM3812[MAX_OPL_CHIPS];	/* array of pointers to the YM3812's */
-+static int YM3812NumChips = 0;				/* number of chips */
-+
-+int YM3812Init(int num, int clock, int rate)
-+{
-+	int i;
-+
-+	if (YM3812NumChips)
-+		return -1;	/* duplicate init. */
-+
-+	YM3812NumChips = num;
-+
-+	for (i = 0;i < YM3812NumChips; i++)
-+	{
-+		/* emulator create */
-+		OPL_YM3812[i] = OPLCreate(OPL_TYPE_YM3812,clock,rate);
-+		if(OPL_YM3812[i] == NULL)
-+		{
-+			/* it's really bad - we run out of memeory */
-+			YM3812NumChips = 0;
-+			return -1;
-+		}
-+	}
-+
-+	return 0;
-+}
-+
-+void YM3812Shutdown(void)
-+{
-+	int i;
-+
-+	for (i = 0;i < YM3812NumChips; i++)
-+	{
-+		/* emulator shutdown */
-+		OPLDestroy(OPL_YM3812[i]);
-+		OPL_YM3812[i] = NULL;
-+	}
-+	YM3812NumChips = 0;
-+}
-+void YM3812ResetChip(int which)
-+{
-+	OPLResetChip(OPL_YM3812[which]);
-+}
-+
-+int YM3812Write(int which, int a, int v)
-+{
-+	return OPLWrite(OPL_YM3812[which], a, v);
-+}
-+
-+unsigned char YM3812Read(int which, int a)
-+{
-+	/* YM3812 always returns bit2 and bit1 in HIGH state */
-+	return OPLRead(OPL_YM3812[which], a) | 0x06 ;
-+}
-+int YM3812TimerOver(int which, int c)
-+{
-+	return OPLTimerOver(OPL_YM3812[which], c);
-+}
-+
-+void YM3812SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset)
-+{
-+	OPLSetTimerHandler(OPL_YM3812[which], TimerHandler, channelOffset);
-+}
-+void YM3812SetIRQHandler(int which,OPL_IRQHANDLER IRQHandler,int param)
-+{
-+	OPLSetIRQHandler(OPL_YM3812[which], IRQHandler, param);
-+}
-+void YM3812SetUpdateHandler(int which,OPL_UPDATEHANDLER UpdateHandler,int param)
-+{
-+	OPLSetUpdateHandler(OPL_YM3812[which], UpdateHandler, param);
-+}
-+
-+
-+/*
-+** Generate samples for one of the YM3812's
-+**
-+** 'which' is the virtual YM3812 number
-+** '*buffer' is the output buffer pointer
-+** 'length' is the number of samples that should be generated
-+*/
-+void YM3812UpdateOne(int which, INT32 *buffer, int length, int vl, int vr, int st)
-+{
-+	FM_OPL		*OPL = OPL_YM3812[which];
-+	UINT8		rhythm = OPL->rhythm&0x20;
-+	INT32   	*buf = buffer;
-+	int i;
-+
-+	if( (void *)OPL != cur_chip ){
-+		cur_chip = (void *)OPL;
-+		/* rhythm slots */
-+		SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1];
-+		SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2];
-+		SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1];
-+		SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2];
-+	}
-+	for( i=0; i < length ; i++ )
-+	{
-+		int lt;
-+
-+		output[0] = 0;
-+
-+		advance_lfo(OPL);
-+
-+		/* FM part */
-+		OPL_CALC_CH(&OPL->P_CH[0]);
-+		OPL_CALC_CH(&OPL->P_CH[1]);
-+		OPL_CALC_CH(&OPL->P_CH[2]);
-+		OPL_CALC_CH(&OPL->P_CH[3]);
-+		OPL_CALC_CH(&OPL->P_CH[4]);
-+		OPL_CALC_CH(&OPL->P_CH[5]);
-+
-+		if(!rhythm)
-+		{
-+			OPL_CALC_CH(&OPL->P_CH[6]);
-+			OPL_CALC_CH(&OPL->P_CH[7]);
-+			OPL_CALC_CH(&OPL->P_CH[8]);
-+		}
-+		else		/* Rhythm part */
-+		{
-+			OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
-+		}
-+
-+		lt = output[0];
-+
-+		lt >>= FINAL_SH;
-+
-+		/* limit check */
-+		lt = limit( lt , MAXOUT, MINOUT );
-+
-+		#ifdef SAVE_SAMPLE
-+			SAVE_ALL_CHANNELS
-+		#endif
-+
-+		/* store to sound buffer */
-+		
-+
-+		if (st) 
-+		   *(buf++) = lt * vr;
-+		*(buf++) += lt * vl;
-+
-+		advance(OPL);
-+	}
-+
-+}
-+#endif /* BUILD_YM3812 */
-+
-+
-+
-+#if (BUILD_YM3526)
-+
-+static FM_OPL *OPL_YM3526[MAX_OPL_CHIPS];	/* array of pointers to the YM3526's */
-+static int YM3526NumChips = 0;				/* number of chips */
-+
-+int YM3526Init(int num, int clock, int rate)
-+{
-+	int i;
-+
-+	if (YM3526NumChips)
-+		return -1;	/* duplicate init. */
-+
-+	YM3526NumChips = num;
-+
-+	for (i = 0;i < YM3526NumChips; i++)
-+	{
-+		/* emulator create */
-+		OPL_YM3526[i] = OPLCreate(OPL_TYPE_YM3526,clock,rate);
-+		if(OPL_YM3526[i] == NULL)
-+		{
-+			/* it's really bad - we run out of memeory */
-+			YM3526NumChips = 0;
-+			return -1;
-+		}
-+	}
-+
-+	return 0;
-+}
-+
-+void YM3526Shutdown(void)
-+{
-+	int i;
-+
-+	for (i = 0;i < YM3526NumChips; i++)
-+	{
-+		/* emulator shutdown */
-+		OPLDestroy(OPL_YM3526[i]);
-+		OPL_YM3526[i] = NULL;
-+	}
-+	YM3526NumChips = 0;
-+}
-+void YM3526ResetChip(int which)
-+{
-+	OPLResetChip(OPL_YM3526[which]);
-+}
-+
-+int YM3526Write(int which, int a, int v)
-+{
-+	return OPLWrite(OPL_YM3526[which], a, v);
-+}
-+
-+unsigned char YM3526Read(int which, int a)
-+{
-+	return OPLRead(OPL_YM3526[which], a);
-+}
-+int YM3526TimerOver(int which, int c)
-+{
-+	return OPLTimerOver(OPL_YM3526[which], c);
-+}
-+
-+void YM3526SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset)
-+{
-+	OPLSetTimerHandler(OPL_YM3526[which], TimerHandler, channelOffset);
-+}
-+void YM3526SetIRQHandler(int which,OPL_IRQHANDLER IRQHandler,int param)
-+{
-+	OPLSetIRQHandler(OPL_YM3526[which], IRQHandler, param);
-+}
-+void YM3526SetUpdateHandler(int which,OPL_UPDATEHANDLER UpdateHandler,int param)
-+{
-+	OPLSetUpdateHandler(OPL_YM3526[which], UpdateHandler, param);
-+}
-+
-+
-+/*
-+** Generate samples for one of the YM3526's
-+**
-+** 'which' is the virtual YM3526 number
-+** '*buffer' is the output buffer pointer
-+** 'length' is the number of samples that should be generated
-+*/
-+void YM3526UpdateOne(int which, INT16 *buffer, int length)
-+{
-+	FM_OPL		*OPL = OPL_YM3526[which];
-+	UINT8		rhythm = OPL->rhythm&0x20;
-+	OPLSAMPLE	*buf = buffer;
-+	int i;
-+
-+	if( (void *)OPL != cur_chip ){
-+		cur_chip = (void *)OPL;
-+		/* rhythm slots */
-+		SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1];
-+		SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2];
-+		SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1];
-+		SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2];
-+	}
-+	for( i=0; i < length ; i++ )
-+	{
-+		int lt;
-+
-+		output[0] = 0;
-+
-+		advance_lfo(OPL);
-+
-+		/* FM part */
-+		OPL_CALC_CH(&OPL->P_CH[0]);
-+		OPL_CALC_CH(&OPL->P_CH[1]);
-+		OPL_CALC_CH(&OPL->P_CH[2]);
-+		OPL_CALC_CH(&OPL->P_CH[3]);
-+		OPL_CALC_CH(&OPL->P_CH[4]);
-+		OPL_CALC_CH(&OPL->P_CH[5]);
-+
-+		if(!rhythm)
-+		{
-+			OPL_CALC_CH(&OPL->P_CH[6]);
-+			OPL_CALC_CH(&OPL->P_CH[7]);
-+			OPL_CALC_CH(&OPL->P_CH[8]);
-+		}
-+		else		/* Rhythm part */
-+		{
-+			OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
-+		}
-+
-+		lt = output[0];
-+
-+		lt >>= FINAL_SH;
-+
-+		/* limit check */
-+		lt = limit( lt , MAXOUT, MINOUT );
-+
-+		#ifdef SAVE_SAMPLE
-+			SAVE_ALL_CHANNELS
-+		#endif
-+
-+		/* store to sound buffer */
-+		buf[i] = lt;
-+
-+		advance(OPL);
-+	}
-+
-+}
-+#endif /* BUILD_YM3526 */
-+
-+
-+
-+
-+#if BUILD_Y8950
-+
-+static FM_OPL *OPL_Y8950[MAX_OPL_CHIPS];	/* array of pointers to the Y8950's */
-+static int Y8950NumChips = 0;				/* number of chips */
-+
-+int Y8950Init(int num, int clock, int rate)
-+{
-+	int i;
-+
-+	if (Y8950NumChips)
-+		return -1;	/* duplicate init. */
-+
-+	Y8950NumChips = num;
-+
-+	for (i = 0;i < Y8950NumChips; i++)
-+	{
-+		/* emulator create */
-+		OPL_Y8950[i] = OPLCreate(OPL_TYPE_Y8950,clock,rate);
-+		if(OPL_Y8950[i] == NULL)
-+		{
-+			/* it's really bad - we run out of memeory */
-+			Y8950NumChips = 0;
-+			return -1;
-+		}
-+	}
-+
-+	return 0;
-+}
-+
-+void Y8950Shutdown(void)
-+{
-+	int i;
-+
-+	for (i = 0;i < Y8950NumChips; i++)
-+	{
-+		/* emulator shutdown */
-+		OPLDestroy(OPL_Y8950[i]);
-+		OPL_Y8950[i] = NULL;
-+	}
-+	Y8950NumChips = 0;
-+}
-+void Y8950ResetChip(int which)
-+{
-+	OPLResetChip(OPL_Y8950[which]);
-+}
-+
-+int Y8950Write(int which, int a, int v)
-+{
-+	return OPLWrite(OPL_Y8950[which], a, v);
-+}
-+
-+unsigned char Y8950Read(int which, int a)
-+{
-+	return OPLRead(OPL_Y8950[which], a);
-+}
-+int Y8950TimerOver(int which, int c)
-+{
-+	return OPLTimerOver(OPL_Y8950[which], c);
-+}
-+
-+void Y8950SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset)
-+{
-+	OPLSetTimerHandler(OPL_Y8950[which], TimerHandler, channelOffset);
-+}
-+void Y8950SetIRQHandler(int which,OPL_IRQHANDLER IRQHandler,int param)
-+{
-+	OPLSetIRQHandler(OPL_Y8950[which], IRQHandler, param);
-+}
-+void Y8950SetUpdateHandler(int which,OPL_UPDATEHANDLER UpdateHandler,int param)
-+{
-+	OPLSetUpdateHandler(OPL_Y8950[which], UpdateHandler, param);
-+}
-+
-+void Y8950SetDeltaTMemory(int which, void * deltat_rom, int deltat_rom_size )
-+{
-+	FM_OPL		*OPL = OPL_Y8950[which];
-+	OPL->deltat->memory = (UINT8 *)(deltat_rom);
-+	OPL->deltat->memory_size = deltat_rom_size;
-+}
-+
-+/*
-+** Generate samples for one of the Y8950's
-+**
-+** 'which' is the virtual Y8950 number
-+** '*buffer' is the output buffer pointer
-+** 'length' is the number of samples that should be generated
-+*/
-+void Y8950UpdateOne(int which, INT16 *buffer, int length)
-+{
-+	int i;
-+	FM_OPL		*OPL = OPL_Y8950[which];
-+	UINT8		rhythm  = OPL->rhythm&0x20;
-+	YM_DELTAT	*DELTAT = OPL->deltat;
-+	OPLSAMPLE	*buf    = buffer;
-+
-+	/* setup DELTA-T unit */
-+	YM_DELTAT_DECODE_PRESET(DELTAT);
-+
-+	if( (void *)OPL != cur_chip ){
-+		cur_chip = (void *)OPL;
-+		/* rhythm slots */
-+		SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1];
-+		SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2];
-+		SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1];
-+		SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2];
-+
-+	}
-+	for( i=0; i < length ; i++ )
-+	{
-+		int lt;
-+
-+		output[0] = 0;
-+		output_deltat[0] = 0;
-+
-+		advance_lfo(OPL);
-+
-+		/* deltaT ADPCM */
-+		if( DELTAT->portstate )
-+			YM_DELTAT_ADPCM_CALC(DELTAT);
-+
-+		/* FM part */
-+		OPL_CALC_CH(&OPL->P_CH[0]);
-+		OPL_CALC_CH(&OPL->P_CH[1]);
-+		OPL_CALC_CH(&OPL->P_CH[2]);
-+		OPL_CALC_CH(&OPL->P_CH[3]);
-+		OPL_CALC_CH(&OPL->P_CH[4]);
-+		OPL_CALC_CH(&OPL->P_CH[5]);
-+
-+		if(!rhythm)
-+		{
-+			OPL_CALC_CH(&OPL->P_CH[6]);
-+			OPL_CALC_CH(&OPL->P_CH[7]);
-+			OPL_CALC_CH(&OPL->P_CH[8]);
-+		}
-+		else		/* Rhythm part */
-+		{
-+			OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
-+		}
-+
-+		lt = output[0] + (output_deltat[0]>>11);
-+
-+		lt >>= FINAL_SH;
-+
-+		/* limit check */
-+		lt = limit( lt , MAXOUT, MINOUT );
-+
-+		#ifdef SAVE_SAMPLE
-+			SAVE_ALL_CHANNELS
-+		#endif
-+
-+		/* store to sound buffer */
-+		buf[i] = lt;
-+
-+		advance(OPL);
-+	}
-+
-+	/* deltaT START flag */
-+	if( !DELTAT->portstate )
-+		OPL->status &= 0xfe;
-+
-+	if( DELTAT->eos ) //AT: set bit 4 of OPL status register on EOS
-+	{
-+		DELTAT->eos = 0;
-+		OPL->status |= 0x10;
-+	}
-+}
-+
-+void Y8950SetPortHandler(int which,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param)
-+{
-+	FM_OPL		*OPL = OPL_Y8950[which];
-+	OPL->porthandler_w = PortHandler_w;
-+	OPL->porthandler_r = PortHandler_r;
-+	OPL->port_param = param;
-+}
-+
-+void Y8950SetKeyboardHandler(int which,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param)
-+{
-+	FM_OPL		*OPL = OPL_Y8950[which];
-+	OPL->keyboardhandler_w = KeyboardHandler_w;
-+	OPL->keyboardhandler_r = KeyboardHandler_r;
-+	OPL->keyboard_param = param;
-+}
-+
-+#endif
-+
-diff --git a/src/player/fmopl.h b/src/player/fmopl.h
-index c269236..a341254 100644
---- a/src/player/fmopl.h
-+++ b/src/player/fmopl.h
-@@ -1,10 +1,16 @@
- #ifndef __FMOPL_H_
- #define __FMOPL_H_
- 
-+#define HAS_YM3812	1
-+
-+/* --- select emulation chips --- */
- #define BUILD_YM3812 (HAS_YM3812)
- #define BUILD_YM3526 (HAS_YM3526)
- #define BUILD_Y8950  (HAS_Y8950)
- 
-+/* select output bits size of output : 8 or 16 */
-+#define OPL_SAMPLE_BITS 16
-+
- /* compiler dependence */
- #ifndef OSD_CPU_H
- #define OSD_CPU_H
-@@ -16,10 +22,11 @@ typedef signed short	INT16;   /* signed 16bit   */
- typedef signed int	INT32;   /* signed 32bit   */
- #endif
- 
--typedef  INT32	FMSAMPLE; /* to use with xmp */
--
--#if BUILD_Y8950
--#include "ymdeltat.h"
-+#if (OPL_SAMPLE_BITS==16)
-+typedef INT16 OPLSAMPLE;
-+#endif
-+#if (OPL_SAMPLE_BITS==8)
-+typedef INT8 OPLSAMPLE;
- #endif
- 
- typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
-@@ -28,135 +35,78 @@ 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 */
--
--/* ---------- 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       */
-+
-+#if BUILD_YM3812
-+
-+int  YM3812Init(int num, int clock, int rate);
-+void YM3812Shutdown(void);
-+void YM3812ResetChip(int which);
-+int  YM3812Write(int which, int a, int v);
-+unsigned char YM3812Read(int which, int a);
-+int  YM3812TimerOver(int which, int c);
-+void YM3812UpdateOne(int which, INT32 *buffer, int length, int vl, int vr, int st);
-+
-+void YM3812SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset);
-+void YM3812SetIRQHandler(int which, OPL_IRQHANDLER IRQHandler, int param);
-+void YM3812SetUpdateHandler(int which, OPL_UPDATEHANDLER UpdateHandler, int param);
-+
- #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 - changed to use with xmp */
--void YM3812UpdateOne(FM_OPL *OPL, FMSAMPLE *bk, int len, int st, int vl, int vr);
-+#if BUILD_YM3526
-+
-+/*
-+** Initialize YM3526 emulator(s).
-+**
-+** 'num' is the number of virtual YM3526's to allocate
-+** 'clock' is the chip clock in Hz
-+** 'rate' is sampling rate
-+*/
-+int  YM3526Init(int num, int clock, int rate);
-+/* shutdown the YM3526 emulators*/
-+void YM3526Shutdown(void);
-+void YM3526ResetChip(int which);
-+int  YM3526Write(int which, int a, int v);
-+unsigned char YM3526Read(int which, int a);
-+int  YM3526TimerOver(int which, int c);
-+/*
-+** Generate samples for one of the YM3526's
-+**
-+** 'which' is the virtual YM3526 number
-+** '*buffer' is the output buffer pointer
-+** 'length' is the number of samples that should be generated
-+*/
-+void YM3526UpdateOne(int which, INT16 *buffer, int length);
-+
-+void YM3526SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset);
-+void YM3526SetIRQHandler(int which, OPL_IRQHANDLER IRQHandler, int param);
-+void YM3526SetUpdateHandler(int which, OPL_UPDATEHANDLER UpdateHandler, int param);
-+
-+#endif
-+
-+
-+#if BUILD_Y8950
-+
-+#include "ymdeltat.h"
-+
-+/* Y8950 port handlers */
-+void Y8950SetPortHandler(int which, OPL_PORTHANDLER_W PortHandler_w, OPL_PORTHANDLER_R PortHandler_r, int param);
-+void Y8950SetKeyboardHandler(int which, OPL_PORTHANDLER_W KeyboardHandler_w, OPL_PORTHANDLER_R KeyboardHandler_r, int param);
-+void Y8950SetDeltaTMemory(int which, void * deltat_rom, int deltat_rom_size );
-+
-+int  Y8950Init (int num, int clock, int rate);
-+void Y8950Shutdown (void);
-+void Y8950ResetChip (int which);
-+int  Y8950Write (int which, int a, int v);
-+unsigned char Y8950Read (int which, int a);
-+int  Y8950TimerOver (int which, int c);
-+void Y8950UpdateOne (int which, INT16 *buffer, int length);
-+
-+void Y8950SetTimerHandler (int which, OPL_TIMERHANDLER TimerHandler, int channelOffset);
-+void Y8950SetIRQHandler (int which, OPL_IRQHANDLER IRQHandler, int param);
-+void Y8950SetUpdateHandler (int which, OPL_UPDATEHANDLER UpdateHandler, int param);
-+
-+#endif
- 
--void Y8950UpdateOne(FM_OPL *OPL, void *buffer, int length);
- 
- #endif
-diff --git a/src/player/synth.c b/src/player/synth.c
-index 321394a..deab39e 100644
---- a/src/player/synth.c
-+++ b/src/player/synth.c
-@@ -15,21 +15,6 @@
- #include "driver.h"
- #include "fmopl.h"
- 
--/* Use the old GPL-compatible version */
--#define USE_OLD_FMOPL
--
--#ifdef USE_OLD_FMOPL
--static FM_OPL *ym3812;
--#define YM3812ResetChip(which)	OPLResetChip(ym3812)
--#define YM3812Write(which,a,v)	OPLWrite(ym3812, a, v)
--#define YM3812Read(which,a)	OPLRead(ym3812, a)
--#define YM3812Init(num,clock,rate) \
--		((ym3812 = OPLCreate(OPL_TYPE_IO, clock, rate)) != NULL)
--#define YM3812Shutdown()	OPLDestroy(ym3812)
--#define YM3812UpdateOne(which,tmp_bk,count,vl,vr,stereo) \
--		YM3812UpdateOne(ym3812, tmp_bk, count, vl, vr, stereo)
--#endif
--
- /*
-  * ------+-----------------------------------+-----------------------+
-  * offset|       SBI data format             |    YM3812 base port
-@@ -280,10 +265,11 @@ int synth_deinit ()
- }
- 
- 
--void synth_mixer (int *tmp_bk, int count, int vl, int vr, int stereo)
-+void synth_mixer (int* tmp_bk, int count, int vl, int vr, int stereo)
- {
-     if (!tmp_bk)
- 	return;
- 
--    YM3812UpdateOne(0, tmp_bk, count, vl, vr, stereo);
-+    YM3812UpdateOne (0, tmp_bk, count, vl, vr, stereo);
- }
-+
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/xmp.git/commitdiff/60f1a56f47df0e76e28f5d38f8191c8411922c5d



More information about the pld-cvs-commit mailing list