Commit 4697f92c663e3c4dbdc803d006b21707ca460658

Authored by Georg Hopp
1 parent 27cb6d81

update dosbox

1 -# Copyright 1999-2015 Gentoo Foundation  
2 -# Distributed under the terms of the GNU General Public License v2  
3 -# $Id$  
4 -  
5 -EAPI=5  
6 -inherit eutils games  
7 -  
8 -DESCRIPTION="DOS emulator"  
9 -HOMEPAGE="http://dosbox.sourceforge.net/"  
10 -SRC_URI="mirror://sourceforge/dosbox/${P}.tar.gz"  
11 -  
12 -LICENSE="GPL-2"  
13 -SLOT="0"  
14 -KEYWORDS="amd64 ~arm ppc ppc64 ~sparc x86"  
15 -IUSE="alsa debug hardened opengl"  
16 -  
17 -DEPEND="alsa? ( media-libs/alsa-lib )  
18 - opengl? ( virtual/glu virtual/opengl )  
19 - debug? ( sys-libs/ncurses:0 )  
20 - media-libs/libpng:0  
21 - media-libs/libsdl[joystick,video,X]  
22 - media-libs/sdl-net  
23 - media-libs/sdl-sound"  
24 -RDEPEND=${DEPEND}  
25 -  
26 -src_prepare() {  
27 - epatch "${FILESDIR}"/${P}-gcc46.patch  
28 - epatch "${FILESDIR}"/map-mouse-buttons.diff  
29 -}  
30 -  
31 -src_configure() {  
32 - #$(use_enable debug debug=heavy) \  
33 - egamesconf \  
34 - $(use_enable alsa alsa-midi) \  
35 - $(use_enable !hardened dynamic-core) \  
36 - $(use_enable !hardened dynamic-x86) \  
37 - $(use_enable debug) \  
38 - $(use_enable opengl)  
39 -}  
40 -  
41 -src_install() {  
42 - default  
43 - make_desktop_entry dosbox DOSBox /usr/share/pixmaps/dosbox.ico  
44 - doicon src/dosbox.ico  
45 - prepgamesdirs  
46 -}  
1 -# Copyright 1999-2016 Gentoo Foundation  
2 -# Distributed under the terms of the GNU General Public License v2  
3 -# $Id$  
4 -  
5 -EAPI=6  
6 -inherit autotools eutils  
7 -  
8 -PATCH=3989  
9 -DESCRIPTION="DOS emulator"  
10 -HOMEPAGE="http://dosbox.sourceforge.net/"  
11 -SRC_URI="mirror://gentoo/dosbox-code-0-${PATCH}-dosbox-trunk.zip"  
12 -  
13 -LICENSE="GPL-2"  
14 -SLOT="0"  
15 -KEYWORDS="amd64 ~arm ~ppc ~ppc64 ~sparc x86"  
16 -IUSE="alsa debug hardened opengl"  
17 -  
18 -RDEPEND="alsa? ( media-libs/alsa-lib )  
19 - opengl? ( virtual/glu virtual/opengl )  
20 - debug? ( sys-libs/ncurses:0 )  
21 - media-libs/libpng:0  
22 - media-libs/libsdl[joystick,video,X]  
23 - media-libs/sdl-net  
24 - media-libs/sdl-sound"  
25 -DEPEND="${RDEPEND}  
26 - app-arch/unzip"  
27 -  
28 -S=${WORKDIR}/${PN}-code-0-${PATCH}-dosbox-trunk  
29 -  
30 -PATCHES=(  
31 -"${FILESDIR}"/dosbox-0.74-gcc46.patch  
32 -"${FILESDIR}"/map-mouse-buttons.patch  
33 -)  
34 -  
35 -src_prepare() {  
36 - default  
37 - eautoreconf  
38 -}  
39 -  
40 -src_configure() {  
41 - econf \  
42 - $(use_enable alsa alsa-midi) \  
43 - $(use_enable !hardened dynamic-core) \  
44 - $(use_enable !hardened dynamic-x86) \  
45 - $(use_enable debug) \  
46 - $(use_enable opengl)  
47 -}  
48 -  
49 -src_install() {  
50 - default  
51 - make_desktop_entry dosbox DOSBox /usr/share/pixmaps/dosbox.ico  
52 - doicon src/dosbox.ico  
53 -}  
1 -# Copyright 1999-2016 Gentoo Foundation 1 +# Copyright 1999-2020 Gentoo Authors
2 # Distributed under the terms of the GNU General Public License v2 2 # Distributed under the terms of the GNU General Public License v2
3 -# $Id$  
4 3
5 -EAPI=6  
6 -inherit autotools eutils flag-o-matic 4 +EAPI=7
7 5
8 -PATCH=3989  
9 -GLIDE_PATCH=3722fc563b737d2d7933df6a771651c2154e6f7b 6 +inherit autotools desktop flag-o-matic
10 7
11 -DESCRIPTION="DOS emulator"  
12 -HOMEPAGE="http://dosbox.sourceforge.net/"  
13 -SRC_URI="mirror://gentoo/dosbox-code-0-${PATCH}-dosbox-trunk.zip  
14 - glide? ( https://raw.githubusercontent.com/voyageur/openglide/${GLIDE_PATCH}/platform/dosbox/dosbox_glide.diff -> dosbox_glide-${GLIDE_PATCH}.diff )" 8 +case "${PV}" in
  9 +9999)
  10 + MY_P=${PN}
  11 + ESVN_REPO_URI="https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk"
  12 + inherit subversion
  13 + ;;
  14 +*_pre*)
  15 + MY_PV=0-r${PV#*_pre}
  16 + MY_P=${PN}-code-${MY_PV}-${PN}-trunk
  17 + SRC_URI="https://sourceforge.net/code-snapshots/svn/d/do/dosbox/code-0/${MY_P}.zip"
  18 + BDEPEND="app-arch/unzip"
  19 + ;;
  20 +*)
  21 + MY_PV=$(ver_rs 2 -)
  22 + MY_P=${PN}-${MY_PV}
  23 + SRC_URI="mirror://sourceforge/dosbox/${MY_P}.tar.gz"
  24 + ;;
  25 +esac
  26 +
  27 +GLIDE_PATCH=841e1071597b64ead14dd08c25a03206b2d1d1b6
  28 +SRC_URI+=" glide? ( https://raw.githubusercontent.com/voyageur/openglide/${GLIDE_PATCH}/platform/dosbox/dosbox_glide.diff -> dosbox_glide-${GLIDE_PATCH}.diff )"
