Browse Source

Try new dosbox opl

louyihua 8 years ago
parent
commit
d5cab5ce4e
12 changed files with 1904 additions and 12 deletions
  1. 48 0
      adplug/dbemuopl.h
  2. 1517 0
      adplug/dbopl.cpp
  3. 290 0
      adplug/dbopl.h
  4. 2 2
      adplug/dosbox_opl.h
  5. 13 4
      adplug/emuopl.cpp
  6. 2 1
      adplug/emuopl.h
  7. 2 0
      global.c
  8. 1 0
      global.h
  9. 12 2
      rixplay.cpp
  10. 5 0
      sdlpal.vcxproj
  11. 12 0
      sdlpal.vcxproj.filters
  12. 0 3
      sound.c

+ 48 - 0
adplug/dbemuopl.h

@@ -0,0 +1,48 @@
+/*
+* Adplug - Replayer for many OPL2/OPL3 audio file formats.
+* Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*
+* demuopl.h - Emulated OPL using DOSBOX's emulator, by Wei Mingzhi
+*             <whistler_wmz@users.sf.net>.
+*/
+
+#ifndef H_ADPLUG_DBEMUOPL
+#define H_ADPLUG_DBEMUOPL
+
+#include "opl.h"
+#include "dbopl.h"
+
+class CDBemuopl : public Copl
+{
+public:
+	CDBemuopl(int rate, bool bit16, bool usestereo);
+	~CDBemuopl();
+
+	void update(short *buf, int samples);
+
+	// template methods
+	void write(int reg, int val);
+
+	void init();
+
+protected:
+	DBOPL::Handler handler;
+	int rate;
+	bool use16bit, stereo;
+};
+
+#endif

File diff suppressed because it is too large
+ 1517 - 0
adplug/dbopl.cpp


+ 290 - 0
adplug/dbopl.h

