- Renamed opl_stereo to opl_fullpan, since DOSBox's core is emulating an OPL3, which is stereo

but only supports three pan positions and not the full 127 MIDI pan positions.
- Added opl_core cvar to select emulator core. 0 is MAME and 1 is DOSBox.
- Added DOSBox's LGPL OPL core, distantly related to one adlibemu.c written by Ken Silverman
  (not to be confused with the ancient MAME-derived and GPL-licensed core also found in DOSBox).
  I believe this corresponds to their "compat" emulator, but I'm not sure.

SVN r3946 (trunk)
This commit is contained in:
Randy Heit 2012-11-08 05:45:58 +00:00
parent 12ee3271c4
commit 3ec387ac32
14 changed files with 114 additions and 68 deletions

View file

@ -566,11 +566,6 @@ else( NO_ASM )
ADD_ASM_FILE( asm_ia32 tmap2 ) ADD_ASM_FILE( asm_ia32 tmap2 )
ADD_ASM_FILE( asm_ia32 tmap3 ) ADD_ASM_FILE( asm_ia32 tmap3 )
endif( X64 ) endif( X64 )
if( WIN32 )
if( NOT X64 )
ADD_ASM_FILE( win32 wrappers )
endif( NOT X64 )
endif( WIN32 )
endif( NO_ASM ) endif( NO_ASM )
add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.h add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.h
@ -817,6 +812,7 @@ add_executable( zdoom WIN32
oplsynth/music_opldumper_mididevice.cpp oplsynth/music_opldumper_mididevice.cpp
oplsynth/music_opl_mididevice.cpp oplsynth/music_opl_mididevice.cpp
oplsynth/opl_mus_player.cpp oplsynth/opl_mus_player.cpp
oplsynth/dosbox/opl.cpp
resourcefiles/ancientzip.cpp resourcefiles/ancientzip.cpp
resourcefiles/file_7z.cpp resourcefiles/file_7z.cpp
resourcefiles/file_grp.cpp resourcefiles/file_grp.cpp

View file

@ -100,7 +100,7 @@ Revision History:
#include <stdarg.h> #include <stdarg.h>
#include <math.h> #include <math.h>
//#include "driver.h" /* use M.A.M.E. */ //#include "driver.h" /* use M.A.M.E. */
#include "fmopl.h" #include "opl.h"
/* compiler dependence */ /* compiler dependence */
#ifndef OSD_CPU_H #ifndef OSD_CPU_H
@ -1576,17 +1576,9 @@ public:
} }
/* YM3812 I/O interface */ /* YM3812 I/O interface */
int Write(int a, int v) void WriteReg(int reg, int v)
{ {
if( !(a&1) ) OPLWriteReg(&Chip, reg & 0xff, v);
{ /* address port */
Chip.address = v & 0xff;
}
else
{ /* data port */
OPLWriteReg(&Chip, Chip.address, v);
}
return Chip.status>>7;
} }
void Reset() void Reset()
@ -1676,7 +1668,7 @@ public:
} }
}; };
OPLEmul *YM3812Init(bool stereo) OPLEmul *YM3812Create(bool stereo)
{ {
/* emulator create */ /* emulator create */
return new YM3812(stereo); return new YM3812(stereo);

View file

@ -1,11 +0,0 @@
#ifndef __FMOPL_H_
#define __FMOPL_H_
#include "opl.h"
// Multiplying OPL_SAMPLE_RATE by ADLIB_CLOCK_MUL gives the number
// Adlib clocks per second, as used by the RAWADATA file format.
OPLEmul *YM3812Init(bool stereo);
#endif

View file

@ -42,7 +42,10 @@
#include <conio.h> #include <conio.h>
#endif #endif
#include "muslib.h" #include "muslib.h"
#include "fmopl.h" #include "opl.h"
#include "c_cvars.h"
EXTERN_CVAR(Int, opl_core)
OPLio::~OPLio() OPLio::~OPLio()
{ {
@ -58,8 +61,12 @@ void OPLio::WriteDelay(int ticks)
void OPLio::OPLwriteReg(int which, uint reg, uchar data) void OPLio::OPLwriteReg(int which, uint reg, uchar data)
{ {
chips[which]->Write(0, reg); if (IsOPL3)
chips[which]->Write(1, data); {
reg |= (which & 1) << 8;
which >>= 1;
}
chips[which]->WriteReg(reg, data);
} }
/* /*
@ -249,10 +256,11 @@ void OPLio::OPLwritePan(uint channel, struct OPL2instrument *instr, int pan)
OPLwriteValue(0xC0, channel, instr->feedback | bits); OPLwriteValue(0xC0, channel, instr->feedback | bits);
// Set real panning if we're using emulated chips. // Set real panning if we're using emulated chips.
int which = channel / OPL2CHANNELS; int chanper = IsOPL3 ? OPL3CHANNELS : OPL2CHANNELS;
int which = channel / chanper;
if (chips[which] != NULL) if (chips[which] != NULL)
{ {
chips[which]->SetPanning(channel % OPL2CHANNELS, pan + 64); chips[which]->SetPanning(channel % chanper, pan + 64);
} }
} }
} }
@ -300,15 +308,20 @@ void OPLio::OPLshutup(void)
/* /*
* Initialize hardware upon startup * Initialize hardware upon startup
*/ */
int OPLio::OPLinit(uint numchips, bool stereo) int OPLio::OPLinit(uint numchips, bool stereo, bool initopl3)
{ {
assert(numchips >= 1 && numchips <= countof(chips)); assert(numchips >= 1 && numchips <= countof(chips));
uint i; uint i;
IsOPL3 = (opl_core == 1);
memset(chips, 0, sizeof(chips)); memset(chips, 0, sizeof(chips));
if (IsOPL3)
{
numchips = (numchips + 1) >> 1;
}
for (i = 0; i < numchips; ++i) for (i = 0; i < numchips; ++i)
{ {
OPLEmul *chip = YM3812Init(stereo); OPLEmul *chip = IsOPL3 ? DBOPLCreate(stereo) : YM3812Create(stereo);
if (chip == NULL) if (chip == NULL)
{ {
break; break;
@ -316,18 +329,24 @@ int OPLio::OPLinit(uint numchips, bool stereo)
chips[i] = chip; chips[i] = chip;
} }
NumChips = i; NumChips = i;
OPLchannels = OPL2CHANNELS * i; OPLchannels = i * (IsOPL3 ? OPL3CHANNELS : OPL2CHANNELS);
OPLwriteInitState(); OPLwriteInitState(initopl3);
return i; return i;
} }
void OPLio::OPLwriteInitState() void OPLio::OPLwriteInitState(bool initopl3)
{ {
for (uint i = 0; i < OPLchannels / OPL2CHANNELS; ++i) for (uint i = 0; i < NumChips; ++i)
{ {
OPLwriteReg (i, 0x01, 0x20); // enable Waveform Select int chip = i << (int)IsOPL3;
OPLwriteReg (i, 0x0B, 0x40); // turn off CSW mode if (IsOPL3 && initopl3)
OPLwriteReg (i, 0xBD, 0x00); // set vibrato/tremolo depth to low, set melodic mode {
OPLwriteReg(chip, 0x105, 0x01); // enable YMF262/OPL3 mode
OPLwriteReg(chip, 0x104, 0x00); // disable 4-operator mode
}
OPLwriteReg(chip, 0x01, 0x20); // enable Waveform Select
OPLwriteReg(chip, 0x0B, 0x40); // turn off CSW mode
OPLwriteReg(chip, 0xBD, 0x00); // set vibrato/tremolo depth to low, set melodic mode
} }
OPLshutup(); OPLshutup();
} }

View file

@ -41,7 +41,7 @@
#include "m_swap.h" #include "m_swap.h"
#include "w_wad.h" #include "w_wad.h"
#include "v_text.h" #include "v_text.h"
#include "fmopl.h" #include "opl.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -66,7 +66,7 @@ EXTERN_CVAR(Int, opl_numchips)
// PUBLIC DATA DEFINITIONS ------------------------------------------------- // PUBLIC DATA DEFINITIONS -------------------------------------------------
CVAR(Bool, opl_stereo, true, CVAR_ARCHIVE); CVAR(Bool, opl_fullpan, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
// CODE -------------------------------------------------------------------- // CODE --------------------------------------------------------------------
@ -78,7 +78,7 @@ CVAR(Bool, opl_stereo, true, CVAR_ARCHIVE);
OPLMIDIDevice::OPLMIDIDevice() OPLMIDIDevice::OPLMIDIDevice()
{ {
IsStereo = opl_stereo; FullPan = opl_fullpan;
FWadLump data = Wads.OpenLumpName("GENMIDI"); FWadLump data = Wads.OpenLumpName("GENMIDI");
OPLloadBank(data); OPLloadBank(data);
SampleRate = (int)OPL_SAMPLE_RATE; SampleRate = (int)OPL_SAMPLE_RATE;
@ -94,11 +94,11 @@ OPLMIDIDevice::OPLMIDIDevice()
int OPLMIDIDevice::Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata) int OPLMIDIDevice::Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata)
{ {
if (io == NULL || 0 == (NumChips = io->OPLinit(opl_numchips, IsStereo))) if (io == NULL || 0 == (NumChips = io->OPLinit(opl_numchips, FullPan, true)))
{ {
return 1; return 1;
} }
int ret = OpenStream(14, IsStereo ? 0 : SoundStream::Mono, callback, userdata); int ret = OpenStream(14, (FullPan || io->IsOPL3) ? 0 : SoundStream::Mono, callback, userdata);
if (ret == 0) if (ret == 0)
{ {
OPLstopMusic(); OPLstopMusic();

View file

@ -39,7 +39,7 @@
#include "doomdef.h" #include "doomdef.h"
#include "m_swap.h" #include "m_swap.h"
#include "w_wad.h" #include "w_wad.h"
#include "fmopl.h" #include "opl.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -188,7 +188,7 @@ int DiskWriterIO::OPLinit(uint numchips, bool dontcare)
CurIntTime = 0; CurIntTime = 0;
CurChip = 0; CurChip = 0;
OPLchannels = OPL2CHANNELS * numchips; OPLchannels = OPL2CHANNELS * numchips;
OPLwriteInitState(); OPLwriteInitState(false);
return numchips; return numchips;
} }

View file

@ -176,9 +176,9 @@ struct OPLio {
void OPLwritePan(uint channel, struct OPL2instrument *instr, int pan); void OPLwritePan(uint channel, struct OPL2instrument *instr, int pan);
void OPLwriteInstrument(uint channel, struct OPL2instrument *instr); void OPLwriteInstrument(uint channel, struct OPL2instrument *instr);
void OPLshutup(void); void OPLshutup(void);
void OPLwriteInitState(); void OPLwriteInitState(bool initopl3);
virtual int OPLinit(uint numchips, bool stereo=false); virtual int OPLinit(uint numchips, bool stereo=false, bool initopl3=false);
virtual void OPLdeinit(void); virtual void OPLdeinit(void);
virtual void OPLwriteReg(int which, uint reg, uchar data); virtual void OPLwriteReg(int which, uint reg, uchar data);
virtual void SetClockRate(double samples_per_tick); virtual void SetClockRate(double samples_per_tick);
@ -187,6 +187,7 @@ struct OPLio {
class OPLEmul *chips[MAXOPL2CHIPS]; class OPLEmul *chips[MAXOPL2CHIPS];
uint OPLchannels; uint OPLchannels;
uint NumChips; uint NumChips;
bool IsOPL3;
}; };
struct DiskWriterIO : public OPLio struct DiskWriterIO : public OPLio

View file

@ -12,10 +12,13 @@ public:
virtual ~OPLEmul() {} virtual ~OPLEmul() {}
virtual void Reset() = 0; virtual void Reset() = 0;
virtual int Write(int a, int v) = 0; virtual void WriteReg(int reg, int v) = 0;
virtual void Update(float *buffer, int length) = 0; virtual void Update(float *buffer, int length) = 0;
virtual void SetPanning(int c, int pan) = 0; virtual void SetPanning(int c, int pan) = 0;
virtual FString GetVoiceString() { return FString(); } virtual FString GetVoiceString() { return FString(); }
}; };
OPLEmul *YM3812Create(bool stereo);
OPLEmul *DBOPLCreate(bool stereo);
#endif #endif

View file

@ -7,7 +7,7 @@
#include "opl_mus_player.h" #include "opl_mus_player.h"
#include "doomtype.h" #include "doomtype.h"
#include "fmopl.h" #include "opl.h"
#include "w_wad.h" #include "w_wad.h"
#include "templates.h" #include "templates.h"
#include "c_cvars.h" #include "c_cvars.h"
@ -25,7 +25,7 @@ OPLmusicBlock::OPLmusicBlock()
LastOffset = 0; LastOffset = 0;
NumChips = MIN(*opl_numchips, 2); NumChips = MIN(*opl_numchips, 2);
Looping = false; Looping = false;
IsStereo = false; FullPan = false;
io = NULL; io = NULL;
io = new OPLio; io = new OPLio;
} }
@ -39,7 +39,7 @@ void OPLmusicBlock::ResetChips ()
{ {
ChipAccess.Enter(); ChipAccess.Enter();
io->OPLdeinit (); io->OPLdeinit ();
NumChips = io->OPLinit(MIN(*opl_numchips, 2), IsStereo); NumChips = io->OPLinit(MIN(*opl_numchips, 2), FullPan);
ChipAccess.Leave(); ChipAccess.Leave();
} }
@ -223,7 +223,8 @@ void OPLmusicFile::Restart ()
bool OPLmusicBlock::ServiceStream (void *buff, int numbytes) bool OPLmusicBlock::ServiceStream (void *buff, int numbytes)
{ {
float *samples1 = (float *)buff; float *samples1 = (float *)buff;
int numsamples = numbytes / (sizeof(float) << int(IsStereo)); int stereoshift = (int)(FullPan | io->IsOPL3);
int numsamples = numbytes / (sizeof(float) << stereoshift);
bool prevEnded = false; bool prevEnded = false;
bool res = true; bool res = true;
@ -243,12 +244,12 @@ bool OPLmusicBlock::ServiceStream (void *buff, int numbytes)
{ {
io->chips[i]->Update(samples1, samplesleft); io->chips[i]->Update(samples1, samplesleft);
} }
OffsetSamples(samples1, samplesleft << int(IsStereo)); OffsetSamples(samples1, samplesleft << stereoshift);
assert(NextTickIn == ticky); assert(NextTickIn == ticky);
NextTickIn -= samplesleft; NextTickIn -= samplesleft;
assert (NextTickIn >= 0); assert (NextTickIn >= 0);
numsamples -= samplesleft; numsamples -= samplesleft;
samples1 += samplesleft << int(IsStereo); samples1 += samplesleft << stereoshift;
} }
if (NextTickIn < 1) if (NextTickIn < 1)
@ -265,7 +266,7 @@ bool OPLmusicBlock::ServiceStream (void *buff, int numbytes)
{ {
io->chips[i]->Update(samples1, samplesleft); io->chips[i]->Update(samples1, samplesleft);
} }
OffsetSamples(samples1, numsamples << int(IsStereo)); OffsetSamples(samples1, numsamples << stereoshift);
} }
res = false; res = false;
break; break;

View file

@ -21,7 +21,7 @@ protected:
int NumChips; int NumChips;
bool Looping; bool Looping;
double LastOffset; double LastOffset;
bool IsStereo; bool FullPan;
FCriticalSection ChipAccess; FCriticalSection ChipAccess;
}; };