15 29
  30 +DESCRIPTION="DOS emulator"
  31 +HOMEPAGE="https://www.dosbox.com/"
16 LICENSE="GPL-2" 32 LICENSE="GPL-2"
17 SLOT="0" 33 SLOT="0"
18 -KEYWORDS="~amd64 ~arm ~ppc ~ppc64 ~sparc ~x86"  
19 -IUSE="alsa debug glide hardened opengl" 34 +KEYWORDS="~amd64 ~arm ~ppc ~ppc64 ~x86"
  35 +IUSE="alsa +core-inline debug glide hardened opengl X mouse"
20 36
21 RDEPEND="alsa? ( media-libs/alsa-lib ) 37 RDEPEND="alsa? ( media-libs/alsa-lib )
22 glide? ( media-libs/openglide ) 38 glide? ( media-libs/openglide )
23 opengl? ( virtual/glu virtual/opengl ) 39 opengl? ( virtual/glu virtual/opengl )
24 - debug? ( sys-libs/ncurses:0 )  
25 - media-libs/libpng:0  
26 - media-libs/libsdl[joystick,video,X] 40 + debug? ( sys-libs/ncurses:0= )
  41 + X? ( x11-libs/libX11 )
  42 + media-libs/libpng:0=
  43 + media-libs/libsdl[joystick,opengl?,video,X?]
27 media-libs/sdl-net 44 media-libs/sdl-net
28 - media-libs/sdl-sound"  
29 -DEPEND="${RDEPEND}  
30 - app-arch/unzip" 45 + media-libs/sdl-sound
  46 + sys-libs/zlib"
  47 +
  48 +DEPEND="${RDEPEND}"