@@ -0,0 +1,290 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+//#include "adlib.h"
+//#include "dosbox.h"
+
+/*
+define Bits, Bitu, Bit32s, Bit32u, Bit16s, Bit16u, Bit8s, Bit8u here
+*/
+
+#if defined(_MSC_VER) && _MSC_VER <= 1600
+#include <windows.h>
+#define uintptr_t ULONG_PTR
+#define intptr_t LONG_PTR
+#define uint32_t DWORD
+#define int32_t INT
+#define uint16_t WORD
+#define int16_t SHORT
+#define uint8_t BYTE
+#define int8_t CHAR
+#else
+#include <stdint.h>
+#endif
+
+typedef uintptr_t	Bitu;
+typedef intptr_t	Bits;
+typedef uint32_t	Bit32u;
+typedef int32_t		Bit32s;
+typedef uint16_t	Bit16u;
+typedef int16_t		Bit16s;
+typedef uint8_t		Bit8u;
+typedef int8_t		Bit8s;
+
+/*
+define attribution that inlines/forces inlining of a function (optional)
+*/
+#define OPL_INLINE inline
+
+#define GCC_UNLIKELY(x) (x)
+
+//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume
+#define WAVE_HANDLER	10
+//Use a logarithmic wavetable with an exponential table for volume
+#define WAVE_TABLELOG	11
+//Use a linear wavetable with a multiply table for volume
+#define WAVE_TABLEMUL	12
+
+//Select the type of wave generator routine
+#define DBOPL_WAVE WAVE_TABLEMUL
+
+namespace DBOPL {
+
+	struct Chip;
+	struct Operator;
+	struct Channel;
+
+#if (DBOPL_WAVE == WAVE_HANDLER)
+	typedef Bits(DB_FASTCALL *WaveHandler) (Bitu i, Bitu volume);
+#endif
+
+	typedef Bits(DBOPL::Operator::*VolumeHandler) ();
+	typedef Channel* (DBOPL::Channel::*SynthHandler) (Chip* chip, Bit32u samples, Bit32s* output);
+
+	//Different synth modes that can generate blocks of data
+	typedef enum {
+		sm2AM,
+		sm2FM,
+		sm3AM,
+		sm3FM,
+		sm4Start,
+		sm3FMFM,
+		sm3AMFM,
+		sm3FMAM,
+		sm3AMAM,
+		sm6Start,
+		sm2Percussion,
+		sm3Percussion,
+	} SynthMode;
+
+	//Shifts for the values contained in chandata variable
+	enum {
+		SHIFT_KSLBASE = 16,
+		SHIFT_KEYCODE = 24,
+	};
+
+	struct Operator {
+	public:
+		//Masks for operator 20 values
+		enum {
+			MASK_KSR = 0x10,
+			MASK_SUSTAIN = 0x20,
+			MASK_VIBRATO = 0x40,
+			MASK_TREMOLO = 0x80,
+		};
+
+		typedef enum {
+			OFF,
+			RELEASE,
+			SUSTAIN,
+			DECAY,
+			ATTACK,
+		} State;
+
+		VolumeHandler volHandler;
+
+#if (DBOPL_WAVE == WAVE_HANDLER)
+		WaveHandler waveHandler;	//Routine that generate a wave 
+#else
+		Bit16s* waveBase;
+		Bit32u waveMask;
+		Bit32u waveStart;
+#endif
+		Bit32u waveIndex;			//WAVE_BITS shifted counter of the frequency index
+		Bit32u waveAdd;				//The base frequency without vibrato
+		Bit32u waveCurrent;			//waveAdd + vibratao
+
+		Bit32u chanData;			//Frequency/octave and derived data coming from whatever channel controls this
+		Bit32u freqMul;				//Scale channel frequency with this, TODO maybe remove?
+		Bit32u vibrato;				//Scaled up vibrato strength
+		Bit32s sustainLevel;		//When stopping at sustain level stop here
+		Bit32s totalLevel;			//totalLevel is added to every generated volume
+		Bit32u currentLevel;		//totalLevel + tremolo
+		Bit32s volume;				//The currently active volume
+
+		Bit32u attackAdd;			//Timers for the different states of the envelope
+		Bit32u decayAdd;
+		Bit32u releaseAdd;
+		Bit32u rateIndex;			//Current position of the evenlope
+
+		Bit8u rateZero;				//Bits for the different states of the envelope having no changes
+		Bit8u keyOn;				//Bitmask of different values that can generate keyon
+		//Registers, also used to check for changes
+		Bit8u reg20, reg40, reg60, reg80, regE0;
+		//Active part of the envelope we're in
+		Bit8u state;
+		//0xff when tremolo is enabled
+		Bit8u tremoloMask;
+		//Strength of the vibrato
+		Bit8u vibStrength;
+		//Keep track of the calculated KSR so we can check for changes
+		Bit8u ksr;
+	private:
+		void SetState(Bit8u s);
+		void UpdateAttack(const Chip* chip);
+		void UpdateRelease(const Chip* chip);
+		void UpdateDecay(const Chip* chip);
+	public:
+		void UpdateAttenuation();
+		void UpdateRates(const Chip* chip);
+		void UpdateFrequency();
+
+		void Write20(const Chip* chip, Bit8u val);
+		void Write40(const Chip* chip, Bit8u val);
+		void Write60(const Chip* chip, Bit8u val);
+		void Write80(const Chip* chip, Bit8u val);
+		void WriteE0(const Chip* chip, Bit8u val);
+
+		bool Silent() const;
+		void Prepare(const Chip* chip);
+
+		void KeyOn(Bit8u mask);
+		void KeyOff(Bit8u mask);
+
+		template< State state>
+		Bits TemplateVolume();
+
+		Bit32s RateForward(Bit32u add);
+		Bitu ForwardWave();
+		Bitu ForwardVolume();
+
+		Bits GetSample(Bits modulation);
+		Bits GetWave(Bitu index, Bitu vol);
+	public:
+		Operator();
+	};
+
+	struct Channel {
+		Operator op[2];
+		inline Operator* Op(Bitu index) {
+			return &((this + (index >> 1))->op[index & 1]);
+		}
+		SynthHandler synthHandler;
+		Bit32u chanData;		//Frequency/octave and derived values
+		Bit32s old[2];			//Old data for feedback
+
+		Bit8u feedback;			//Feedback shift
+		Bit8u regB0;			//Register values to check for changes
+		Bit8u regC0;
+		//This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel
+		Bit8u fourMask;
+		Bit8s maskLeft;		//Sign extended values for both channel's panning
+		Bit8s maskRight;
+
+		//Forward the channel data to the operators of the channel
+		void SetChanData(const Chip* chip, Bit32u data);
+		//Change in the chandata, check for new values and if we have to forward to operators
+		void UpdateFrequency(const Chip* chip, Bit8u fourOp);
+		void WriteA0(const Chip* chip, Bit8u val);
+		void WriteB0(const Chip* chip, Bit8u val);
+		void WriteC0(const Chip* chip, Bit8u val);
+		void ResetC0(const Chip* chip);
+
+		//call this for the first channel
+		template< bool opl3Mode >
+		void GeneratePercussion(Chip* chip, Bit32s* output);
+
+		//Generate blocks of data in specific modes
+		template<SynthMode mode>
+		Channel* BlockTemplate(Chip* chip, Bit32u samples, Bit32s* output);
+		Channel();
+	};
+
+	struct Chip {
+		//This is used as the base counter for vibrato and tremolo
+		Bit32u lfoCounter;
+		Bit32u lfoAdd;
+
+
+		Bit32u noiseCounter;
+		Bit32u noiseAdd;
+		Bit32u noiseValue;
+
+		//Frequency scales for the different multiplications
+		Bit32u freqMul[16];
+		//Rates for decay and release for rate of this chip
+		Bit32u linearRates[76];
+		//Best match attack rates for the rate of this chip
+		Bit32u attackRates[76];
+
+		//18 channels with 2 operators each
+		Channel chan[18];
+
+		Bit8u reg104;
+		Bit8u reg08;
+		Bit8u reg04;
+		Bit8u regBD;
+		Bit8u vibratoIndex;
+		Bit8u tremoloIndex;
+		Bit8s vibratoSign;
+		Bit8u vibratoShift;
+		Bit8u tremoloValue;
+		Bit8u vibratoStrength;
+		Bit8u tremoloStrength;
+		//Mask for allowed wave forms
+		Bit8u waveFormMask;
+		//0 or -1 when enabled
+		Bit8s opl3Active;
+
+		//Return the maximum amount of samples before and LFO change
+		Bit32u ForwardLFO(Bit32u samples);
+		Bit32u ForwardNoise();
+
+		void WriteBD(Bit8u val);
+		void WriteReg(Bit32u reg, Bit8u val);
+
+		Bit32u WriteAddr(Bit32u port, Bit8u val);
+
+		void GenerateBlock2(Bitu samples, Bit32s* output);
+		void GenerateBlock3(Bitu samples, Bit32s* output);
+
+		//void Generate( Bit32u samples );
+		void Setup(Bit32u r);
+
+		Chip();
+	};
+
+	struct Handler {
+		DBOPL::Chip chip;
+		Bit32s buffer[512 * 2];
+		Bit32u WriteAddr(Bit32u port, Bit8u val);
+		void WriteReg(Bit32u addr, Bit8u val);
+		void Generate(Bit16s* buf, Bitu samples);
+		void Init(Bitu rate);
+	};
+};		//Namespace