View file

@ -19,6 +19,8 @@ CUSTOM_CVAR (Int, opl_numchips, 2, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
} }
} }
CVAR(Int, opl_core, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
OPLMUSSong::OPLMUSSong (FILE *file, BYTE *musiccache, int len) OPLMUSSong::OPLMUSSong (FILE *file, BYTE *musiccache, int len)
{ {
int samples = int(OPL_SAMPLE_RATE / 14); int samples = int(OPL_SAMPLE_RATE / 14);
@ -26,7 +28,7 @@ OPLMUSSong::OPLMUSSong (FILE *file, BYTE *musiccache, int len)
Music = new OPLmusicFile (file, musiccache, len); Music = new OPLmusicFile (file, musiccache, len);
m_Stream = GSnd->CreateStream (FillStream, samples*4, m_Stream = GSnd->CreateStream (FillStream, samples*4,
SoundStream::Mono | SoundStream::Float, int(OPL_SAMPLE_RATE), this); (opl_core != 1 ? SoundStream::Mono : 0) | SoundStream::Float, int(OPL_SAMPLE_RATE), this);
if (m_Stream == NULL) if (m_Stream == NULL)
{ {
Printf (PRINT_BOLD, "Could not create music stream.\n"); Printf (PRINT_BOLD, "Could not create music stream.\n");

View file

@ -1400,6 +1400,12 @@ OptionValue GusMemory
4, "1024K" 4, "1024K"
} }
OptionValue OplCores
{
0, "MAME"
1, "DOSBox"
}
OptionMenu AdvSoundOptions OptionMenu AdvSoundOptions
{ {
Title "ADVANCED SOUND OPTIONS" Title "ADVANCED SOUND OPTIONS"
@ -1409,7 +1415,8 @@ OptionMenu AdvSoundOptions
StaticText " " StaticText " "
StaticText "OPL Synthesis", 1 StaticText "OPL Synthesis", 1
Slider "Number of emulated OPL chips", "opl_numchips", 1, 8, 1, 0 Slider "Number of emulated OPL chips", "opl_numchips", 1, 8, 1, 0
Option "Support MIDI stero panning", "opl_stereo", "OnOff" Option "Full MIDI stereo panning", "opl_fullpan", "OnOff"
Option "OPL Emulator Core", "opl_core", "OplCores"
StaticText " " StaticText " "
StaticText "GUS Emulation", 1 StaticText "GUS Emulation", 1
Slider "MIDI voices", "midi_voices", 16, 256, 4, 0 Slider "MIDI voices", "midi_voices", 16, 256, 4, 0

View file

@ -2602,10 +2602,6 @@
/> />
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\src\oplsynth\fmopl.h"
>
</File>
<File <File
RelativePath=".\src\oplsynth\mlopl.cpp" RelativePath=".\src\oplsynth\mlopl.cpp"
> >
@ -2630,6 +2626,46 @@
RelativePath=".\src\oplsynth\opl_mus_player.h" RelativePath=".\src\oplsynth\opl_mus_player.h"
> >
</File> </File>
<Filter
Name="DOSBox"
>
<File
RelativePath=".\src\oplsynth\dosbox\opl.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\oplsynth\dosbox\opl.h"
>
</File>
</Filter>
</Filter> </Filter>
<Filter <Filter
Name="Timidity" Name="Timidity"

View file

@ -115,7 +115,7 @@ set(ZLIB_SRCS
trees.c trees.c
uncompr.c uncompr.c
zutil.c zutil.c
win32/zlib1.rc # win32/zlib1.rc
) )
# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION # parse the full version number from zlib.h and include in ZLIB_FULL_VERSION