31 49
32 -S=${WORKDIR}/${PN}-code-0-${PATCH}-dosbox-trunk 50 +S="${WORKDIR}/${MY_P}"
33 51
34 PATCHES=( 52 PATCHES=(
35 -"${FILESDIR}"/dosbox-0.74-gcc46.patch  
36 -"${FILESDIR}"/map-mouse-buttons.patch 53 + "${FILESDIR}"/${PN}-0.74-ncurses.patch
37 ) 54 )
38 55
39 src_prepare() { 56 src_prepare() {
  57 + eapply -p1 "${FILESDIR}"/mt32-patch.diff
40 use glide && eapply "${DISTDIR}"/dosbox_glide-${GLIDE_PATCH}.diff 58 use glide && eapply "${DISTDIR}"/dosbox_glide-${GLIDE_PATCH}.diff
  59 + use mouse && eapply -p0 "${FILESDIR}"/map-mouse-buttons.diff
41 default 60 default
42 eautoreconf 61 eautoreconf
43 } 62 }
@@ -45,8 +64,10 @@ src_prepare() { @@ -45,8 +64,10 @@ src_prepare() {
45 src_configure() { 64 src_configure() {
46 use glide && append-cppflags -I"${EPREFIX}"/usr/include/openglide 65 use glide && append-cppflags -I"${EPREFIX}"/usr/include/openglide
47 66
  67 + ac_cv_lib_X11_main=$(usex X yes no) \
48 econf \ 68 econf \
49 $(use_enable alsa alsa-midi) \ 69 $(use_enable alsa alsa-midi) \
  70 + $(use_enable core-inline) \
50 $(use_enable !hardened dynamic-core) \ 71 $(use_enable !hardened dynamic-core) \
51 $(use_enable !hardened dynamic-x86) \ 72 $(use_enable !hardened dynamic-x86) \
52 $(use_enable debug) \ 73 $(use_enable debug) \
1 ---- a/include/dos_inc.h 2011-04-28 08:46:04.505011354 +0200  
2 -+++ b/include/dos_inc.h 2011-04-28 08:46:27.104408178 +0200  
3 -@@ -21,6 +21,7 @@  
4 - #ifndef DOSBOX_DOS_INC_H  
5 - #define DOSBOX_DOS_INC_H  
6 -  
7 -+#include <cstddef>  
8 - #ifndef DOSBOX_DOS_SYSTEM_H  
9 - #include "dos_system.h"  
10 - #endif  
  1 +https://sourceforge.net/p/dosbox/patches/286/
  2 +
  3 +--- a/configure.ac 2019-11-12 17:55:51.000000000 +0000
  4 ++++ b/configure.ac 2020-01-02 21:26:27.551856431 +0000
  5 +@@ -235,36 +235,38 @@
  6 + #Features to enable/disable
  7 + AH_TEMPLATE(C_DEBUG,[Define to 1 to enable internal debugger, requires libcurses])
  8 + AH_TEMPLATE(C_HEAVY_DEBUG,[Define to 1 to enable heavy debugging, also have to enable C_DEBUG])
  9 +-AC_ARG_ENABLE(debug,AC_HELP_STRING([--enable-debug],[Enable debug mode]),[
  10 +- AC_CHECK_HEADER(curses.h,have_curses_h=yes,)
  11 +- AC_CHECK_LIB(curses, initscr, have_curses_lib=yes, , )
  12 +- AC_CHECK_LIB(ncurses, initscr, have_ncurses_lib=yes, , )
  13 +- AC_CHECK_LIB(pdcurses, initscr, have_pdcurses_lib=yes, , )
  14 ++AC_ARG_ENABLE(debug,AC_HELP_STRING([--enable-debug],[Enable debug mode]),,enable_debug=no)
  15 ++AC_MSG_CHECKING(whether debug will be enabled)
  16 ++
  17 ++if test x$enable_debug = xno; then
  18 ++ AC_MSG_RESULT(no)
  19 ++else
  20 ++ AC_MSG_RESULT(yes)
  21 +
  22 +- if test x$enable_debug = xno; then
  23 +- AC_MSG_RESULT([Debugger not enabled])
  24 +- elif test x$have_ncurses_lib = xyes -a x$have_curses_h = xyes ; then
  25 +- LIBS="$LIBS -lncurses"
  26 +- AC_DEFINE(C_DEBUG,1)
  27 +- if test x$enable_debug = xheavy ; then
  28 +- AC_DEFINE(C_HEAVY_DEBUG,1)
  29 +- fi
  30 +- elif test x$have_curses_lib = xyes -a x$have_curses_h = xyes ; then
  31 +- LIBS="$LIBS -lcurses"
  32 +- AC_DEFINE(C_DEBUG,1)
  33 +- if test x$enable_debug = xheavy ; then
  34 +- AC_DEFINE(C_HEAVY_DEBUG,1)
  35 +- fi
  36 +- elif test x$have_pdcurses_lib = xyes -a x$have_curses_h = xyes ; then
  37 +- LIBS="$LIBS -lpdcurses"
  38 +- AC_DEFINE(C_DEBUG,1)
  39 +- if test x$enable_debug = xheavy ; then
  40 +- AC_DEFINE(C_HEAVY_DEBUG,1)
  41 +- fi
  42 +- else
  43 +- AC_MSG_ERROR([Can't find curses, which is required for debug mode])
  44 +- fi
  45 +-],)
  46 ++ PKG_CHECK_MODULES(NCURSES, ncurses, [
  47 ++ LIBS="$LIBS $NCURSES_LIBS"; CFLAGS="$CFLAGS $NCURSES_CFLAGS"
  48 ++ ], [
  49 ++ AC_CHECK_HEADER(curses.h,have_curses_h=yes,)
  50 ++ AC_CHECK_LIB(curses, initscr, have_curses_lib=yes, , )
  51 ++ AC_CHECK_LIB(ncurses, initscr, have_ncurses_lib=yes, , )
  52 ++ AC_CHECK_LIB(pdcurses, initscr, have_pdcurses_lib=yes, , )
  53 ++
  54 ++ if test x$have_ncurses_lib = xyes -a x$have_curses_h = xyes ; then
  55 ++ LIBS="$LIBS -lncurses"
  56 ++ elif test x$have_curses_lib = xyes -a x$have_curses_h = xyes ; then
  57 ++ LIBS="$LIBS -lcurses"
  58 ++ elif test x$have_pdcurses_lib = xyes -a x$have_curses_h = xyes ; then
  59 ++ LIBS="$LIBS -lpdcurses"
  60 ++ else
  61 ++ AC_MSG_ERROR([Can't find curses, which is required for debug mode])
  62 ++ fi
  63 ++ ])
  64 ++
  65 ++ AC_DEFINE(C_DEBUG,1)
  66 ++ if test x$enable_debug = xheavy; then
  67 ++ AC_DEFINE(C_HEAVY_DEBUG,1)
  68 ++ fi
  69 ++fi
  70 +
  71 + AH_TEMPLATE(C_CORE_INLINE,[Define to 1 to use inlined memory functions in cpu core])
  72 + AC_ARG_ENABLE(core-inline,AC_HELP_STRING([--disable-core-inline],[Disable inlined memory handling in CPU Core]),,enable_core_inline=yes)
1 -diff -Naur a/src/gui/sdl_mapper.cpp b/src/gui/sdl_mapper.cpp  
2 ---- a/src/gui/sdl_mapper.cpp 2015-01-10 14:16:22.000000000 +0100  
3 -+++ b/src/gui/sdl_mapper.cpp 2016-10-31 21:36:44.509231014 +0100 1 +Index: src/gui/sdl_mapper.cpp
  2 +===================================================================
  3 +--- src/gui/sdl_mapper.cpp (revision 3914)
  4 ++++ src/gui/sdl_mapper.cpp (working copy)
4 @@ -32,6 +32,7 @@ 5 @@ -32,6 +32,7 @@
5 #include "dosbox.h" 6 #include "dosbox.h"
6 #include "video.h" 7 #include "video.h"
  1 +diff --git a/src/Makefile.am b/src/Makefile.am
  2 +index a4029e83..3869353a 100644
  3 +--- a/src/Makefile.am
  4 ++++ b/src/Makefile.am
  5 +@@ -18,4 +18,4 @@ dosbox_LDADD = cpu/libcpu.a debug/libdebug.a dos/libdos.a fpu/libfpu.a hardware
  6 +
  7 + EXTRA_DIST = winres.rc dosbox.ico
  8 +
  9 +-
  10 ++LIBS += -lmt32emu
  11 +diff --git a/src/dosbox.cpp b/src/dosbox.cpp
  12 +index 8ae1e4df..9864ae7e 100644
  13 +--- a/src/dosbox.cpp
  14 ++++ b/src/dosbox.cpp
  15 +@@ -561,7 +561,7 @@ void DOSBOX_Init(void) {
  16 +
  17 + const char* mputypes[] = { "intelligent", "uart", "none",0};
  18 + // FIXME: add some way to offer the actually available choices.
  19 +- const char *devices[] = { "default", "win32", "alsa", "oss", "coreaudio", "coremidi","none", 0};
  20 ++ const char *devices[] = { "default", "win32", "alsa", "oss", "coreaudio", "coremidi", "mt32", "none", 0};
  21 + Pstring = secprop->Add_string("mpu401",Property::Changeable::WhenIdle,"intelligent");
  22 + Pstring->Set_values(mputypes);
  23 + Pstring->Set_help("Type of MPU-401 to emulate.");
  24 +@@ -577,6 +577,8 @@ void DOSBOX_Init(void) {
  25 + "In that case, add 'delaysysex', for example: midiconfig=2 delaysysex\n"
  26 + "See the README/Manual for more details.");
  27 +
  28 ++#include "mt32options.h"
  29 ++
  30 + #if C_DEBUG
  31 + secprop=control->AddSection_prop("debug",&DEBUG_Init);
  32 + #endif
  33 +diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am
  34 +index 84b22b14..b8bc1b04 100644
  35 +--- a/src/gui/Makefile.am
  36 ++++ b/src/gui/Makefile.am
  37 +@@ -7,5 +7,5 @@ libgui_a_SOURCES = sdlmain.cpp sdl_mapper.cpp dosbox_logo.h \
  38 + render_templates_sai.h render_templates_hq.h \
  39 + render_templates_hq2x.h render_templates_hq3x.h \
  40 + midi.cpp midi_win32.h midi_oss.h midi_coreaudio.h midi_alsa.h \
  41 +- midi_coremidi.h sdl_gui.cpp dosbox_splash.h
  42 ++ midi_coremidi.h midi_mt32.h midi_mt32.cpp sdl_gui.cpp dosbox_splash.h
  43 +
  44 +diff --git a/src/gui/midi.cpp b/src/gui/midi.cpp
  45 +index 28b65f46..adcfe2d5 100644
  46 +--- a/src/gui/midi.cpp
  47 ++++ b/src/gui/midi.cpp
  48 +@@ -97,6 +97,9 @@ MidiHandler Midi_none;
  49 +
  50 + #endif
  51 +
  52 ++#include "midi_mt32.h"
  53 ++static MidiHandler_mt32 &Midi_mt32 = MidiHandler_mt32::GetInstance();
  54 ++
  55 + DB_Midi midi;
  56 +
  57 + void MIDI_RawOutByte(Bit8u data) {
  58 +diff --git a/src/gui/midi_mt32.cpp b/src/gui/midi_mt32.cpp
  59 +new file mode 100644
  60 +index 00000000..b036547a
  61 +--- /dev/null
  62 ++++ b/src/gui/midi_mt32.cpp
  63 +@@ -0,0 +1,299 @@
  64 ++#include <SDL_thread.h>
  65 ++#include <SDL_endian.h>
  66 ++#include "control.h"
  67 ++
  68 ++#ifndef DOSBOX_MIDI_H
  69 ++#include "midi.h"
  70 ++#endif
  71 ++
  72 ++#include "midi_mt32.h"
  73 ++
  74 ++static const Bitu MILLIS_PER_SECOND = 1000;
  75 ++
  76 ++MidiHandler_mt32 &MidiHandler_mt32::GetInstance() {
  77 ++ static MidiHandler_mt32 midiHandler_mt32;
  78 ++ return midiHandler_mt32;
  79 ++}
  80 ++
  81 ++const char *MidiHandler_mt32::GetName(void) {
  82 ++ return "mt32";
  83 ++}
  84 ++
  85 ++bool MidiHandler_mt32::Open(const char *conf) {
  86 ++ service = new MT32Emu::Service();
  87 ++ Bit32u version = service->getLibraryVersionInt();
  88 ++ if (version < 0x020100) {
  89 ++ delete service;
  90 ++ service = NULL;
  91 ++ LOG_MSG("MT32: libmt32emu version is too old: %s", service->getLibraryVersionString());
  92 ++ return false;
  93 ++ }
  94 ++ service->createContext(getReportHandlerInterface(), this);
  95 ++ mt32emu_return_code rc;
  96 ++
  97 ++ Section_prop *section = static_cast<Section_prop *>(control->GetSection("midi"));
  98 ++ const char *romDir = section->Get_string("mt32.romdir");
  99 ++ if (romDir == NULL) romDir = "./"; // Paranoid NULL-check, should never happen
  100 ++ size_t romDirLen = strlen(romDir);
  101 ++ bool addPathSeparator = false;
  102 ++ if (romDirLen < 1) {
  103 ++ romDir = "./";
  104 ++ } else if (4080 < romDirLen) {
  105 ++ LOG_MSG("MT32: mt32.romdir is too long, using the current dir.");
  106 ++ romDir = "./";
  107 ++ } else {
  108 ++ char lastChar = romDir[strlen(romDir) - 1];
  109 ++ addPathSeparator = lastChar != '/' && lastChar != '\\';
  110 ++ }
  111 ++
  112 ++ char pathName[4096];
  113 ++
  114 ++ makeROMPathName(pathName, romDir, "CM32L_CONTROL.ROM", addPathSeparator);
  115 ++ if (MT32EMU_RC_ADDED_CONTROL_ROM != service->addROMFile(pathName)) {
  116 ++ makeROMPathName(pathName, romDir, "MT32_CONTROL.ROM", addPathSeparator);
  117 ++ if (MT32EMU_RC_ADDED_CONTROL_ROM != service->addROMFile(pathName)) {
  118 ++ delete service;
  119 ++ service = NULL;
  120 ++ LOG_MSG("MT32: Control ROM file not found");
  121 ++ return false;
  122 ++ }
  123 ++ }
  124 ++ makeROMPathName(pathName, romDir, "CM32L_PCM.ROM", addPathSeparator);
  125 ++ if (MT32EMU_RC_ADDED_PCM_ROM != service->addROMFile(pathName)) {
  126 ++ makeROMPathName(pathName, romDir, "MT32_PCM.ROM", addPathSeparator);
  127 ++ if (MT32EMU_RC_ADDED_PCM_ROM != service->addROMFile(pathName)) {
  128 ++ delete service;
  129 ++ service = NULL;
  130 ++ LOG_MSG("MT32: PCM ROM file not found");
  131 ++ return false;
  132 ++ }
  133 ++ }
  134 ++
  135 ++ service->setPartialCount(Bit32u(section->Get_int("mt32.partials")));
  136 ++ service->setAnalogOutputMode((MT32Emu::AnalogOutputMode)section->Get_int("mt32.analog"));
  137 ++ int sampleRate = section->Get_int("mt32.rate");
  138 ++ service->setStereoOutputSampleRate(sampleRate);
  139 ++ service->setSamplerateConversionQuality((MT32Emu::SamplerateConversionQuality)section->Get_int("mt32.src.quality"));
  140 ++
  141 ++ if (MT32EMU_RC_OK != (rc = service->openSynth())) {
  142 ++ delete service;
  143 ++ service = NULL;
  144 ++ LOG_MSG("MT32: Error initialising emulation: %i", rc);
  145 ++ return false;
  146 ++ }
  147 ++
  148 ++ if (strcmp(section->Get_string("mt32.reverb.mode"), "auto") != 0) {
  149 ++ Bit8u reverbsysex[] = {0x10, 0x00, 0x01, 0x00, 0x05, 0x03};
  150 ++ reverbsysex[3] = (Bit8u)atoi(section->Get_string("mt32.reverb.mode"));
  151 ++ reverbsysex[4] = (Bit8u)section->Get_int("mt32.reverb.time");
  152 ++ reverbsysex[5] = (Bit8u)section->Get_int("mt32.reverb.level");
  153 ++ service->writeSysex(16, reverbsysex, 6);
  154 ++ service->setReverbOverridden(true);
  155 ++ }
  156 ++
  157 ++ service->setDACInputMode((MT32Emu::DACInputMode)section->Get_int("mt32.dac"));
  158 ++
  159 ++ service->setReversedStereoEnabled(section->Get_bool("mt32.reverse.stereo"));
  160 ++ service->setNiceAmpRampEnabled(section->Get_bool("mt32.niceampramp"));
  161 ++ noise = section->Get_bool("mt32.verbose");
  162 ++ renderInThread = section->Get_bool("mt32.thread");
  163 ++
  164 ++ if (noise) LOG_MSG("MT32: Set maximum number of partials %d", service->getPartialCount());
  165 ++
  166 ++ if (noise) LOG_MSG("MT32: Adding mixer channel at sample rate %d", sampleRate);
  167 ++ chan = MIXER_AddChannel(mixerCallBack, sampleRate, "MT32");
  168 ++
  169 ++ if (renderInThread) {
  170 ++ stopProcessing = false;
  171 ++ playPos = 0;
  172 ++ int chunkSize = section->Get_int("mt32.chunk");
  173 ++ minimumRenderFrames = (chunkSize * sampleRate) / MILLIS_PER_SECOND;
  174 ++ int latency = section->Get_int("mt32.prebuffer");
  175 ++ if (latency <= chunkSize) {
  176 ++ latency = 2 * chunkSize;
  177 ++ LOG_MSG("MT32: chunk length must be less than prebuffer length, prebuffer length reset to %i ms.", latency);
  178 ++ }
  179 ++ framesPerAudioBuffer = (latency * sampleRate) / MILLIS_PER_SECOND;
  180 ++ audioBufferSize = framesPerAudioBuffer << 1;
  181 ++ audioBuffer = new Bit16s[audioBufferSize];
  182 ++ service->renderBit16s(audioBuffer, framesPerAudioBuffer - 1);
  183 ++ renderPos = (framesPerAudioBuffer - 1) << 1;
  184 ++ playedBuffers = 1;
  185 ++ lock = SDL_CreateMutex();
  186 ++ framesInBufferChanged = SDL_CreateCond();
  187 ++ thread = SDL_CreateThread(processingThread, NULL);
  188 ++ }
  189 ++ chan->Enable(true);
  190 ++
  191 ++ open = true;
  192 ++ return true;
  193 ++}
  194 ++
  195 ++void MidiHandler_mt32::Close(void) {
  196 ++ if (!open) return;
  197 ++ chan->Enable(false);
  198 ++ if (renderInThread) {
  199 ++ stopProcessing = true;
  200 ++ SDL_LockMutex(lock);
  201 ++ SDL_CondSignal(framesInBufferChanged);
  202 ++ SDL_UnlockMutex(lock);
  203 ++ SDL_WaitThread(thread, NULL);
  204 ++ thread = NULL;
  205 ++ SDL_DestroyMutex(lock);
  206 ++ lock = NULL;
  207 ++ SDL_DestroyCond(framesInBufferChanged);
  208 ++ framesInBufferChanged = NULL;
  209 ++ delete[] audioBuffer;
  210 ++ audioBuffer = NULL;
  211 ++ }
  212 ++ MIXER_DelChannel(chan);
  213 ++ chan = NULL;
  214 ++ service->closeSynth();
  215 ++ delete service;
  216 ++ service = NULL;
  217 ++ open = false;
  218 ++}
  219 ++
  220 ++void MidiHandler_mt32::PlayMsg(Bit8u *msg) {
  221 ++ if (renderInThread) {
  222 ++ service->playMsgAt(SDL_SwapLE32(*(Bit32u *)msg), getMidiEventTimestamp());
  223 ++ } else {
  224 ++ service->playMsg(SDL_SwapLE32(*(Bit32u *)msg));
  225 ++ }
  226 ++}
  227 ++
  228 ++void MidiHandler_mt32::PlaySysex(Bit8u *sysex, Bitu len) {
  229 ++ if (renderInThread) {
  230 ++ service->playSysexAt(sysex, len, getMidiEventTimestamp());
  231 ++ } else {
  232 ++ service->playSysex(sysex, len);
  233 ++ }
  234 ++}
  235 ++
  236 ++void MidiHandler_mt32::mixerCallBack(Bitu len) {
  237 ++ MidiHandler_mt32::GetInstance().handleMixerCallBack(len);
  238 ++}
  239 ++
  240 ++int MidiHandler_mt32::processingThread(void *) {
  241 ++ MidiHandler_mt32::GetInstance().renderingLoop();
  242 ++ return 0;
  243 ++}
  244 ++
  245 ++void MidiHandler_mt32::makeROMPathName(char pathName[], const char romDir[], const char fileName[], bool addPathSeparator) {
  246 ++ strcpy(pathName, romDir);
  247 ++ if (addPathSeparator) {
  248 ++ strcat(pathName, "/");
  249 ++ }
  250 ++ strcat(pathName, fileName);
  251 ++}
  252 ++
  253 ++mt32emu_report_handler_i MidiHandler_mt32::getReportHandlerInterface() {
  254 ++ class ReportHandler {
  255 ++ public:
  256 ++ static mt32emu_report_handler_version getReportHandlerVersionID(mt32emu_report_handler_i) {
  257 ++ return MT32EMU_REPORT_HANDLER_VERSION_0;
  258 ++ }
  259 ++
  260 ++ static void printDebug(void *instance_data, const char *fmt, va_list list) {
  261 ++ MidiHandler_mt32 &midiHandler_mt32 = *(MidiHandler_mt32 *)instance_data;
  262 ++ if (midiHandler_mt32.noise) {
  263 ++ char s[1024];
  264 ++ vsnprintf(s, 1023, fmt, list);
  265 ++ LOG_MSG("MT32: %s", s);
  266 ++ }
  267 ++ }
  268 ++
  269 ++ static void onErrorControlROM(void *) {
  270 ++ LOG_MSG("MT32: Couldn't open Control ROM file");
  271 ++ }
  272 ++
  273 ++ static void onErrorPCMROM(void *) {
  274 ++ LOG_MSG("MT32: Couldn't open PCM ROM file");
  275 ++ }
  276 ++
  277 ++ static void showLCDMessage(void *, const char *message) {
  278 ++ LOG_MSG("MT32: LCD-Message: %s", message);
  279 ++ }
  280 ++ };
  281 ++
  282 ++ static const mt32emu_report_handler_i_v0 REPORT_HANDLER_V0_IMPL = {
  283 ++ ReportHandler::getReportHandlerVersionID,
  284 ++ ReportHandler::printDebug,
  285 ++ ReportHandler::onErrorControlROM,
  286 ++ ReportHandler::onErrorPCMROM,
  287 ++ ReportHandler::showLCDMessage
  288 ++ };
  289 ++
  290 ++ static const mt32emu_report_handler_i REPORT_HANDLER_I = { &REPORT_HANDLER_V0_IMPL };
  291 ++
  292 ++ return REPORT_HANDLER_I;
  293 ++}
  294 ++
  295 ++MidiHandler_mt32::MidiHandler_mt32() : open(false), chan(NULL), service(NULL), thread(NULL) {
  296 ++}
  297 ++
  298 ++MidiHandler_mt32::~MidiHandler_mt32() {
  299 ++ Close();
  300 ++}
  301 ++
  302 ++void MidiHandler_mt32::handleMixerCallBack(Bitu len) {
  303 ++ if (renderInThread) {
  304 ++ while (renderPos == playPos) {
  305 ++ SDL_LockMutex(lock);
  306 ++ SDL_CondWait(framesInBufferChanged, lock);
  307 ++ SDL_UnlockMutex(lock);
  308 ++ if (stopProcessing) return;
  309 ++ }
  310 ++ Bitu renderPosSnap = renderPos;
  311 ++ Bitu playPosSnap = playPos;
  312 ++ Bitu samplesReady = (renderPosSnap < playPosSnap) ? audioBufferSize - playPosSnap : renderPosSnap - playPosSnap;
  313 ++ if (len > (samplesReady >> 1)) {
  314 ++ len = samplesReady >> 1;
  315 ++ }
  316 ++ chan->AddSamples_s16(len, audioBuffer + playPosSnap);
  317 ++ playPosSnap += (len << 1);
  318 ++ while (audioBufferSize <= playPosSnap) {
  319 ++ playPosSnap -= audioBufferSize;
  320 ++ playedBuffers++;
  321 ++ }
  322 ++ playPos = playPosSnap;
  323 ++ renderPosSnap = renderPos;
  324 ++ const Bitu samplesFree = (renderPosSnap < playPosSnap) ? playPosSnap - renderPosSnap : audioBufferSize + playPosSnap - renderPosSnap;
  325 ++ if (minimumRenderFrames <= (samplesFree >> 1)) {
  326 ++ SDL_LockMutex(lock);
  327 ++ SDL_CondSignal(framesInBufferChanged);
  328 ++ SDL_UnlockMutex(lock);
  329 ++ }
  330 ++ } else {
  331 ++ service->renderBit16s((Bit16s *)MixTemp, len);
  332 ++ chan->AddSamples_s16(len, (Bit16s *)MixTemp);
  333 ++ }
  334 ++}
  335 ++
  336 ++void MidiHandler_mt32::renderingLoop() {
  337 ++ while (!stopProcessing) {
  338 ++ const Bitu renderPosSnap = renderPos;
  339 ++ const Bitu playPosSnap = playPos;
  340 ++ Bitu samplesToRender;
  341 ++ if (renderPosSnap < playPosSnap) {
  342 ++ samplesToRender = playPosSnap - renderPosSnap - 2;
  343 ++ } else {
  344 ++ samplesToRender = audioBufferSize - renderPosSnap;
  345 ++ if (playPosSnap == 0) samplesToRender -= 2;
  346 ++ }
  347 ++ Bitu framesToRender = samplesToRender >> 1;
  348 ++ if ((framesToRender == 0) || ((framesToRender < minimumRenderFrames) && (renderPosSnap < playPosSnap))) {
  349 ++ SDL_LockMutex(lock);
  350 ++ SDL_CondWait(framesInBufferChanged, lock);
  351 ++ SDL_UnlockMutex(lock);
  352 ++ } else {
  353 ++ service->renderBit16s(audioBuffer + renderPosSnap, framesToRender);
  354 ++ renderPos = (renderPosSnap + samplesToRender) % audioBufferSize;
  355 ++ if (renderPosSnap == playPos) {
  356 ++ SDL_LockMutex(lock);
  357 ++ SDL_CondSignal(framesInBufferChanged);
  358 ++ SDL_UnlockMutex(lock);
  359 ++ }
  360 ++ }
  361 ++ }
  362 ++}
  363 +diff --git a/src/gui/midi_mt32.h b/src/gui/midi_mt32.h
  364 +new file mode 100644
  365 +index 00000000..eb32729f
  366 +--- /dev/null
  367 ++++ b/src/gui/midi_mt32.h
  368 +@@ -0,0 +1,55 @@
  369 ++#ifndef DOSBOX_MIDI_MT32_H
  370 ++#define DOSBOX_MIDI_MT32_H
  371 ++
  372 ++#include "mixer.h"
  373 ++
  374 ++#define MT32EMU_API_TYPE 3
  375 ++#include <mt32emu/mt32emu.h>
  376 ++
  377 ++#if MT32EMU_VERSION_MAJOR != 2 || MT32EMU_VERSION_MINOR < 1
  378 ++#error Incompatible mt32emu library version
  379 ++#endif
  380 ++
  381 ++struct SDL_Thread;
  382 ++
  383 ++class MidiHandler_mt32 : public MidiHandler {
  384 ++public:
  385 ++ static MidiHandler_mt32 &GetInstance(void);
  386 ++
  387 ++ const char *GetName(void);
  388 ++ bool Open(const char *conf);
  389 ++ void Close(void);
  390 ++ void PlayMsg(Bit8u *msg);
  391 ++ void PlaySysex(Bit8u *sysex, Bitu len);
  392 ++
  393 ++private:
  394 ++ MixerChannel *chan;
  395 ++ MT32Emu::Service *service;
  396 ++ SDL_Thread *thread;
  397 ++ SDL_mutex *lock;
  398 ++ SDL_cond *framesInBufferChanged;
  399 ++ Bit16s *audioBuffer;
  400 ++ Bitu audioBufferSize;
  401 ++ Bitu framesPerAudioBuffer;
  402 ++ Bitu minimumRenderFrames;
  403 ++ volatile Bitu renderPos, playPos, playedBuffers;
  404 ++ volatile bool stopProcessing;
  405 ++ bool open, noise, renderInThread;
  406 ++
  407 ++ static void mixerCallBack(Bitu len);
  408 ++ static int processingThread(void *);
  409 ++ static void makeROMPathName(char pathName[], const char romDir[], const char fileName[], bool addPathSeparator);
  410 ++ static mt32emu_report_handler_i getReportHandlerInterface();
  411 ++
  412 ++ MidiHandler_mt32();
  413 ++ ~MidiHandler_mt32();
  414 ++
  415 ++ Bit32u inline getMidiEventTimestamp() {
  416 ++ return service->convertOutputToSynthTimestamp(Bit32u(playedBuffers * framesPerAudioBuffer + (playPos >> 1)));
  417 ++ }
  418 ++
  419 ++ void handleMixerCallBack(Bitu len);
  420 ++ void renderingLoop();
  421 ++};
  422 ++
  423 ++#endif /* DOSBOX_MIDI_MT32_H */
  424 +diff --git a/src/mt32options.h b/src/mt32options.h
  425 +new file mode 100644
  426 +index 00000000..6292f0b6
  427 +--- /dev/null
  428 ++++ b/src/mt32options.h
  429 +@@ -0,0 +1,109 @@
  430 ++Pstring = secprop->Add_string("mt32.romdir",Property::Changeable::WhenIdle,"");
  431 ++Pstring->Set_help("Name of the directory where MT-32 Control and PCM ROM files can be found. Emulation requires these files to work.\n"
  432 ++ " Accepted file names are as follows:\n"
  433 ++ " MT32_CONTROL.ROM or CM32L_CONTROL.ROM - control ROM file.\n"
  434 ++ " MT32_PCM.ROM or CM32L_PCM.ROM - PCM ROM file.");
  435 ++
  436 ++Pbool = secprop->Add_bool("mt32.reverse.stereo",Property::Changeable::WhenIdle,false);
  437 ++Pbool->Set_help("Reverse stereo channels for MT-32 output");
  438 ++
  439 ++Pbool = secprop->Add_bool("mt32.verbose",Property::Changeable::WhenIdle,false);
  440 ++Pbool->Set_help("MT-32 debug logging");
  441 ++
  442 ++Pbool = secprop->Add_bool("mt32.thread",Property::Changeable::WhenIdle,false);
  443 ++Pbool->Set_help("MT-32 rendering in separate thread");
  444 ++
  445 ++Pint = secprop->Add_int("mt32.chunk",Property::Changeable::WhenIdle,16);
  446 ++Pint->SetMinMax(2,100);
  447 ++Pint->Set_help("Minimum milliseconds of data to render at once. (min 2, max 100)\n"
  448 ++ "Increasing this value reduces rendering overhead which may improve performance but also increases audio lag.\n"
  449 ++ "Valid for rendering in separate thread only.");
  450 ++
  451 ++Pint = secprop->Add_int("mt32.prebuffer",Property::Changeable::WhenIdle,32);
  452 ++Pint->SetMinMax(3,200);
  453 ++Pint->Set_help("How many milliseconds of data to render ahead. (min 3, max 200)\n"
  454 ++ "Increasing this value may help to avoid underruns but also increases audio lag.\n"
  455 ++ "Cannot be set less than or equal to mt32.chunk value.\n"
  456 ++ "Valid for rendering in separate thread only.");
  457 ++
  458 ++Pint = secprop->Add_int("mt32.partials",Property::Changeable::WhenIdle,32);
  459 ++Pint->SetMinMax(8,256);
  460 ++Pint->Set_help("The maximum number of partials playing simultaneously. (min 8, max 256");
  461 ++
  462 ++const char *mt32DACModes[] = {"0", "1", "2", "3",0};
  463 ++Pint = secprop->Add_int("mt32.dac",Property::Changeable::WhenIdle,0);
  464 ++Pint->Set_values(mt32DACModes);
  465 ++Pint->Set_help("MT-32 DAC input emulation mode\n"
  466 ++ "Nice = 0 - default\n"
  467 ++ "Produces samples at double the volume, without tricks.\n"
  468 ++ "Higher quality than the real devices\n\n"
  469 ++
  470 ++ "Pure = 1\n"
  471 ++ "Produces samples that exactly match the bits output from the emulated LA32.\n"
  472 ++ "Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range)\n"
  473 ++ "Much less likely to overdrive than any other mode.\n"
  474 ++ "Half the volume of any of the other modes.\n"
  475 ++ "Perfect for developers while debugging :)\n\n"
  476 ++
  477 ++ "GENERATION1 = 2\n"
  478 ++ "Re-orders the LA32 output bits as in early generation MT-32s (according to Wikipedia).\n"
  479 ++ "Bit order at DAC (where each number represents the original LA32 output bit number, and XX means the bit is always low):\n"
  480 ++ "15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 XX\n\n"
  481 ++
  482 ++ "GENERATION2 = 3\n"
  483 ++ "Re-orders the LA32 output bits as in later generations (personally confirmed on my CM-32L - KG).\n"
  484 ++ "Bit order at DAC (where each number represents the original LA32 output bit number):\n"
  485 ++ "15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 14");
  486 ++
  487 ++const char *mt32analogModes[] = {"0", "1", "2", "3",0};
  488 ++Pint = secprop->Add_int("mt32.analog",Property::Changeable::WhenIdle,2);
  489 ++Pint->Set_values(mt32analogModes);
  490 ++Pint->Set_help("MT-32 analogue output emulation mode\n"
  491 ++ "Digital = 0\n"
  492 ++ "Only digital path is emulated. The output samples correspond to the digital output signal appeared at the DAC entrance.\n"
  493 ++ "Fastest mode.\n\n"
  494 ++
  495 ++ "Coarse = 1\n"
  496 ++ "Coarse emulation of LPF circuit. High frequencies are boosted, sample rate remains unchanged.\n"
  497 ++ "A bit better sounding but also a bit slower.\n\n"
  498 ++
  499 ++ "Accurate = 2 - default\n"
  500 ++ "Finer emulation of LPF circuit. Output signal is upsampled to 48 kHz to allow emulation of audible mirror spectra above 16 kHz,\n"
  501 ++ "which is passed through the LPF circuit without significant attenuation.\n"
  502 ++ "Sounding is closer to the analog output from real hardware but also slower than the modes 0 and 1.\n\n"
  503 ++
  504 ++ "Oversampled = 3\n"
  505 ++ "Same as the default mode 2 but the output signal is 2x oversampled, i.e. the output sample rate is 96 kHz.\n"
  506 ++ "Even slower than all the other modes but better retains highest frequencies while further resampled in DOSBox mixer.");
  507 ++
  508 ++const char *mt32reverbModes[] = {"0", "1", "2", "3", "auto",0};
  509 ++Pstring = secprop->Add_string("mt32.reverb.mode",Property::Changeable::WhenIdle,"auto");
  510 ++Pstring->Set_values(mt32reverbModes);
  511 ++Pstring->Set_help("MT-32 reverb mode");
  512 ++
  513 ++const char *mt32reverbTimes[] = {"0", "1", "2", "3", "4", "5", "6", "7",0};
  514 ++Pint = secprop->Add_int("mt32.reverb.time",Property::Changeable::WhenIdle,5);
  515 ++Pint->Set_values(mt32reverbTimes);
  516 ++Pint->Set_help("MT-32 reverb decaying time");
  517 ++
  518 ++const char *mt32reverbLevels[] = {"0", "1", "2", "3", "4", "5", "6", "7",0};
  519 ++Pint = secprop->Add_int("mt32.reverb.level",Property::Changeable::WhenIdle,3);
  520 ++Pint->Set_values(mt32reverbLevels);
  521 ++Pint->Set_help("MT-32 reverb level");
  522 ++
  523 ++Pint = secprop->Add_int("mt32.rate", Property::Changeable::WhenIdle, 44100);
  524 ++Pint->Set_values(rates);
  525 ++Pint->Set_help("Sample rate of MT-32 emulation.");
  526 ++
  527 ++const char *mt32srcQuality[] = {"0", "1", "2", "3",0};
  528 ++Pint = secprop->Add_int("mt32.src.quality", Property::Changeable::WhenIdle, 2);
  529 ++Pint->Set_values(mt32srcQuality);
  530 ++Pint->Set_help("MT-32 sample rate conversion quality\n"
  531 ++ "Value '0' is for the fastest conversion, value '3' provides for the best conversion quality. Default is 2.");
  532 ++
  533 ++Pbool = secprop->Add_bool("mt32.niceampramp", Property::Changeable::WhenIdle, true);
  534 ++Pbool->Set_help("Toggles \"Nice Amp Ramp\" mode that improves amplitude ramp for sustaining instruments.\n"
  535 ++ "Quick changes of volume or expression on a MIDI channel may result in amp jumps on real hardware.\n"
  536 ++ "When \"Nice Amp Ramp\" mode is enabled, amp changes gradually instead.\n"
  537 ++ "Otherwise, the emulation accuracy is preserved.\n"
  538 ++ "Default is true.");
Please register or login to post a comment