+ 2 - 2
adplug/dosbox_opl.h

@@ -33,8 +33,8 @@
 
 #if defined(_MSC_VER) && _MSC_VER <= 1600
 #include <windows.h>
-#define uintptr_t ULONG
-#define intptr_t LONG
+#define uintptr_t ULONG_PTR
+#define intptr_t LONG_PTR
 #define uint32_t DWORD
 #define int32_t INT
 #define uint16_t WORD

+ 13 - 4
adplug/emuopl.cpp

@@ -21,10 +21,15 @@
 
 #include "emuopl.h"
 
+#ifndef NULL
+#define NULL     0
+#endif
+
 CEmuopl::CEmuopl(int rate, bool bit16, bool usestereo)
-      : use16bit(bit16), stereo(usestereo), mixbufSamples(0) {
-   opl[0] = OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
-   opl[1] = OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
+      : use16bit(bit16), stereo(usestereo), mixbufSamples(0), rate(rate) {
+   //opl[0] = OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
+   //opl[1] = OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
+	opl[0] = opl[1] = NULL;
 
    currType = TYPE_OPL2;
 
@@ -136,7 +141,11 @@ void CEmuopl::write(int reg, int val) {
 }
 
 void CEmuopl::init() {
-   OPLResetChip(opl[0]);
+	if (opl[0]) OPLDestroy(opl[0]);
+	if (opl[1]) OPLDestroy(opl[1]);
+	opl[0] = OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
+	opl[1] = OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
+	OPLResetChip(opl[0]);
    OPLResetChip(opl[1]);
    currChip = 0;
 }

+ 2 - 1
adplug/emuopl.h

@@ -22,6 +22,7 @@
 #ifndef H_ADPLUG_EMUOPL
 #define H_ADPLUG_EMUOPL
 
+
 #include "opl.h"
 extern "C" {
 #include "fmopl.h"
@@ -42,7 +43,7 @@ private:
    bool		use16bit, stereo;
    FM_OPL	*opl[2];				// OPL2 emulator data
    short		*mixbuf0, *mixbuf1;
-   int		mixbufSamples;
+   int		mixbufSamples, rate;
 };
 
 #endif

+ 2 - 0
global.c

@@ -203,6 +203,8 @@ PAL_InitGlobals(
 					   sscanf(ptr, "%31s", opl_type);
 					   if (SDL_strcasecmp(opl_type, "DOSBOX") == 0)
 						   eOPLType = OPL_DOSBOX;
+					   else if (SDL_strcasecmp(opl_type, "DOSBOXOLD") == 0)
+						   eOPLType = OPL_DOSBOX_OLD;
 					   else if (PAL_HAS_MAME && SDL_strcasecmp(opl_type, "MAME") == 0)
 						   eOPLType = OPL_MAME;
 				   }

+ 1 - 0
global.h

@@ -554,6 +554,7 @@ typedef enum tagMUSICTYPE
 
 typedef enum tagOPLTYPE
 {
+	OPL_DOSBOX_OLD,
 	OPL_DOSBOX,
 	OPL_MAME
 } OPLTYPE, *LPOPLTYPE;

+ 12 - 2
rixplay.cpp

@@ -24,6 +24,7 @@
 #include "resampler.h"
 #include "adplug/opl.h"
 #include "adplug/demuopl.h"
+#include "adplug/dbemuopl.h"
 #if PAL_HAS_MAME
 #include "adplug/emuopl.h"
 #endif
@@ -359,12 +360,18 @@ RIX_Init(
 	{
 		switch (gpGlobals->eOPLType)
 		{
-		case OPL_DOSBOX:
+		case OPL_DOSBOX_OLD:
 			pRixPlayer->opl = new CSurroundopl(
 				new CDemuopl(gpGlobals->iOPLSampleRate, true, false),
 				new CDemuopl(gpGlobals->iOPLSampleRate, true, false),
 				true, gpGlobals->iOPLSampleRate, gpGlobals->dSurroundOPLOffset);
 			break;
+		case OPL_DOSBOX:
+			pRixPlayer->opl = new CSurroundopl(
+				new CDBemuopl(gpGlobals->iOPLSampleRate, true, false),
+				new CDBemuopl(gpGlobals->iOPLSampleRate, true, false),
+				true, gpGlobals->iOPLSampleRate, gpGlobals->dSurroundOPLOffset);
+			break;
 		case OPL_MAME:
 			pRixPlayer->opl = new CSurroundopl(
 				new CEmuopl(gpGlobals->iOPLSampleRate, true, false),
@@ -377,9 +384,12 @@ RIX_Init(
 	{
 		switch (gpGlobals->eOPLType)
 		{
-		case OPL_DOSBOX:
+		case OPL_DOSBOX_OLD:
 			pRixPlayer->opl = new CDemuopl(gpGlobals->iOPLSampleRate, true, gpGlobals->iAudioChannels == 2);
 			break;
+		case OPL_DOSBOX:
+			pRixPlayer->opl = new CDBemuopl(gpGlobals->iOPLSampleRate, true, gpGlobals->iAudioChannels == 2);
+			break;
 		case OPL_MAME:
 			pRixPlayer->opl = new CEmuopl(gpGlobals->iOPLSampleRate, true, gpGlobals->iAudioChannels == 2);
 			break;

+ 5 - 0
sdlpal.vcxproj

@@ -60,6 +60,7 @@
       <WarningLevel>Level3</WarningLevel>
       <SuppressStartupBanner>true</SuppressStartupBanner>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <Optimization>Disabled</Optimization>
     </ClCompile>
     <ResourceCompile>
       <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -118,6 +119,8 @@
   </ItemDefinitionGroup>
   <ItemGroup>
     <ClCompile Include="adplug\adlibemu.c" />
+    <ClCompile Include="adplug\dbemuopl.cpp" />
+    <ClCompile Include="adplug\dbopl.cpp" />
     <ClCompile Include="adplug\demuopl.cpp" />
     <ClCompile Include="battle.c">
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@@ -455,6 +458,8 @@
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="adplug\adlibemu.h" />
+    <ClInclude Include="adplug\dbemuopl.h" />
+    <ClInclude Include="adplug\dbopl.h" />
     <ClInclude Include="adplug\kemuopl.h" />
     <ClInclude Include="ascii.h" />
     <ClInclude Include="battle.h" />

+ 12 - 0
sdlpal.vcxproj.filters

@@ -293,6 +293,12 @@
     <ClCompile Include="mp3play.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="adplug\dbopl.cpp">
+      <Filter>adplug</Filter>
+    </ClCompile>
+    <ClCompile Include="adplug\dbemuopl.cpp">
+      <Filter>adplug</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="ascii.h">
@@ -622,6 +628,12 @@
     <ClInclude Include="players.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="adplug\dbopl.h">
+      <Filter>adplug</Filter>
+    </ClInclude>
+    <ClInclude Include="adplug\dbemuopl.h">
+      <Filter>adplug</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="sdlpal.ico">

+ 0 - 3
sound.c

@@ -576,9 +576,6 @@ SOUND_OpenAudio(
 --*/
 {
    SDL_AudioSpec spec;
-   char *mkfs[2];
-   FNLoadSoundData func[2];
-   int i;
 
    if (gSndOpened)
    {